Rust 类型推断异常

Rust type inferencing oddity

我运行早些时候陷入了一个奇怪的境地。我写道:

if rand::random() < self.food_chance {...}

(self.food_chance 的类型是 f32)

我遇到类型推断错误:

   |
71 |             if rand::random() < self.food_chance {
   |                ^^^^^^^^^^^^ cannot infer type for `T`

但是这段代码可以编译

if self.food_chance > rand::random() {...}

我还在想。这种行为有原因吗? 这甚至是有意的行为吗?

我对类型推断理论了解一点,而且我知道大多数算法对 lhs/rhs 都是不可知的,所以我很想认为这是预期的行为,而不是直接的错误。

我试着四处搜索,但我从来没有找到任何接近这个的东西。

> 运算符是方法的糖分; partial_cmp method of the PartialOrd 特征。该方法以左侧作为 self 参数调用;这决定了使用 PartialOrd 的哪个实现。因为你可以为不同的类型实现 PartialOrd 特性,f32 作为右侧类型,所以 PartialOrd 的实现只有当左侧的类型是已知。 PartialOrd 的这种实现又决定了 rand::random.

所需的类型

这主要是因为 Rust 永远无法推断出接收者的类型。必须知道接收器的类型才能执行方法查找,并且由于

rand::random() < self.food_chance

相当于

std::cmp::PartialOrd::lt(&rand::random(), &self.food_chance);

接收者是左边的操作数。

表达式中

self.food_chance > rand::random()

另一方面,接收者是已知的,因此 Rust 可以执行方法查找。它只会找到 f32 作为接收者的单一实现,即 PartialOrd<f32>,然后它又决定了右侧的类型。如果有不同右侧类型的实现,那么 Rust 也无法在这种情况下推断类型。

要了解为什么 Rust 无法推断接收者,请查看how Rust's method lookup process works。第一步是根据接收者的类型构建候选类型列表。这显然只有在您已经知道接收器的类型时才有效。