Type definition with a trait: Differences of specifying an explicit lifetime bound?

后端 未结 1 1406
遇见更好的自我
遇见更好的自我 2021-01-01 05:31

I\'m having issues understanding the lifetime bound requirements when I use a trait in a type definition. For instance:

trait Kind { /* ... */ }
type Collect         


        
1条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-01 06:00

    Answer for new question

    You really have two orthogonal cases . I'll tackle the easier one first, the difference of #2 and #3. Comments are inline with what I hope is a representative example:

    trait Kind { 
        fn trait_fn(&self) -> u8 { 0 }
    }
    
    type CollectionOfKind1<'a> = Vec<&'a (dyn Kind + 'static)>;
    type CollectionOfKind2<'a> = Vec<&'a (dyn Kind + 'a)>;
    
    struct Alpha;
    impl Kind for Alpha {}
    
    struct Beta<'b> {
        name: &'b str,
    }
    impl<'a> Kind for Beta<'a> {}
    
    fn main() {
        let name = "world".to_string();
    
        // Doesn't need/have it's own lifetime.
        let a = Alpha;
        // Has a reference to something with the 'static lifetime.
        let b1 = Beta { name: "hello" };
        // Has a reference to something with the lifetime of `name`,
        // which is less than 'static.
        let b2 = Beta { name: &name[..] };  
    
        // Our vector is composed of references to
        // things that *might* have a reference themselves!
        let mut c1: CollectionOfKind1 = Vec::new();
        c1.push(&a);
        c1.push(&b1);
        // c1.push(&b2); // error: `name` does not live long enough
        
        let mut c2: CollectionOfKind2 = Vec::new();
        c2.push(&a);
        c2.push(&b1);
        c2.push(&b2); // Hooray
    }
    

    Of note here is that the lifetimes don't have to be the same! You could have written:

    type CollectionOfKind2<'a, 'b> = Vec<&'a (dyn Kind + 'b)>;
    

    The second thing is the meaning of trait Foo : 'static. I'm less sure here, but I wrote this small example:

    trait Foo : 'static {}
    
    fn x(a: &Foo) {}
    
    fn main() {
        x(&3u8);
    }
    

    This errors during compilation with

    the trait Foo must be implemented for the cast to the object type Foo + 'static

    Based on that, I think that Foo : 'static is just another way of writing Foo + 'static. The main difference I can think of is that it restricts the trait from ever being implemented on a struct with non-'static lifetimes:

    struct B<'a> {
        b: &'a str,
    }
    
    impl<'a> Foo for B<'a> {}
    

    Has the error

    declared lifetime bound not satisfied [...] but lifetime parameter must outlive the static lifetime

    Original answer

    I see you've found this out already, but you may want to update your version of Rust. If I compile your code on the Playpen, I get a suggestion on how to fix it:

    error: expected a path on the left-hand side of `+`, not `&'a Kind` [E0178]
    type CollectionOfKind<'a> = Vec<&'a Kind + 'a>;
                                    ^~~~~~~~
    note: perhaps you meant `&'a (Kind + 'a)`? (per RFC 438)
    type CollectionOfKind<'a> = Vec<&'a Kind + 'a>;
                                    ^~~~~~~~
    

    That references RFC 438, Precedence of Plus.

    0 讨论(0)
提交回复
热议问题