Why is Rust's usize to u128 conversion considered failable?

Viewed 2305

Take a look:

use std::convert::{From, TryFrom};

fn main() {
  let size: usize = 42;
  let good: u128  = u128::try_from(size).unwrap(); // works fine
  let bad:  u128  = u128::from(size);              // doesn't compile!
}

As far as I know, usize is an integral type and those are never larger than 128 bits. Therefore, I see no way the usize -> u128 conversion can fail. So, why doesn't u128 implement From<usize>?

Update: Rust's documentation says:

From T for U implies Into U for T

Though usize -> u128 seems fine, u128 -> usize doesn't. OK, but why isn't Into<u128> implemented for usize instead?

2 Answers

Though usize -> u128 seems fine, u128 -> usize doesn't. OK, but why isn't Into implemented for usize instead?

Because while usize is guaranteed to always ever be at least 16 bits as far as Rust is concerned, it's not guaranteed to always ever be at most 64 bits.

It seems unlikely to ever be useful but technically nothing precludes 256 bits pointers, and since usize is guaranteed to be pointer-sized it would make the usize -> u128 conversion failible.

The document of From trait says

Note: This trait must not fail. If the conversion can fail, use TryFrom.

Since you will not know whether usize can hold a u16/u32/u64/u128 value(depending on your compile target), all of these primitive types implement TryFrom instead of From.

In Rust document, implies means when you have a type implements From, the compiler will give you an Into for free(note that the opposite is not true). The same idea applies to TryFrom and TryInto.So the following code will work as expected.

use std::convert::{TryFrom,TryInto};

fn main() {
  let size: usize = 42;
  let good: u128  = u128::try_from(size).unwrap();
  let doublegood:usize = good.try_into().unwrap();
}
Related