自从创建这个答案以来,决定了 https://github.com/rust-lang/rust/pull/51564实施TryFrom<usize>
无论当前平台如何,始终考虑到失败的可能性。原始代码现在可以在 Rust 1.34 中成功编译。
原答案
having TryFrom<usize>
for u32
取决于有From<usize>
for u32
,这对我来说有点奇怪
这是因为有一个全面的实施TryFrom
对于任何实现From
:
impl<T, U> TryFrom<U> for T
where
T: From<U>,
{
type Error = !;
}
正如您所提到的,由于 Rust 支持本机整数长度为 16、32 或 64 位的平台,因此具有这样的实现From
/ Into
在其中一些平台上不会是无损的。
出现此错误是因为没有直接实现TryFrom
/ TryInto
对于这些类型。这是因为这些特征的用户更喜欢在适合平台的情况下实现万无一失(type Error = !
).
有一个单独的跟踪问题 49415 https://github.com/rust-lang/rust/issues/49415专门来决定这个问题。
我认为我可以编写自己的函数来进行转换
是的,这就是你应该做的。像这段未经测试的代码:
use std::u32;
struct SomeError;
// usize is a u16 or u32, which always fits in a u32
#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
fn my_thing(a: usize) -> Result<u32, SomeError> {
Ok(a as u32)
}
// usize is a u64, which might be too big
#[cfg(target_pointer_width = "64")]
fn my_thing(a: usize) -> Result<u32, SomeError> {
if a > u32::MAX as usize {
Err(SomeError)
} else {
Ok(a as u32)
}
}
如果 Rust 没有一些惯用的方法来进行这种转换,我会感到惊讶。usize
and u32
毕竟是两种基本类型。
问题是usize
并不是真正的“基本”类型,因为它会根据目标平台改变大小。得到这个正确的、高性能的and符合人体工程学并不容易。