rustwinit

How to propagate error out of a closure? (Rust, winit crate's event loop)


"this_function_returns_error" returns Result and I need to propagate it back to main. Signature of the run function: https://docs.rs/winit/0.25.0/winit/event_loop/struct.EventLoop.html#method.run

Simplified example of what I need mean:

use winit::{
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::WindowBuilder,
};

fn main() -> Result<(), SomeError> {
    let event_loop = EventLoop::new();
    let window = WindowBuilder::new().build(&event_loop).unwrap();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Wait;

        match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                window_id,
            } if window_id == window.id() => *control_flow = ControlFlow::Exit,
            _ => (),
        }
        this_function_returns_error()?;
    });
}

Compiler is pointing out that:

position of closure in run method: this function should return Result or Option to accept ?

but I am not sure if I can even return the result from this closure as it is argument to winit's function.


Solution

  • I am not sure if I can even return the result from this closure as it is argument to winit's function.

    No you can't, the type of the event loop handler is:

    FnMut(Event<'_, T>, &EventLoopWindowTarget<T>, &mut ControlFlow)
    

    there's no return value in there.

    Not only that, but the event loop runner is typed:

    pub fn run<F>(self, event_handler: F) -> !
    

    The -> ! means it never returns.

    It will exit, but I assume it straight up terminates the current process1, because its type annotation clearly says it will never yield back control to the enclosing main.


    1) and indeed that's exactly what every implementation seems to do: they run the underlying event loop, and if that ever terminates they just go ::std::process::exit(0);.