为什么在这种情况下Rust不能选择正确的特征?

问题描述 投票:5回答:1

请考虑以下代码:

use std::ops::Add;

trait Trait
    where Self::Assoc: Add<Self::Assoc, Output=Self::Assoc>
                     + for <'a> Add<&'a Self::Assoc, Output=Self::Assoc>
{
    type Assoc;
    fn get(&self) -> Self::Assoc;
}

fn add1<T: Trait>(x: T, y: T) -> T::Assoc {
    x.get() + y.get()
}

无法编译为:

error[E0308]: mismatched types
  --> src/lib.rs:12:15
   |
12 |     x.get() + y.get()
   |               ^^^^^^^
   |               |
   |               expected reference, found associated type
   |               help: consider borrowing here: `&y.get()`
   |
   = note:    expected reference `&<T as Trait>::Assoc`
           found associated type `<T as Trait>::Assoc`

我可以通过明确指定要使用的特征来解决此问题:

fn add2<T: Trait>(x: T, y: T) -> T::Assoc {
    <T::Assoc as Add<T::Assoc>>::add(x.get(), y.get())
}

但是我想知道:为什么会这样?另外,还有其他更紧凑的解决方法吗?

请注意,特征范围的顺序很重要。如果我将其更改为:

    where Self::Assoc: for <'a> Add<&'a Self::Assoc, Output=Self::Assoc>
                     + Add<Self::Assoc, Output=Self::Assoc>

...然后add1可以正常编译,但是失败:

fn add3<T: Trait>(x: T, y: T) -> T::Assoc {
    x.get() + &y.get()
}

Link to playground

rust traits
1个回答
3
投票

方法分派基于方法的接收者(其self),并且不考虑任何其他参数。一旦编译器通过应用Addx找到了auto-ref rules的实例,它将不会尝试查找任何其他实现-即使方法参数未进行类型检查。

由于implementation detail,所以顺序很重要。似乎您声明边界的顺序会影响算法搜索匹配方法的顺序。


参见:

© www.soinside.com 2019 - 2024. All rights reserved.