rust 为什么我不能比较两个不同类型的整数?

pbpqsu0x  于 2022-12-19  发布在  其他
关注(0)|答案(3)|浏览(130)
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没有为不同类型的整数实现。同样的情况发生在f32f64之间,对于PartialOrd也是如此。这有什么原因吗?它是否打算在Rust的未来版本中实现?

ogsagwnx

ogsagwnx1#

在Rust中有许多整数类型:

  • x一个锰一个x、x一个锰一个x、x一个锰二个n一个x、x一个锰三个n一个x和x一个锰四个n一个x,
  • x一米五氮一x、x一米六氮一x、x一米七氮一x、x一米八氮一x和x一米九氮一x,
  • isize
  • 一米一米一。

在某些情况下,混合算术或比较将具有明显的实现,因为无损转换在一个方向上是可能的:

  • 如果x < y,则i<x>总是可以被转换为i<y>
  • 如果x < yu<x>总是可以被转换为u<y>
  • 如果x < y,则u<x>始终可以转换为i<y>

但是,有些转换并不明显或不可移植:

  • 无论xy各自的值是什么都不能将i<x>转换为u<y>
  • isizeusize在任何地方都具有平台特定的大小,小到16位,大到64位。

因此,由于Rust对溢出或下溢不感兴趣,因此不太可能实现 * 任意 * 混合算术或比较。
可以实现受限子集,但随后会产生两个问题:

  • 受限子集不是不符合人体工程学吗?
  • 使用混合类型不是设计问题的标志吗?同样,数量应该有单位,数量应该有一个“已知的大小”。
i2loujxw

i2loujxw2#

这是预期行为- Rust是一种强类型语言,它不会在不同类型的整数之间执行隐式强制转换。
我不认为这种情况在未来会改变,因为这将是一个众所周知的难以发现的错误的潜在来源。
你需要明确地表达并注意数字强制转换的潜在警告(截断等):

let x: i32 = 4;
let y: i16 = 4;

println!("{}", x == y as i32);
arknldoa

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.可能是有效的,尽管非常主观且难以证明。

  • 这是可以测试的,虽然我不认为这会是一个问题:
  • 标准库是预编译
  • 在标准库中已经有数千个trait实现(例如仅在U8上就有422个
  • 在整数类型的组合上实现trait是有先例的:自、试自、Shl(分配)、Shr(分配)

从我所能找到的论据来看,我目前认为允许比较不同大小的整数对Rust来说是一个积极的选择。
orlp已经在num-ord crate中实现了这些算法

相关问题