Reputation: 21
I have a struct Bar
that implements the Foo
trait.
struct Bar;
trait Foo {
fn foo(&self) {
print!("Foo");
}
}
impl Foo for Bar {}
I also have Print
trait that takes a Kind
parameter. Both Foo
and Bar
implement Print
with Bar
as its Kind
.
trait Print {
type Kind;
fn print(_: &Self::Kind);
}
impl Print for Bar {
type Kind = Bar;
fn print(_: &Bar) {
println!("Bar");
}
}
impl Print for Foo {
type Kind = Bar;
fn print(bar: &Bar) {
bar.foo();
Bar::print(bar);
}
}
Finally, I want to print Bar
using the different implementations.
fn main() {
let b = Bar;
Bar::print(&b); // prints: Bar
Foo::print(&b); // prints: FooBar
<Bar as Foo>::print(&b); // error
}
The code is also available in the playground
The two first calls to print
works fine but the line <Bar as Foo>::print(&b);
gives the following compilation error:
error[E0576]: cannot find method or associated constant `print` in trait `Foo`
--> src/main.rs:35:19
|
35 | <Bar as Foo>::print(&b); // error
| ^^^^^ not found in `Foo`
I would have expected the last two lines to print the same thing. Why do I get an error saying that Foo::print
is an unresolved name, when the line above works fine? What's the difference between the two lines?
Upvotes: 1
Views: 290
Reputation: 90852
<A as B>
is Fully Qualified Syntax (FQS) meaning “find the implementation of the trait B
for the type A
”. Your <Bar as Foo>::print
, then, is trying to call the print
method from the Foo
trait with Bar
as Self
. The Foo
trait does not have any such method, and so it quite naturally fails. What you need there for that to work is <Foo as Print>::print
.
Bar::print
looks first for an intrinsic method on the type Bar
and then for any method named print
on any trait that Bar
implements, and so is resolved as <Bar as Print>::print
. The deal is the same for Foo::Print
.
Upvotes: 2