Borrow checker throws error "Dropped here while still borrowed" in genuine case


#1

Hi,

I am unable to compile code similar to below.

fn main() {
    fn f<T>(_: T) {}
    let f = f;
    let v = 0;
    f(&v);
}

Error message:-

error[E0597]: `v` does not live long enough
 --> src/main.rs:6:1
  |
5 |     f(&v);
  |        - borrow occurs here
6 | }
  | ^ `v` dropped here while still borrowed
  |
  = note: values in a scope are dropped in the opposite order they are created

error: aborting due to previous error

error: Could not compile `playground`.

Found this open issue in GitHub pointing to above error. Is there any workaround available for this issue?


#2

Swap the lines let f = f; and let v = 0;


#3

Thank you. That worked.

But I am unable apply the same for my use case. An example exactly resembling my use case is

trait Element<'a> {
    fn layout(&'a self) -> Box<Drawable + 'a>;
}

trait ElementGroup<'a> : Element<'a> {
    fn children(&self) -> &[Box<Element<'a>>];
}

trait Drawable {
    fn draw(&self);
}

struct SimpleElement {
    prop: String,
}

struct SimpleDrawable<'a, T: Element<'a> + 'a> {
    prop_reader: fn(&T) -> &str,
    simple_element: &'a T,
}

impl<'a, T: Element<'a>> Drawable for SimpleDrawable<'a, T> {
    fn draw(&self) {
        println!("Draw simple element with property {}", (self.prop_reader)(self.simple_element));
    }
}

impl<'a> Element<'a> for SimpleElement {
    fn layout(&'a self) -> Box<Drawable + 'a> {
        Box::new(SimpleDrawable::<'a, SimpleElement> { prop_reader: |v| &v.prop, simple_element: self })
    }
}

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

impl<'a> ElementGroup<'a> for SimpleElementGroup<'a> {
    fn children(&self) -> &[Box<Element<'a>>] {
        &self.elements[..]
    }
}

impl<'a> Element<'a> for SimpleElementGroup<'a> {
    fn layout(&'a self) -> Box<Drawable + 'a> {
        unimplemented!()
    }
}

fn main() {
    let element = SimpleElement { prop: String::from("Lengthy text") };
    {
        let drawable = element.layout();
        drawable.draw();
    }

    let group = SimpleElementGroup { elements: vec![Box::new(element)] };

    let res = group.layout();
    res.draw();
}

When I try to compile, I get the following error

error[E0597]: `group` does not live long enough
  --> src/main.rs:61:1
   |
59 |     let res = group.layout();
   |               ----- borrow occurs here
60 |     res.draw();
61 | }
   | ^ `group` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

error: aborting due to previous error

#4

This is different - layout is saying it needs to borrow &self (the group) for 'a which is actually the lifetime of element here. Since group is dropped before element the compiler complains.

Is there a need to borrow self with 'a?


#5

Thanks. I managed to rewrite without borrowing self with 'a and it worked.


#6

Can u please share your revised version the this Element/Group sample? Iā€™m a rust newbie and am just struggling with the lifetime parameters. Hope this can help me understand this idea better. Thanks


#7

Not sure how @srl3g ended up rewriting the code, but this is what I would do if I wanted to stick as close to the original code as possible:

trait Element {
    fn layout<'s>(&'s self) -> Box<Drawable + 's>;
}

trait ElementGroup: Element {
    fn children(&self) -> &[Box<Element>];
}

trait Drawable {
    fn draw(&self);
}

struct SimpleElement {
    prop: String,
}

struct SimpleDrawable<'a, T: Element + 'a> {
    prop_reader: fn(&T) -> &str,
    simple_element: &'a T,
}

impl<'a, T: Element> Drawable for SimpleDrawable<'a, T> {
    fn draw(&self) {
        println!(
            "Draw simple element with property {}",
            (self.prop_reader)(self.simple_element)
        );
    }
}

impl Element for SimpleElement {
    fn layout<'s>(&'s self) -> Box<Drawable + 's> {
        Box::new(SimpleDrawable::<SimpleElement> {
            prop_reader: |v| &v.prop,
            simple_element: self,
        })
    }
}

struct SimpleElementGroup {
    elements: Vec<Box<Element>>,
}

impl ElementGroup for SimpleElementGroup {
    fn children(&self) -> &[Box<Element>] {
        &self.elements[..]
    }
}

impl Element for SimpleElementGroup {
    fn layout(&self) -> Box<Drawable> {
        unimplemented!()
    }
}

fn main() {
    let element = SimpleElement {
        prop: String::from("Lengthy text"),
    };
    {
        let drawable = element.layout();
        drawable.draw();
    }

    let group = SimpleElementGroup {
        elements: vec![Box::new(element)],
    };

    let res = group.layout();
    res.draw();
}

#8

Many thanks for your prompt help.