The following code segment gives me an error:
use std::rc::Rc;
// Definition of Cat, Dog, and Animal (see the last code block)
// ...
type RcAnimal = Rc<Box<Animal>>;
fn new_rc_animal<T>(animal: T) -> RcAnimal
where
T: Animal, /* + 'static */ // works fine if uncommented
{
Rc::new(Box::new(animal) as Box<Animal>)
}
fn main() {
let dog: RcAnimal = new_rc_animal(Dog);
let cat: RcAnimal = new_rc_animal(Cat);
let mut v: Vec<RcAnimal> = Vec::new();
v.push(cat.clone());
v.push(dog.clone());
for animal in v.iter() {
println!("{}", (**animal).make_sound());
}
}
error[E0310]: the parameter type `T` may not live long enough
--> src/main.rs:8:13
|
4 | fn new_rc_animal<T>(animal: T) -> RcAnimal
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
8 | Rc::new(Box::new(animal) as Box<Animal>)
| ^^^^^^^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/main.rs:8:13
|
8 | Rc::new(Box::new(animal) as Box<Animal>)
| ^^^^^^^^^^^^^^^^
but this compiles fine:
use std::rc::Rc;
// Definition of Cat, Dog, and Animal (see the last code block)
// ...
fn new_rc_animal<T>(animal: T) -> Rc<Box<T>>
where
T: Animal,
{
Rc::new(Box::new(animal))
}
fn main() {
let dog = new_rc_animal(Dog);
let cat = new_rc_animal(Cat);
}
What is the cause of the error? The only real difference seems to be the use of operator as
. How can a type not live long enough? (playground)
// Definition of Cat, Dog, and Animal
trait Animal {
fn make_sound(&self) -> String;
}
struct Cat;
impl Animal for Cat {
fn make_sound(&self) -> String {
"meow".to_string()
}
}
struct Dog;
impl Animal for Dog {
fn make_sound(&self) -> String {
"woof".to_string()
}
}
There are actually plenty of types that can "not live long enough": all the ones that have a lifetime parameter.
If I were to introduce this type:
ShortLivedBee
is not valid for any lifetime, but only the ones that are valid for'a
as well.So in your case with the bound
the only
ShortLivedBee
I could feed into your function isShortLivedBee<'static>
.What causes this is that when creating a
Box<Animal>
, you are creating a trait object, which need to have an associated lifetime. If you do not specify it, it defaults to'static
. So the type you defined is actually:That's why your function require that a
'static
bound is added toT
: It is not possible to store aShortLivedBee<'a>
in aBox<Animal + 'static>
unless'a = 'static
.An other approach would be to add a lifetime annotation to your
RcAnimal
, like this:And change your function to explicit the lifetime relations: