简短版: T 实现 Deref<T> 毫无意义,因此在解除对左侧的引用方面,方法调用和运算符调用的工作方式有所不同,因为 @987654324 @不与a.add(&b)完全一样。
加长版:
就获取引用而言,+ 运算符和 Add.add 的操作方式不同。
+ 运算符 通过引用本身获取两个操作数。 a + b 对于 A 和 B 各自类型的操作数要求有 Add<B, C> 的实现 A 并将产生一个类型为 C 的值。如前所述,a 和b 被引用;它会默默地自己制作这些引用;没有猜测。它们的工作原理如下:
let a = 1i;
let b = a + a; // this one works
let c = a + &a; // mismatched types: expected `int`, found `&int` (expected int, found &-ptr)
let d = &a + a; // binary operation `+` cannot be applied to type `&int`
let e = &a + &a; // binary operation `+` cannot be applied to type `&int`
在任何情况下都不会取消引用,因此狡猾的T: Deref<T> 要求不会破坏任何东西。
Add.add 通过引用获取这两个值。作为常规函数调用,它具有在必要时自动取消引用和引用左侧的能力。虽然右侧作为方法参数按原样传入,但左侧被尽可能地取消引用以找到所有可能由add 表示的方法。通常这很好,它会做你想做的事,但在这种情况下它不会,因为T(a 是哪个类型)实现了Deref<T>。所以取消引用得到了T。然后T,实现Deref<T>,取消引用T。更重要的是,T 实现了Deref<T>,因此取消了对T 的引用。它一直这样做,直到达到递归限制。真的,T 实现 Deref<T> 完全没有意义。
为了比较,下面是方法调用 add 工作原理的一些演示:
let a = 1i;
let b = a.add(a); // mismatched types: expected `&int`, found `int` (expected &-ptr, found int)
let c = a.add(&a); // this one works (a reference to the LHS is taken automatically)
let d = (&a).add(a); // mismatched types: expected `&int`, found `int` (expected &-ptr, found int)
let e = (&a).add(&a); // this one works (LHS is dereferenced and then rereferenced)