Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

rust - Why is type conversion from u64 to usize allowed using `as` but not `From`?

The first conversion using 'as' compiles, but the second one using the 'From' trait does not:

fn main() {
    let a: u64 = 5;
    let b = a as usize;
    let b = usize::from(a);
}

Using Rust 1.34.0, I get the following error:

error[E0277]: the trait bound `usize: std::convert::From<u64>` is not satisfied
 --> src/main.rs:4:13
  |
4 |     let b = usize::from(a);
  |             ^^^^^^^^^^^ the trait `std::convert::From<u64>` is not implemented for `usize`
  |
  = help: the following implementations were found:
            <usize as std::convert::From<bool>>
            <usize as std::convert::From<std::num::NonZeroUsize>>
            <usize as std::convert::From<u16>>
            <usize as std::convert::From<u8>>
  = note: required by `std::convert::From::from`

When I replace u64 with u8, there is no more error. From the error message, I understand that the From trait is implemented only for u8, but not for the other integer types.

If there is a good reason for that, then why shouldn't the conversion using 'as' should also fail to compile?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

as casts are fundamentally different from From conversions. From conversions are "simple and safe" whereas as casts are purely "safe". When considering numeric types, From conversions exist only when the output is guaranteed to be the same, i.e. there is no loss of information (no truncation or flooring or loss of precision). as casts, however, do not have this limitation.

Quoting the docs,

The size of [usize] is "how many bytes it takes to reference any location in memory. For example, on a 32 bit target, this is 4 bytes and on a 64 bit target, this is 8 bytes."

Since the size depends on the target architecture and cannot be determined before compilation, there is no guarantee that a From conversion between a numeric type and usize is possible. An as cast, however, will always operate by the rules listed here.

For instance, on a 32-bit system, usize is equivalent to u32. Since a usize is smaller than a u64, there can be loss of information (truncation) when converting a u64 into a usize and hence a From conversion cannot exist. However, the size of a usize is always guaranteed to be 8 bits or greater and a u8 to usize From conversion will always exist.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...