【问题标题】:Rust type inferencing oddityRust 类型推断奇怪
【发布时间】:2019-04-27 06:57:25
【问题描述】:

我之前遇到了一个奇怪的情况。我写道:

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

self.food_chancef32 类型)

我得到一个类型推断错误:

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

但是这段代码可以编译

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

我想知道。这种行为有原因吗? 它甚至是预期的行为吗?

我对类型推断理论略知一二,而且我知道大多数算法对 lhs/rhs 是不可知的,所以我倾向于认为这是预期的行为,而不是直接导致错误。

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

【问题讨论】:

    标签: rust type-inference


    【解决方案1】:

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

    rand::random() < self.food_chance
    

    等价于

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

    接收者是左操作数。

    在表达式中

    self.food_chance > rand::random()
    

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

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

    【讨论】:

    • 您是否会知道这是语言的限制(无法以其他方式解决)还是仅仅是当前实现的限制?
    • @MatthieuM。当前的语言定义根本不包含推断接收者类型的过程。方法查找过程的定义(见答案中的链接)当然要求事先知道接收者的类型。如果我们想推断接收者的类型,我们需要为接收者未知的情况发明不同的方法查找语义。我想不出任何合理且一致的方式来为此定义语义。
    • 我认为平等对待所有论点应该是可能的;通过简单的名称查找(固有 + 可见特征)选择候选方法列表,然后对接收器和参数使用推断来查找可以匹配的候选方法,如果有任何歧义则拒绝。我不确定是否存在算法复杂性会爆炸的情况,使其几乎无法解决。
    • @MatthieuM。您可能可以使用这些语义定义一种语言,但它与 Rust 完全不同。
    • 我可能很天真,但我看不出这里有任何语义的区别;只是在推断类型上有所不同。
    【解决方案2】:

    &gt; 运算符是方法的糖; PartialOrd 特征的 partial_cmp 方法。该方法使用左侧作为self 参数调用;这决定了使用PartialOrd 的哪个实现。因为您可以使用 f32 作为右侧类型为不同类型实现 PartialOrd 特征,所以只有在左侧类型已知的情况下才能唯一确定 PartialOrd 的实现。 PartialOrd 的这种实现反过来又从 rand::random 确定所需的类型。

    【讨论】:

    • 您认为f32 作为右侧可能有不同的类型,而f32 作为左侧可能只有一种实现。这不是真的,你可以看到in this example。只有一个以f32 作为左侧的实现,但也只有一个以f32 作为右侧的实现,所以我看不出这个答案是如何解释不对称的。跨度>
    • 我的论点假设 OP 没有为 f32 手动实现 PartialOrd,在这种情况下 OP 应该提到这一点,因为它与问题相关。这是编译器能够推断类型的原因。我没有说明PartialOrd 的实现只能是一种,左侧是f32。但是,您的示例确实很好地证明了您的答案。
    猜你喜欢
    • 2016-02-29
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多