struct Foo;
struct Bar;
impl From<&Bar> for Foo {
fn from(_: &Bar) -> Foo {
Foo
}
}
fn main() {
let f: Foo = Bar.into(); // <- doesn't compile - I expected it to do `(&Bar).into()` automatically
let f: Foo = (&Bar).into(); // Requires explicit `&`
}
(Playground)
Implementing Into instead of the From above doesn't make it compile either, as expected.
impl Into<Foo> for &Bar {
fn into(self) -> Foo {
Foo
}
}
Whereas defining an inherent method does make it compile.
impl Bar {
fn into(&self) -> Foo {
Foo
}
}
It's not clear to me why the original should fail based on the method call resolution documentation. Any insights?
The receiver expression has type Bar. Using Deref to find a list of starting candidates, we find... oh, it's just Bar. Then apply auto ref and our full list of receiver candidates is:
Try the candidates in order. The first is Bar. Is there a method called into with Bar as the receiver? Yes, there's <Bar as Into<Bar>>::into.
The search stops there and it never finds the method that takes &Bar.
Not if Into::into is visible.
1 Like
Oh, dang. Makes sense.
The compiler's error suggested to me that it was reasoning differently given that it even found the one defined on &Bar to suggest adding the &. But it looks per your explanation like it stopped auto-refing anyway as soon it found a method matching the name.
error[E0277]: the trait bound `Bar: Into<_>` is not satisfied
--> src/main.rs:29:22
|
29 | let f: Foo = Bar.into(); // <- doesn't compile
| ^^^^ the trait `Into<_>` is not implemented for `Bar`
|
= note: required for `Bar` to implement `Into<Foo>`
help: consider borrowing here
|
29 | let f: Foo = (&Bar).into(); // <- doesn't compile
| ++ +
For more information about this error, try `rustc --explain E0277`.
Yeah, the diagnostics in the case of an error go looking further than the method resolution algorithm itself.