I've been messing around with traits using Rust and I've come across a problem. Here's some code:
struct Foo;
trait Bar {}
impl Bar for Foo {}
fn bar<B: Bar>(bar: B) {}
fn barr<B: Bar>() {
bar(Foo); // 1. THIS WILL WORK
let foo: B = Foo; // 2. THIS WILL NOT WORK
let foo_vec: Vec<B> = vec![Foo]; // 3. THIS WILL NOT WORK
}
This produces the errors:
error[E0308]: mismatched types
--> src/main.rs:11:18
|
11 | let foo: B = Foo; // 2. THIS WILL NOT WORK
| ^^^ expected type parameter, found struct `Foo`
|
= note: expected type `B`
found type `Foo`
error[E0308]: mismatched types
--> src/main.rs:12:32
|
12 | let foo_vec: Vec<B> = vec![Foo]; // 3. THIS WILL NOT WORK
| ^^^ expected type parameter, found struct `Foo`
|
= note: expected type `_`
found type `Foo`
Why won't #2 & #3 work? How can I let the compiler know that Foo
does in fact have a Bar
impl
?
Another examle:
struct Foo<B: Bar> {
bar: Option<B>,
}
struct Foo2;
trait Bar {}
impl<B: Bar> Bar for Foo<B> {}
impl Bar for Foo2 {}
fn bar<B: Bar>(bar: B) {}
fn circle_vec<B: Bar>() {
bar(Foo2); // 1. WORKS
Foo { bar: Some(Foo { bar: None }) }; // 2. WILL NOT WORK
}
This will give me this error:
error[E0282]: type annotations needed
--> src/main.rs:17:21
|
17 | Foo { bar: Some(Foo { bar: None }) }; // 2. WILL NOT WORK
| ^^^ cannot infer type for `B`
You have two different problems so I guess I'll write two different answers.
In your first code sample, 2 and 3 don't work because B is an input type parameter; it is the caller of
barr
that decides what B is. However, you are trying to force it to beFoo
.Let's suppose we have another implementation of
Bar
:And let's suppose we call
barr
like this:barr
would essentially be compiled as this:Foo
andQuux
are not compatible, andVec<Foo>
andVec<Quux>
are not compatible either.If you're trying to create a vector of arbitrary
Bar
objects, you need to useBar
in a non-generic way. As trait types are unsized, you can't store them directly in aVec
, so you must useVec<Box<Bar>>
,Vec<&Bar>
or some other type that wraps a pointer.In your second code sample, the error is that
None
has the typeOption<T>
, and the compiler is unable to infer an appropriate type forT
. We can explicitly specifyT
like this: