trait A {
fn print(&self);
}
struct Aimpl {
s: String
}
impl A for Aimpl {
fn print(&self){
println!("{}", self.s);
}
}
fn prints(v: Vec<&dyn A>){
for a in v {
a.print();
}
}
fn main(){
// This doesn't work because &Aimpl
// "creates a temporary which is freed while still in use"
//let v: Vec<&dyn A> = vec![&Aimpl{s: "123".into()}, &Aimpl{s: "456".into()}];
// This doesn't work, because
// "prints(v) expected trait object 'dyn A', found struct 'Aimpl"
let v = vec![&Aimpl{s: "123".into()}, &Aimpl{s: "456".into()}];
prints(v);
}
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:26:12
|
26 | prints(v);
| ------ ^ expected trait object `dyn A`, found struct `Aimpl`
| |
| arguments to this function are incorrect
|
= note: expected struct `Vec<&dyn A>`
found struct `Vec<&Aimpl>`
note: function defined here
--> src/main.rs:15:4
|
15 | fn prints(v: Vec<&dyn A>){
| ^^^^^^ --------------
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
Yes. You cannot store a reference to something that isn't already stored somewhere else (hence the t"emporary which is freed while still in use" error).
30 | prints(v);
| ------ ^ expected trait object `dyn A`, found struct `Aimpl`
| |
| arguments to this function are incorrect
|
= note: expected struct `Vec<Box<(dyn A + 'static)>>`
found struct `Vec<Box<Aimpl>>`
To elaborate, you can't perform unsized coercion (from Box<Aimpl> to Box<dyn A>) through the outer Vec, so you have to have a Vec<Box<dyn A>> from the start. (There's nothing in the unannotated initialization to nudge the compiler to infer the coercion, so you got a Vec<Box<Aimpl>>.)
I think the difference there is that having an intermediary binding gave the type system somewhere to attach the type of the Vec to, and after that point the type was considered known. So inference didn't get involved when you passed v to prints because it had already decided it was done with v.