1
votes

I'm holding a reference to a Struct inside another Struct, both of which are declared in the same block. I later want to use the outer Struct in a closure which is run repeatedly and never returns. The reference inside the Struct apparently does not live long enough, but in my understanding, it should never go out of scope, or at least should live at least as long as the Struct it is referring to:

struct MyStruct;

struct ReferenceStruct<'a> {
    reference: &'a MyStruct
}

impl<'a> ReferenceStruct<'a> {
    fn do_something(&self) -> () {}
}

fn run<F>(mut function: F) -> !
where
    F: FnMut() -> () + 'static
{
    loop {
        function();
    }
}

fn main() {
    let my_struct = MyStruct;
    let reference = ReferenceStruct { reference: &my_struct };

    run(move || {
        reference.do_something();
    });
}

(link to playground)

The run function (for context) mirrors an event loop, similar to that of Winit, and in reality, I have another Struct which owns the value being referenced, but this example reproduces it in fewer lines.

The error:

error[E0597]: `my_struct` does not live long enough
  --> src\main.rs:26:50
   |
26 |       let reference = ReferenceStruct { reference: &my_struct };
   |                                                    ^^^^^^^^^^ borrowed value does not live long enough
27 | 
28 | /     run(move ||
29 | |     {
30 | |         reference.do_something();
31 | |     });
   | |______- argument requires that `my_struct` is borrowed for `'static`
32 |   }
   |   - `my_struct` dropped here while still borrowed

It appears that my_struct is dropped at the end of main, but even if the program flow somehow escapes the loop, it surely lasts as long as the reference struct, which is as long as it needs to. I don't understand where or how this error could come about, or what to do about it.

1

1 Answers

0
votes

Your problem is the lifetime bound 'static for the closure passed into run(). This means that the lifetime of reference is also 'static because it is moved into the closure, which in turn means that my_struct must also have static lifetime – and that is not the case.

Luckily, you do not need the 'static bound here. If you remove it, everything works:

...
fn run<F>(mut function: F) -> !
where
    F: FnMut() -> ()
...

However, this might not be a solution in your use case if the event loop needs the closure to be 'static.