Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Both languages will insert implicit casts between primitive types whenever it is safe to do so, and require explicit casts otherwise.

I think Rust always requires explicit casts. It's a bit annoying tbh - especially for array indexing - indexing with a u8, u16 or u32 should always be fine but you still have to do `as usize`.



I forgot rust doesn't upcast numbers, but I was mostly thinking about https://doc.rust-lang.org/nomicon/coercions.html


It is annoying since in relationship to bounds checking, we could write a non-surprising automatic conversion - given array length type and index type, we'd need to cast to the bigger of the two and make the bound check. But it doesn't mesh well with the fact that all but primitive indexing are implemented in the library, and is not built in.


I guess Index could be implemented on some type for both u32 and usize and then upcasting a u32 would produce ambiguity.


This is indeed the main reason array[42u32] isn't supported today: implementing Index on both usize and u32 would make array[42] ambiguous for the type system, it needs to unify the {integer} literal and some implementor of Index, but there are now two possibilities. This would be a breaking change.


You can also write `as _` most of the time.

Edit: But as the reply below says, please don't.


Which is not recommended, because it could silently truncate if _ is a smaller type, or later becomes one as the code is edited over time.

Much better to use ::from() or into() for numeric type conversions, which are only implemented for types that are guaranteed to fit the value, unless you know that truncation is perfectly fine behavior in a particular instance... which it rarely actually is.


Annoyingly, .into() is mostly useless for array indexing, since even when you're compiling for a 64-bit machine (and thus x[my_u32.into()] would be perfectly fine) it's only defined for up to u16 (because you might want the same multi-megabyte code to also work in a tiny microcontroller). If you don't want to use x[my_u32 as usize], you are forced to use x[my_u32.try_into().unwrap()], or just use usize everywhere (of course, you could also use traits to create your own .into_usize() and use it everywhere).


It's fine for increasing width - e.g. u8 -> u16.

There's a lint you can enable to detct truncation - https://rust-lang.github.io/rust-clippy/master/#cast_possibl...


Ah, sorry; I forgot that `as` let you cast bigger types to smaller types. Yeah, that does make the tragically verbose `.into()` the safer option, unless you know that the type you're casting into will always be bigger.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: