For conversion between numeric types the current policy is that
From must never fail, for any platform, not just on the target platform. It’s a nice idea, and I think it’s beneficial for portability between 32-bit and 64-bit platforms.
However, I think it goes too far in requiring support for 16-bit and hypothetical 128-bit platforms as well, because this has a cost of promoting dangerous use of
as for conversions that are common on 32-bit and 64-bit platforms.
IMHO the policy doesn’t help portability, because
as does not avoid the problem
Into was meant to avoid, it only hides these types of bugs from the compiler. I find
as to be C-like dangerous, and I would prefer to never use
as in my code.
It causes broken code on 16-bit
For example, if I’m not allowed to use
u32.into() usize, then I’ll have to use
u32 as usize instead, even if I require conversion to never truncate. Lack of this
into() implementation does not make my code work on 16-bit platforms. It makes Rust compile code designed with invalid assumptions without a warning.
I think errors about missing
.into() implementations would help supporting 16-bit platforms — they’d prevent broken programs from running and corrupting data, and make the compiler point out places where the code needs to be fixed first.
Prevents libraries from changing exposed types
The same risk that applies for conversions between
usize on various platforms, also applies to conversions between program’s types and libraries’ types.
I may be forced to use
as casts that are not truncating in the current version of a library, but when the library changes sizes of its types, the
as cast will continue to compile, but it’ll start silently corrupting data. When the library is an FFI, it becomes a safety problem.
OTOH if I could use
.into() everywhere, then such incompatible change would be caught by the compiler (and only if my usage was actually incompatible).
I’m forced to support a platform that doesn’t even exist
Lack of conversion from
u64 causes problems for me on real platforms today. I’m unhappy about having to use
as that is currently dangerous and not future-proof, only because
.into() is meant to seamlessly support hypothetical future platform.
I prefer to fix compile errors when porting code to a new platform, than have to use dangerous (and non-portable) casts on platforms that I currently use.
- Add conversion from
u64on all current platforms. Leave it unimplemented on a future 128-bit platform.
- Add conversion from
usizeon 32-bit and wider platforms. Leave it unimplemented on 16-bit platforms.
This is limited and keeps the current requirement that code must compile on both 32-bit and 64-bit platforms.
Discussion Pre-RFC: a vision for platform/architecture/configuration-specific APIs mentions “compatibility targets”.
- Implement all conversions that are lossless for all compatibility targets (and don’t restrict conversions because they’re lossy on platforms that aren’t the targets).