`self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement

Please help me understand the problem and how to resolve it.

I have a main function that creates the application and calls the run function.

fn main() {
    let application: Application = Application::new();
    application.run();
}

The compiler does not like that because the self has a limited lifespan.
I want application to run for the lifetime of the application though.

The error I am getting is this.

error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
  --> src\.\core\application.rs:22:29
   |
21 |       pub fn run(&self) {
   |                  ----- this data with an anonymous lifetime `'_`...
22 |           self.event_loop.run(move |event, _, control_flow| match event {
   |  _____________________________^
23 | |
24 | |             Event::WindowEvent {
25 | |                 ref event,
...  |
41 | |             _ => {}
42 | |         });
   | |_________^ ...is captured here...
   |
note: ...and is required to live as long as `'static` here
  --> src\.\core\application.rs:22:25
   |
22 |         self.event_loop.run(move |event, _, control_flow| match event {
   |                         ^^^

I changed the parameter to look like this

pub fn run(&'static self) {

aparently there is a scope problem when trying to run it though

error[E0597]: `application` does not live long enough
  --> src\main.rs:11:5
   |
11 |     application.run();
   |     ^^^^^^^^^^^------
   |     |
   |     borrowed value does not live long enough
   |     argument requires that `application` is borrowed for `'static`
12 | }
   | - `application` dropped here while still borrowed

You can't declare the Application static

static application: Application = Application::new();

because that is limited too tuple structs and tuple variants.

Question: so how can I declare the application to be static and live for the duration of the app's life ?

Just spitballing because there is somewhat limited information here, but as this looks like some sort of gui program, and I've run into this dilemma with gtk-rs, try moving run out of the impl block and calling it as a freestanding function.

name_of_mod::run(&application);

When the compiler says it wants 'static, it's very poorly trying to say that all temporary references are forbidden (@ekuber any chance of removing misleading 'static from errors?)

No amount of lifetime annotations can solve this problem. You can't take a temporarily borrowed argument of a function and pass it to a thread that may live for as long as it wants (which event_loop.run most likely wants to do).

If you can, you need to change the temporary scope-bound &self to an owned self that can be moved to the event loop. Alternatively, if you need to use it in multiple places, try Arc<Self> or reorganize the code in a way that the even loop doesn't use self.

Generally, when compiler demands 'static, ignore it, and keep wrapping stuff in Arc or Arc<Mutex> until it compiles. Don't use references.

If you have only one instance of Application, then the last-resort hack is to use Box::leak to make a leaked reference, which actually is 'static like the compiler wanted.

3 Likes

This is probably the easiest way I've found to do it:

Pass self by value, destructure it and claim the necessary mutability on each field, and use event_loop.run_return(...) instead of event_loop.run(...).

Here's some example code:

use std::error::Error;

use winit::{
    dpi::LogicalSize,
    event::{DeviceEvent, ElementState, Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    platform::run_return::EventLoopExtRunReturn,
    window::{Window, WindowBuilder},
};

pub struct Application {
    pub event_loop: EventLoop<()>,
    pub window: Window,
}

impl Application {
    pub fn new() -> Result<Self, Box<dyn Error>> {
        let event_loop = EventLoop::new();

        let window = WindowBuilder::new()
            .with_inner_size(LogicalSize {
                width: 1280.0,
                height: 720.0,
            })
            .build(&event_loop)?;

        Ok(Self { event_loop, window })
    }

    pub fn run(self) {
        let Self {
            mut event_loop,
            window,
        } = self;

        event_loop.run_return(|event, _target, control_flow| {
            *control_flow = ControlFlow::Poll;

            match event {
                Event::WindowEvent {
                    event: WindowEvent::CloseRequested,
                    ..
                } => {
                    *control_flow = ControlFlow::Exit;
                }

                Event::DeviceEvent {
                    event:
                        DeviceEvent::Button {
                            state: ElementState::Pressed,
                            ..
                        },
                    ..
                } => {
                    window.set_title("Button pressed");
                }

                _ => {}
            }
        });
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    Ok(Application::new()?.run())
}
1 Like

Wow this is like waking up to xmas.
Thank you very much for all your effort here I am certainly going to give it a try :slight_smile:

1 Like

I've thought about removing 'static messages altogether, and we've removed a bunch of suggestions and tweaked some errors, but this would be a whole project to actually cover every diagnostic people might get. I'm in favor of doing that, but in the meantime it'd be useful to file targeted tickets so that anyone with time to spare can tackle them piecemeal.

1 Like