Why `impl Into<Foo2> for &Foo` not work for `Foo.into()`?

Here is my test code:

#[derive(Debug, Clone, Copy)]
struct Foo;

#[derive(Debug, Clone, Copy)]
struct Foo2;

trait Hello {
    fn hello(self) -> Foo2;
}

impl Hello for &Foo {
    fn hello(self) -> Foo2 {
        println!("hello: &Foo");
        Foo2
    }
}

impl Into<Foo2> for &Foo {
    fn into(self) -> Foo2 {
        println!("into: Foo2");
        Foo2
    }
}

fn main() {
    // try exactly (reference) type.
    {
        let foo = &Foo;
        
        foo.hello(); // successful
        let _foo2: Foo2 = foo.into(); // successful
    }
    
    // try owned type.
    {
        let foo = Foo;
        
        foo.hello(); // successful
        let _foo2: Foo2 = foo.into(); // failed. why?
    }
}

Look like Hello::hello and Into::into has the same interface, why Foo.into() failed in here? Something I missed?

For both cases to work you must implement Into<Foo2> for both Foo and &Foo. If you only implement it for one of these, then in the other case you must borrow or dereference the Foo when calling into().

Method call resolution finds a receiver for Foo (<Foo as Into<Foo>>::into), after which any receiver for &Foo won't be elligible to call.

P.s. implement From, not Into. (It won't make this complie, but is idiomatic.)

1 Like

(I believe you mean <Foo as Into<Foo2>>::into)

But compiler can't find the <Foo as Into<Foo2>>::into right? Only <&Foo as Into<Foo2>>::into be implemented in this case. So no multiple possible candidates and should not be conflicted?

Thanks and fully agree, I won't impl Into in real code. In here just try to show that two function signatures are the same.

Yes I agree, but I just want to know why :smile:. It's not a real problem in my code base.

No, every sized T implements From<T> and Into<T>, so this works for owned foo: Foo:

        let _foo: Foo = foo.into();

You could implement Into<Foo2> for Foo and your OP would work. But x.into() will never autoref for a sized x as there is always a matching receiver before the autoref stage.

(Sorry for the brevity, on mobile)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.