请考虑以下代码:
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()
}
方法分派基于方法的接收者(其self
),并且不考虑任何其他参数。一旦编译器通过应用Add
为x
找到了auto-ref rules的实例,它将不会尝试查找任何其他实现-即使方法参数未进行类型检查。
由于implementation detail,所以顺序很重要。似乎您声明边界的顺序会影响算法搜索匹配方法的顺序。
参见: