Help with borrow checker: "does not live long enough"

Hello
I am a beginner to Rust. I simplified a bit this example and I am getting a different error:
Could you please point me to the cause/learning resources ?

error[E0597]: `group` does not live long enough
  --> src/lifetime.rs:30:10
   |
30 |     test(&group);    
   |          ^^^^^^ borrowed value does not live long enough
31 | }
   | -
   | |
   | `group` dropped here while still borrowed
   | borrow might be used here, when `group` is dropped and runs the destructor for type `lifetime::SimpleElementGroup<'_>`
trait Element<'a> {}

trait ElementGroup<'a> : Element<'a> {}

trait Drawable { fn draw(&self);}

struct SimpleElementGroup<'a> {elements: Vec<Box<dyn Element<'a>>> }

impl<'a> ElementGroup<'a> for SimpleElementGroup<'a> {}

impl<'a> Element<'a> for SimpleElementGroup<'a> {}

fn test<'a>(group: &'a SimpleElementGroup<'a>) { }

fn main() {    
    let group = SimpleElementGroup { elements:vec![] };    
    test(&group);    
}

You can fix it by modifying test to:

fn test<'a>(group: &SimpleElementGroup<'a>) { }
//or:
fn test(group: &SimpleElementGroup<'_>) { }
// or even:
fn test(group: &SimpleElementGroup) { }

The compiler can then transform it to:

fn test<'a: 'b, 'b>(group: &'b SimpleElementGroup<'a>) { }

SimpleElementGroup contains a Vec which implements Drop. When group goes out of scope Drop::drop is called before the stack is popped. But test asks to borrow group for it’s whole lifetime, conflicting with Drop::drop.
You can learn more about Drop in this chapter of the book.

2 Likes

Thank you for the clarification.Now I understand why using a different life annotation works.
In this even simple example I am forcing a container to have the same lifetime as it's elements which is wrong (they are not "contained" by reference)

trait Element<'a> {}

trait Group<'a> {}

type InnerContainerType<'a> = Vec<Box<Element<'a>>>;

struct SimpleGroup<'a> {elements: InnerContainerType<'a> }

impl<'a> Group<'a> for SimpleGroup<'a> {}

fn test_fail_compile<'a>(group:&'a Group<'a>) { }

fn test_compiles_ok<'g, 'a>(group:&'g Group<'a>) { }

fn main() {    
    let group = SimpleGroup { elements:vec![] };    
    test_compiles_ok(&group);
    test_fail_compile(&group);
}