openlang

Accessing a union’s payload causes a panic

Hello, this is driving me a little crazy. I'm using this rather nice windowing library (https://github.com/ypsvlq/wio), with these directions (https://github.com/ypsvlq/wio/tree/master?tab=readme-ov-file#wayland) for reaching the wayland API.

Yet accessing the .backend union using any value immediately panics with invalid enum value, and I can't work out the cause. I'd expect an incorrect union access to be rejected during compilation, and the type inspection gives the expected field_names, yet using either the right member (.wayland here) or a wrong member (.x11) at runtime panics. Nor can I spot anything that would leave that value undefined when I access it.

What's going on here??

The conversation continues 5

Follow the reasoning
  1. Permalink

    A safety check produces invalid enum value when switching over an enum containing an invalid value.

    Union-field access performs safety checks too, apparently using a switch, judging by this error message.

    As why17 suggested, the union probably holds undefined, which would make its tag undefined too.

  2. Permalink

    From reading through that part of the code, I don't see any unions involved here, the selected backend depends on the os and the target that you are building for at compile time.

    After wio.init is called, that backend ought to be initialized (or initialization should return an error), whereas before wio.init runs (and calls backend.init(options)), its backend values have not been initialized and their default values are all undefined at that point:

    https://github.com/ypsvlq/wio/blob/dd0f273fdbbd1ced2a8e716ea3a5526a6c4d83cf/src/unix.zig#L20-L98

    I'm puzzled by the library's heavy reliance on singletons and container-level variables initialized to undefined, I dislike that enough that I'd probably choose a different library.

    Rather than delegate to its backend, wio could store the statically selected backend in a field of an ordinary struct, avoiding a singleton whose backend exists in an unusable state before being initialized.

    It looks excessively focused on concealing details from the API by using globals everywhere.

  3. Permalink

    I'm referring specifically to unix.Window, a union containing wayland and x11 implementations.

    What escaped me completely was that the error originates inside a resize event callback, which apparently runs straight away during Window.init, and I'm reading from the very variable which is intended to contain the window currently being initialized, so that would account for the problem I am seeing here. That's… another design choice I'm not especially keen on either, though I havent discovered any decent alternative libraries.

    It seems rather curious that accessing the union specifically is where it fails, when the window variable itself contains undefined, wouldn't reading its .backend member already fail before that?

  4. Permalink

    A debugger run together with a printed backtrace ought to clarify the precise location and cause of the failure.

Other sides of the same question

  1. Delaying a cleanup block's mutable borrow until it actually runs

    What would be a way for me to write a panic-safe mecanism in Rust that behaves similarly to Java's try { ... } finally { ...…

    Replies 2Latest activity rust
  2. Inputting character arrays through pointers

    Whenever I attempt keyboard input into some char arrays, my program ends up crashing. What's a straightforward way of reading…

    Replies 2Latest activity c
  3. Can an input function avoid relying on global variables?

    I'd like a function to process what a user enters, filter it, and return the resulting string to whichever function called it…

    Replies 2Latest activity c