let x: i32 = 4;
let y: i16 = 4;
println!("{}", x == y);
编译上面的代码段时,编译器打印以下错误:
error[E0308]: mismatched types
--> src/main.rs:5:25
|
5 | println!("{}", x == y);
| ^ expected i32, found i16
看起来PartialEq
没有为不同类型的整数实现。同样的情况发生在f32
和f64
之间,对于PartialOrd
也是如此。这有什么原因吗?它是否打算在Rust的未来版本中实现?
3条答案
按热度按时间ogsagwnx1#
在Rust中有许多整数类型:
isize
,在某些情况下,混合算术或比较将具有明显的实现,因为无损转换在一个方向上是可能的:
x < y
,则i<x>
总是可以被转换为i<y>
,x < y
,u<x>
总是可以被转换为u<y>
,x < y
,则u<x>
始终可以转换为i<y>
。但是,有些转换并不明显或不可移植:
x
和y
各自的值是什么都不能将i<x>
转换为u<y>
,isize
和usize
在任何地方都具有平台特定的大小,小到16位,大到64位。因此,由于Rust对溢出或下溢不感兴趣,因此不太可能实现 * 任意 * 混合算术或比较。
可以实现受限子集,但随后会产生两个问题:
i2loujxw2#
这是预期行为- Rust是一种强类型语言,它不会在不同类型的整数之间执行隐式强制转换。
我不认为这种情况在未来会改变,因为这将是一个众所周知的难以发现的错误的潜在来源。
你需要明确地表达并注意数字强制转换的潜在警告(截断等):
arknldoa3#
编辑:我提交了an RFC,在许多错误的答案中,thomcc提供了以下有价值的评论:
我认为推理问题使它无法启动。我希望它能破坏所有rust代码,其中一个数值类型的变量与一个数字文本进行比较(例如,a == 0)。我们在std::simd中遇到过类似的(但不那么极端)问题,它破坏了大量代码(甚至是根本不关心simd的代码)。
类型推断不应受此更改的影响,因为PartialOrd和PartialEq上的泛型参数默认为Self。因此,像1 == 1_u8这样的表达式将通过正确推断第一个文本为u8而继续工作。
遗憾的是,我不相信类型推理是这样工作的,至少目前不是这样(我的理解是,至少要像一些人期望的那样扩展它来处理默认值,需要一些不平凡的设计工作)。
这就是为什么不同类型的整数不能比较的真实的原因
我研究了一下,找到了几个参数。比较不同大小的整数...
1.需要隐式强制转换,这很容易被误用并导致错误
1.难以正确定义/在边缘情况下可能产生意外结果
1.需要非平凡逻辑(例如,符号检查或零扩展),并且可能对整数类型运算具有不可接受的性能影响
1.可能暗示代码中存在设计问题
1.为所有12个整数类型的每个组合添加(部分)Eq/Ord实现是264个实现,这可能影响编译时间
答复:
1.没有实际意义:对于不同大小的整数,会有显式的Eq/Ord实现。
1.也是没有实际意义的,因为排序的数学定义是明确的和直观的。
1.在我的Intel i5- 8600 k上,带有符号检查的
u64 < i64
检查比本机u64 < u64
检查慢0.1纳秒,这可以忽略不计。1.可能是有效的,尽管非常主观且难以证明。
从我所能找到的论据来看,我目前认为允许比较不同大小的整数对Rust来说是一个积极的选择。
orlp已经在num-ord crate中实现了这些算法