问题
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?
回答1:
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.
回答2:
As already mentioned, converting from a 64-bit value to a usize
might cause truncation; you might lose data when a usize
is 16 or 32 bits.
Fallable conversions are covered by the TryFrom trait, available in Rust 1.34:
use std::convert::TryFrom;
fn main() {
let a: u64 = 5;
let b = a as usize;
let b = usize::try_from(a);
}
See also:
- How do I convert a usize to a u32 using TryFrom?
来源:https://stackoverflow.com/questions/47786322/why-is-type-conversion-from-u64-to-usize-allowed-using-as-but-not-from