我想知道这是正常还是错误:
struct A<T> (T);
impl<T> Add<A<T>, A<T>> for A<T>
where T: Add<T, T> + Deref<T> + Copy {
fn add(&self, &A(b): &A<T>) -> A<T> {
let A(a) = *self;
A(a.add(&b))
}
}
Run Code Online (Sandbox Code Playgroud)
产生此错误:
<anon>:7:11: 7:12 error: reached the recursion limit while auto-dereferencing T [E0055]
<anon>:7 A(a.add(&b))
Run Code Online (Sandbox Code Playgroud)
同时a.add(&b)
通过a+b
编译替换没有错误
不a+b
应该只是糖a.add(&b)
吗?
短版: T
执行Deref<T>
是没有意义的,因此在方法调用和运营商的呼叫如何与问候提领左侧的工作差异吹的东西了,因为a + b
是不完全一样a.add(&b)
.
长版:
在+
运营商和Add.add
进行不同的操作,只要引用的回吐关注.
该+
运营商通过引用本身需要两个操作数.a + b
对于各种类型的操作数,A
并B
要求有一个Add<B, C>
for 的实现,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`
Run Code Online (Sandbox Code Playgroud)
在任何这种情况下都不会解除引用,因此狡猾的T: Deref<T>
要求不会造成任何影响.
Add.add
通过引用获取两个值.作为常规函数调用,它具有在必要时自动解除引用并引用左侧的能力.虽然右侧作为方法参数按原样传递,但是左侧被解除引用以尽可能地找到可能意味着的所有可能方法add
.通常这很好,它会做你想要的,但在这种情况下,它不会,因为T
(其类型a
)实现Deref<T>
.因此解除引用会得到它T
.然后T
,实施Deref<T>
,解除引用T
.更重要的是,T
实现Deref<T>
和解释T
.它一直这样做,直到达到递归限制.真的,T
实施Deref<T>
完全没有任何意义.
为了比较,下面是一些方法调用添加如何工作的演示:
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)
Run Code Online (Sandbox Code Playgroud)