Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lifetime of reference to boxed value does not live long enough

The following code doesn't compile:

use std::borrow::Borrow;

struct Inner<'a> {
    v: Vec<&'a u8>,
}

struct Foo<'a> {
    inner: Inner<'a>,
    derp: Box<u8>,
}

impl<'a> Foo<'a> {
    fn new() -> Foo<'a> {
        let mut e = Foo {
            inner: Inner { v: vec![] },
            derp: Box::new(128),
        };
        e.inner.v.push(&*e.derp);

        return e;
    }

    fn derp(&mut self) {
        println!("{:?}", self.inner.v);
    }
}

fn main() {
    let mut f = Foo::new();

    f.derp();
}

I get the following error:

error[E0597]: `*e.derp` does not live long enough
  --> src/main.rs:18:25
   |
18 |         e.inner.v.push(&*e.derp);
   |                         ^^^^^^^ does not live long enough
...
21 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 12:1...
  --> src/main.rs:12:1
   |
12 | / impl<'a> Foo<'a> {
13 | |     fn new() -> Foo<'a> {
14 | |         let mut e = Foo {
15 | |             inner: Inner { v: vec![] },
...  |
25 | |     }
26 | | }
   | |_^

I think that the value inside of the box does live for as long as 'a since it is a member of Foo, which has exactly that lifetime.

I wondered if the move of Foo at the end of the new function was confusing it, so if tried to do the append in derp. I get a different error:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> main.rs:20:27
   |
20 |         self.inner.v.push(& *self.derp);
   |                           ^^^^^^^^^^

which gives me no indication of what lifetime the compiler thinks the boxed value has.

like image 537
Bob Bobbio Avatar asked Dec 03 '25 08:12

Bob Bobbio


1 Answers

I think though that the value inside of the box does live for as long as 'a since it is a member of Foo which has exactly that lifetime.

It is possible to assign a new box to the derp member, at which point the old box will be dropped and the lifetime of the value in it ends.

I think what you are trying to do is impossible in safe Rust: cross-references between struct members are not supported. This comes up regularly as a question, but it's just not available in the language.

  • How to initialize struct fields which reference each other
  • Why can't I store a value and a reference to that value in the same struct?

You can use Rc to work around this, perhaps in combination with RefCell.

like image 164
Florian Weimer Avatar answered Dec 05 '25 21:12

Florian Weimer