Lifetime bounds on types

The Splitting Borrows section of the Rust nomicon contains the following example.

use std::mem;

pub struct IterMut<'a, T: 'a>(&'a mut[T]); // <- Focus on this line

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        let slice = mem::replace(&mut self.0, &mut []);
        if slice.is_empty() { return None; }

        let (l, r) = slice.split_at_mut(1);
        self.0 = r;
        l.get_mut(0)
    }
}

I'm trying to understand why the bound T: 'a is necessary, and specifically I'm trying to come up with an example that compiles with T: 'a but fails to compile if instead I write

pub struct IterMut<'a, T>(&'a mut[T]);  // Note the missing T: 'a

I would have thought the following should be such an example, but it compiles just fine either way:

fn main() {
    let mut x = 1;
    let mut v = [&mut x];
    let mut iter = IterMut(&mut v);
    iter.next();
}

Can anyone help me?

It's not needed any more with the particular line you're playing with, but it used to be.

When Rust sees a reference:

&'x mut U

Then it applies an implied bound that U: 'x, since you can't take a reference that lasts longer than the value. It used to be the case that when you have such a reference in a struct:

pub struct IterMut<'a, T: 'a>(&'a mut[T]); // <- Focus on this line

You had to declare the T: 'a requirement as part of your "public API". However, RFC 2093 made it so that those bounds are inferred on struct declarations. Now you type less but the type abstraction is more leaky.

Read more here in particular.

The version without T: 'a fails to compile in Rust 1.30 (but works in 1.31).

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.