I like how this highlights the pitfalls of using `as` to cast between types. The article says to prefer using `try_into()` instead of `as`, which is a good suggestion when available, but `as` lets you cast between floats and ints, while `try_into` is not implemented for these type conversions. I think the reasoning is it is unclear `try_into` should fail when it had to round a decimal number down or only when the float was something above the bounds or `NaN`. Regardless it seems like a missed opportunity in the standard library.
For floats you do end up having to use `as` which is unfortunate. However the amount of things that can go wrong is too vast for `TryInto`.
The article also says "If you upcast u32 to u64, you can use the keyword as". I would avoid this. In these cases you can just use `.into()`. This is infallible and will raise errors if refactoring causes that conversion to no longer be infallible. (In which case you can fix it or migrate to `.try_into()`)
I think the floating point case is similar. Keep `as` super suspicious, but sometimes you do want to do it.
Also, in generic code write try_into() and don't sweat it, for the cases which can't actually fail in the monomorphised results the error type is Infallible, that's an Empty Type (an enum with no variants, as distinct from a Zero Size Type which is a struct with no members) and so no error handling code is emitted.
The compiler can't even imagine what the code should look like, after all this type can't exist, does it fit in a register? How do we perform operations on it? If we try to actually realise an empty type by e.g. dereferencing a pointer to it that somebody gave us from a C API the Rust compiler will reject that as nonsense.
https://play.rust-lang.org/?version=stable&mode=debug&editio...