Reputation: 619
"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.
Upvotes: 0
Views: 741
Reputation: 42492
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);
.
Upvotes: 2
Reputation:
I'm pretty late but I guess one can just wrap the event loop runner in another closure that returns a result type, and handle it like below :
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
window::WindowBuilder,
};
fn main() -> Result<(), SomeError> {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
let run_event_loop = move |
event: Event<()>,
_: &EventLoopWindowTarget,
control_flow: &mut ControlFlow
| -> Result<(), SomeError> {
*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()?;
}
event_loop.run(move |event, target, control_flow| {
handle_result(run_event_loop(event, target, control_flow));
});
}
fn handle_result(r: Result<(), SomeError>) {
if let SomeError(e) = r {
eprintln!("{}", e);
std::process::exit(1);
}
}
I read winit has changed quite a lot since, but tao still works in a similar manner.
Upvotes: 0