1
votes

I have a simple Wrapper that holds a reference to a slice of type T. My first attempt looked like this:

struct SliceWrapper<'a, T> {
    a: &'a [T],
}

Now the compiler rightly complains that T may not live long enough. So I do what it suggests and add a lifetime bound to T. Thereby telling the compiler that all borrowed content within T outlives 'a.

This is how my final attempt looks:

#[derive(Debug)]
struct SliceWrapper<'a, T: 'a> {
    a: &'a [T],
}

impl<'a, T> SliceWrapper<'a, T> {
    fn new(n: &'a [T]) -> SliceWrapper<'a, T> {
        SliceWrapper { a: n }
    }
}

fn main() {
    let array = [1, 2, 3, 4, 5];

    let aw = SliceWrapper::new(&array[..2]);

    println!("{:?}", aw);
}

This works. But, if I changed the impl to

impl<'a, T: 'a> SliceWrapper<'a, T> {
    fn new(n: &'a [T]) -> SliceWrapper<'a, T> {
        SliceWrapper { a: n }
    }
}

it also works. Why don't I have to also specify the lifetime bound on the impl block? What is different from my first successful attempt where I omitted it on the impl block?

1

1 Answers

2
votes

I would suggest that defining

struct SliceWrapper<'a, T: 'a>

would implicitly force the bound T: 'a wherever you use SliceWrapper. So both are equivalent:

 impl<'a, T>     SliceWrapper<'a, T> // T: 'a is "contained" in SliceWrapper definition
 impl<'a, T: 'a> SliceWrapper<'a, T> // but it doesn't harm to say it again

This is just a feeling, not a well-proven assertion (I didn't check RFCs or compiler code). It would be consistent with what happens with type inference: you usually have to supply the type once, and can be implicit in most other places.