Wgpu / winit, weird exception

This is a followup to Getting rid of this error: Error: Using exceptions for control flow, don't mind me. This isn't actually an error! - #4 by zeroexcuses -- but the question is different. The previous question was "how do we get rid of the error"; this question is "why the %$*#(# is this setup this way in the first place."

Problem:

Let's run the simplest wgpu example, say drawing a triangle to the screen. For example:

What do we get? I get this error in Chrome:

client_w.js:1520 Uncaught (in promise) Error: Using exceptions for control flow, don't mind me. This isn't actually an error!
    at imports.wbg.__wbindgen_throw (client_w.js:1520:15)
    at wasm_bindgen::throw_str::hb1c6988c45382356 (client_w_bg.wasm:0x1d5076)
    at winit::platform_impl::platform::backend::throw::h482073abf773b6b8 (client_w_bg.wasm:0x1d4efe)
    at winit::platform_impl::platform::event_loop::EventLoop<T>::run::h0e9a8db0a8271094 (client_w_bg.wasm:0x1d2089)
    at winit::event_loop::EventLoop<T>::run::h3499b49451ee8fea (client_w_bg.wasm:0x1d4111)
    at game_client::run::{{closure}}::h2acaea1ee1f3396f (client_w_bg.wasm:0x10ee6e)
    at wasm_bindgen_futures::task::singlethread::Task::run::h3d31e6802fbe514c (client_w_bg.wasm:0x1aad9b)
    at wasm_bindgen_futures::queue::Queue::new::{{closure}}::hd2b1bbe7cf30da7e (client_w_bg.wasm:0x177fd8)
    at <dyn core::ops::function::FnMut<(A,)>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::hbe46f6e01bfae5ec (client_w_bg.wasm:0x1d211e)
    at __wbg_adapter_46 (client_w.js:224:10)

So after digging around a bit, we find this function:

This function is pretty weird:

    pub fn run<F>(self, event_handler: F) -> !
    where
        F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
    {
        self.spawn(event_handler);

        // Throw an exception to break out of Rust execution and use unreachable to tell the
        // compiler this function won't return, giving it a return type of '!'
        backend::throw(
            "Using exceptions for control flow, don't mind me. This isn't actually an error!",
        );

        unreachable!();
    }

I don't get it -- why do we throw this exception in the first place? Why not let it return ?

You might make the counter argument of: It says it right in the error. It is using it for control flow!!!!

But then I counter and point out, the line which calls that function, learn-wgpu/lib.rs at master · sotrh/learn-wgpu · GitHub , is the LAST LINE of the MAIN FUNCTION.

This is like doing:


fn call_last_fn() {

 lots of work;
  todo!("let's throw exception for control flow"); // last line
}

fn main() {
  lots of work ....
  call_last_fn(); // last line
}

I feel like there is something very very simple I am missing here. WTF is going on? :slight_smile:

The reason is that run had a return type of !. This means that the only way to return from it is to panic. On several OSes the event loop will never return. The only options on those OSes are to continue running the event loop or to exit the process. AFAICT for portability reasons winit has chosen to force the same behavior on other OSes (and the web) unless you explicitly opt to use a non-portable method that allows returning.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.