Type of parameter can not live long?

The following code fragment throws 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 the as operator. How can a type 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() } } 
+14
source share
1 answer

In fact, there are many types that may "not live long enough": all those that have a life expectancy parameter.

If I introduced this type:

 struct ShortLivedBee<'a>; impl<'a> Animal for ShortLivedBee<'a> {} 

ShortLivedBee not valid for any lifetime, but only those valid for 'a .

So in your case with binding

 where T: Animal + 'static 

the only ShortLivedBee I could use in your function is ShortLivedBee<'static> .

The reason for this is that when you create a Box<Animal> you create an object object that must have a lifetime associated with it. If you do not specify it, the default will be 'static . So the type you defined is actually:

 type RcAnimal = Rc<Box<Animal + 'static>>; 

For your function to require the addition of 'static in T : It is not possible to save ShortLivedBee<'a> in Box<Animal + 'static> , unless 'a = 'static .


Another approach would be to add an annotation for life to your RcAnimal , for example:

 type RcAnimal<'a> = Rc<Box<Animal + 'a>>; 

And change your function to explicit life relation:

 fn new_rc_animal<'a, T>(animal: T) -> RcAnimal<'a> where T: Animal + 'a { Rc::new(Box::new(animal) as Box<Animal>) } 
+21
source

Source: https://habr.com/ru/post/985485/


All Articles