The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want

前端 未结 2 665
[愿得一人]
[愿得一人] 2020-11-22 09:35

I\'m trying to implement something that looks like this minimal example:

trait Bar {}

struct Foo {
    data: Vec>         


        
相关标签:
2条回答
  • 2020-11-22 10:05

    Check out the entire error:

    error[E0310]: the parameter type `U` may not live long enough
     --> src/main.rs:9:24
      |
    8 |     fn add<U: Bar<T>>(&mut self, x: U) {
      |            -- help: consider adding an explicit lifetime bound `U: 'static`...
    9 |         self.data.push(Box::new(x));
      |                        ^^^^^^^^^^^
      |
    note: ...so that the type `U` will meet its required lifetime bounds
     --> src/main.rs:9:24
      |
    9 |         self.data.push(Box::new(x));
      |                        ^^^^^^^^^^^
    

    Specifically, the compiler is letting you know that it's possible that some arbitrary type U might contain a reference, and that reference could then become invalid:

    impl<'a, T> Bar<T> for &'a str {}
    
    fn main() {
        let mut foo = Foo { data: vec![] };
    
        {
            let s = "oh no".to_string();
            foo.add(s.as_ref());
        }
    }
    

    That would be Bad News.

    Whether you want a 'static lifetime or a parameterized lifetime is up to your needs. The 'static lifetime is easier to use, but has more restrictions. Because of this, it's the default when you declare a trait object in a struct or a type alias:

    struct Foo<T> {
        data: Vec<Box<dyn Bar<T>>>,
        // same as
        // data: Vec<Box<dyn Bar<T> + 'static>>,
    } 
    

    However, when used as an argument, a trait object uses lifetime elision and gets a unique lifetime:

    fn foo(&self, x: Box<dyn Bar<T>>)
    // same as
    // fn foo<'a, 'b>(&'a self, x: Box<dyn Bar<T> + 'b>)
    

    These two things need to match up.

    struct Foo<'a, T> {
        data: Vec<Box<dyn Bar<T> + 'a>>,
    }
    
    impl<'a, T> Foo<'a, T> {
        fn add<U>(&mut self, x: U)
        where
            U: Bar<T> + 'a,
        {
            self.data.push(Box::new(x));
        }
    }
    

    or

    struct Foo<T> {
        data: Vec<Box<dyn Bar<T>>>,
    }
    
    impl<T> Foo<T> {
        fn add<U>(&mut self, x: U)
        where
            U: Bar<T> + 'static,
        {
            self.data.push(Box::new(x));
        }
    }
    
    0 讨论(0)
  • 2020-11-22 10:11

    asking me to consider adding a 'static lifetime qualifier (E0310). I am 99% sure that's not what I want, but I'm not exactly sure what I'm supposed to do.

    Yes it is. The compiler does not want a &'static reference, it wants U: 'static.

    Having U: 'static means that U contains no references with a lifetime less than 'static. This is required because you want to put a U instance in a structure without lifetimes.

    trait Bar<T> {}
    
    struct Foo<T> {
        data: Vec<Box<dyn Bar<T>>>,
    }
    
    impl<T> Foo<T> {
        fn add<U: Bar<T> + 'static>(&mut self, x: U) {
            self.data.push(Box::new(x));
        }
    }
    
    0 讨论(0)
提交回复
热议问题