Auto dereferencing and traits

Why don't trait methods use auto-dereferencing? In the following code we have to write &x explicitly. We wouldn't have to do that with a method call; why?

struct A;
struct B;

impl From<&A> for B {
    fn from(_value: &A) -> Self {
        Self
    }
}

fn main() {
    let x = A;
    let y: B = x.into();
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `A: Into<_>` is not satisfied
  --> src/main.rs:12:18
   |
12 |     let y: B = x.into();
   |                  ^^^^ the trait `Into<_>` is not implemented for `A`
   |
   = note: required for `A` to implement `Into<B>`
help: consider borrowing here
   |
12 |     let y: B = (&x).into();
   |                ++ +

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to previous error

They do, and they do limited auto-referencing (which is what your example needs). However, it doesn't always work out unambiguously or how you wish it would.

&A has an Into implementation[1] and the into method has a Self receiver, so the algorithm never reaches the auto-reference consideration.


  1. all Sized types do ↩ī¸Ž

1 Like

Thanks. If this example worked would there an awful unintended consequence?

I encountered a similar situation today where a type implemented TryFrom<&A> and TryFrom<A> and a.try_into() was moving a.

Changing the algorithm would be breaking and churny. Extending the algorithm may be possible but as far as I know isn't on the horizon.

That means the OP could conceivably work some day (afaik and no idea what the teams or community think about it). But choosing auto-ref over the base type will probably never happen.

2 Likes