为什么允许使用`as`而不是`From`从u64到usize的类型转换?

Kağ*_*yal 13 numbers type-conversion rust

使用'as'编译的第一次转换,但使用'From'特性的第二次转换不会:

fn main() {
    let a: u64 = 5;
    let b = a as usize;
    let b = usize::from(a);
}
Run Code Online (Sandbox Code Playgroud)

使用Rust 1.22.1我收到以下错误:

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`
Run Code Online (Sandbox Code Playgroud)

当我更换u64u8,没有更多的错误.从错误消息中,我了解该From特征仅针对u8其他整数类型实现,而不是针对其他整数类型实现.

如果有充分的理由,为什么不应该使用'as'的转换也不能编译?

Evi*_*Tak 13

as演员与From转换从根本上不同.From转换是" 简单而安全的",而as转换则纯粹是"安全的".在考虑数字类型时,From只有在保证输出相同的情况下才存在转换,即不会丢失信息(没有截断或地板或精度损失).as但是,演员没有这个限制.

引用文档,

[ usize] 的大小是"引用内存中任何位置所需的字节数.例如,在32位目标上,这是4个字节,在64位目标上,这是8个字节."

由于大小取决于目标体系结构,并且在编译之前无法确定,因此无法保证From数字类型之间的转换usize是可能的.一个as演员,但是,总是会被列出的规则进行操作这里.

例如,在32位系统上,usize相当于u32.由于a usize小于a u64,因此在将a转换u64为a 时可能会丢失信息(截断)usize,因此From不能存在转换.然而,a的大小usize总是保证是8位或更高和u8usize From转换将总是存在的.

  • 有了这个理解,我尝试了 `println!("{}", 500u16 as u8);` 并得到了 244。我认为“安全”在这里意味着我们不能弄乱内存,但我们仍然可能最终一个完全错误的数字。由于我不愿从数学的角度将其称为“安全”,因此我建议将“强制转换纯粹是“安全的”替换为“强制转换仅是“内存安全”,但在您的答案中可能会改变值左右。这样,未来的读者将对他们仍然可能产生的潜在错误发出更强烈的警告,并避免错误的“安全”感。 (2认同)
  • [rust 参考:不安全](https://doc.rust-lang.org/stable/reference/unsafety.html):“不安全操作是那些可能违反 Rust 静态语义的内存安全保证的操作。” (2认同)

She*_*ter 6

如前所述,从 64 位值转换为 ausize可能会导致截断;当 ausize为 16 或 32 位时,您可能会丢失数据。

在 Rust 1.34 中可用的TryFromtrait涵盖了可失败的转换:

use std::convert::TryFrom;

fn main() {
    let a: u64 = 5;
    let b = a as usize;
    let b = usize::try_from(a);
}
Run Code Online (Sandbox Code Playgroud)

也可以看看:

  • 但令人惊讶的是,你不能(目前)在相反的情况下使用 `TryFrom`:https://github.com/rust-lang/rust/issues/49415 (3认同)