Error: Recursion limit reached while automatically dereferencing T

I wonder if this is normal or is it 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))
    }
}

      

raises this error:

<anon>:7:11: 7:12 error: reached the recursion limit while auto-dereferencing T [E0055]
<anon>:7         A(a.add(&b))

      

when replaced a.add(&b)

with, it a+b

compiles without errors

playpen

a+b

should n't be just sugar for a.add(&b)

?

+3


source to share


1 answer


Short version: The T

implementation Deref<T>

doesn't make sense, and so the differences in the way method calls and operator calls with respect to dereferencing the left side blow things up, because it's a + b

not quite the same as a.add(&b)

.

Long version:

Operator +

and Add.add

operate differently in relation to the use of links.

The operator+

takes both operands by reference. a + b

for operands of the corresponding types A

and B

requires that there be an implementation Add<B, C>

for A

and create a value of the type C

. As indicated A

and B

taken from the link; he makes these references himself, silently; there is no guesswork. This is 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 happens in any of them, and so the dodgy requirement T: Deref<T>

won't blow anything up.

Add.add

takes both values โ€‹โ€‹by reference. Like a normal function call, it has the ability to automatically dereference and reference the left side when needed. While the right side as a method argument is passed as is, the left side is dereferenced as much as possible to find all possible methods that might be implied add

. This is usually ok and it will do what you want, but in this case it won't, because T

(from which type A

) implements Deref<T>

. So dereferencing does it T

. And then T

, realizing Deref<T>

, acting out T

. Moreover, it T

implements Deref<T>

and therefore divides into T

. It continues to do this until it reaches the recursion limit. Really,T

the implementation Deref<T>

just doesn't make sense.

For comparison, here are some examples of how method invocation 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)

      

+5


source







All Articles