error: reached the recursion limit while auto-dereferencing T

rust

Solution

Short version: `T` implementing `Deref<T>` makes no sense and so the differences in how method calls and operator calls work with regards to dereferencing the left hand side blows things up, because `a + b` is not quite the same as `a.add(&b)`.

Long version:

The `+` operator and `Add.add` operate differently as far as taking of references is concerned.

The `+` operator takes both operands by reference itself. `a + b` for operands of respective types `A` and `B` requires that there be an implementation of `Add<B, C>` for `A` and will produce a value of type `C`. As stated, `a` and `b` are taken by reference; it makes these references itself, silently; there is no guessing. Here’s how they work:

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`

No dereferencing occurs in any of this, and so the dodgy `T: Deref<T>` requirement doesn’t blow anything up.

`Add.add` takes both values by reference. As a regular function call, it has the ability to automatically dereference and reference the left hand side when necessary. While the right hand side, as a method argument, is passed in as it is, the left hand side is dereferenced as much as possible to find all the possible methods that could be being meant by `add`. Normally this is fine and it would do what you want, but in this case it won’t, because `T` (of which type `a` is) implements `Deref<T>`. So dereferencing gets it a `T`. And then `T`, implementing `Deref<T>`, dereferences to `T`. What’s more, `T` implements `Deref<T>` and so dereferences to `T`. It keeps doing this until it reaches the recursion limit. Really, `T` implementing `Deref<T>` just makes no sense at all.

For comparison, here are some demonstrations of how the method-call add works:

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)

Problem

I wonder if this is normal or it is a bug : ``` 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)) } } ``` produces this error: ``` <anon>:7:11: 7:12 error: reached the recursion limit while auto-dereferencing T [E0055] <anon>:7 A(a.add(&b)) ``` while replacing `a.add(&b)` by `a+b` compiles without error playpen isn't `a+b`supposed to be just sugar for `a.add(&b)` ?

Original source