Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

it is undefined behavior to use this value error on latest nightly compiler #698

Closed
doonv opened this issue Feb 11, 2024 · 12 comments
Closed

Comments

@doonv
Copy link

doonv commented Feb 11, 2024

Building on the latest nightly compiler (rustc 1.78.0-nightly (6cc484351 2024-02-10)) causes the following error:

   Compiling wayland-client v0.31.2
error[E0080]: it is undefined behavior to use this value
   --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wayland-client-0.31.2/src/lib.rs:218:9
    |
218 |         wayland_scanner::generate_interfaces!("wayland.xml");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1].child_interface.<enum-variant(Some)>.0.<deref>.c_ptr.<enum-variant(Some)>.0: encountered reference to mutable memory in `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
                ╾───alloc2328<imm>────╼                         │ ╾──────╼
            }
    = note: this error originates in the macro `wayland_scanner::generate_interfaces` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant encountered
   --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wayland-client-0.31.2/src/lib.rs:218:9
    |
218 |         wayland_scanner::generate_interfaces!("wayland.xml");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this note originates in the macro `wayland_scanner::generate_interfaces` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0080]: it is undefined behavior to use this value
   --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wayland-client-0.31.2/src/lib.rs:218:9
    |
218 |         wayland_scanner::generate_interfaces!("wayland.xml");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1].child_interface.<enum-variant(Some)>.0.<deref>.c_ptr.<enum-variant(Some)>.0: encountered reference to mutable memory in `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
                ╾───alloc2418<imm>────╼                         │ ╾──────╼
            }
    = note: this error originates in the macro `wayland_scanner::generate_interfaces` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0080]: it is undefined behavior to use this value
   --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wayland-client-0.31.2/src/lib.rs:218:9
    |
218 |         wayland_scanner::generate_interfaces!("wayland.xml");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0].child_interface.<enum-variant(Some)>.0.<deref>.c_ptr.<enum-variant(Some)>.0: encountered reference to mutable memory in `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
                ╾───alloc2484<imm>────╼                         │ ╾──────╼
            }
    = note: this error originates in the macro `wayland_scanner::generate_interfaces` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0080]: it is undefined behavior to use this value
   --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wayland-client-0.31.2/src/lib.rs:218:9
    |
218 |         wayland_scanner::generate_interfaces!("wayland.xml");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1].arg_interfaces.<deref>[0].<deref>.c_ptr.<enum-variant(Some)>.0: encountered reference to mutable memory in `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
                ╾───alloc2719<imm>────╼                         │ ╾──────╼
            }
    = note: this error originates in the macro `wayland_scanner::generate_interfaces` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0080]: it is undefined behavior to use this value
   --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wayland-client-0.31.2/src/lib.rs:218:9
    |
218 |         wayland_scanner::generate_interfaces!("wayland.xml");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[5].arg_interfaces.<deref>[0].<deref>.c_ptr.<enum-variant(Some)>.0: encountered reference to mutable memory in `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
                ╾───alloc2930<imm>────╼                         │ ╾──────╼
            }
    = note: this error originates in the macro `wayland_scanner::generate_interfaces` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0080]: it is undefined behavior to use this value
   --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wayland-client-0.31.2/src/lib.rs:218:9
    |
218 |         wayland_scanner::generate_interfaces!("wayland.xml");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[7].arg_interfaces.<deref>[0].<deref>.c_ptr.<enum-variant(Some)>.0: encountered reference to mutable memory in `const`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
                ╾───alloc3042<imm>────╼                         │ ╾──────╼
            }
    = note: this error originates in the macro `wayland_scanner::generate_interfaces` (in Nightly builds, run with -Z macro-backtrace for more info)
@alufers
Copy link

alufers commented Feb 11, 2024

I've bisected the nightly releases, and found the change which causes this error (tested on master of this repo):

searched nightlies: from nightly-2024-02-09 to nightly-2024-02-11
regressed nightly: nightly-2024-02-11
searched commit range: rust-lang/rust@d44e3b9...6cc4843
regressed commit: rust-lang/rust@6cc4843

bisected with cargo-bisect-rustc v0.6.8

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc 

@PolyMeilex
Copy link
Member

PolyMeilex commented Feb 12, 2024

Looks like rustc is not happy about a ref to a mutable static here:

        pub static WL_CALLBACK_INTERFACE: wayland_backend::protocol::Interface =
            wayland_backend::protocol::Interface {
                name: "wl_callback",
                version: 1u32,
                requests: &[],
                events: &[wayland_backend::protocol::MessageDesc {
                    name: "done",
                    signature: &[wayland_backend::protocol::ArgumentType::Uint],
                    since: 1u32,
                    is_destructor: true,
                    child_interface: None,
                    arg_interfaces: &[],
                }],
                // This causes the error
                c_ptr: Some(unsafe { &wl_callback_interface }),
            };
        pub static mut wl_callback_interface: wayland_backend::protocol::wl_interface =
            wayland_backend::protocol::wl_interface {
                name: b"wl_callback\x00" as *const u8 as *const std::os::raw::c_char,
                version: 1,
                request_count: 0,
                requests: NULLPTR as *const wayland_backend::protocol::wl_message,
                event_count: 1,
                events: unsafe { &wl_callback_events as *const _ },
            };

Not sure why this static needs to be mutable yet.
Removing the mut fixes the problem, but I'm pretty sure it was there for a reason.

EDIT: Nevermind it got even worse, now I get:

error[E0391]: cycle detected when const-evaluating + checking `xdg::shell::generated::client::__interfaces::XDG_TOPLEVEL_INTERFACE`

Nightly is fun.

PolyMeilex added a commit to PolyMeilex/wayland-rs that referenced this issue Feb 12, 2024
@elinorbgr
Copy link
Member

The fact that the error is encountered reference to mutable memory in `const` makes me wonder if rustc is not trying to do some const-promotion in the definition of the static, and causing the whole thing to fail. I'll try to make a minimal example.

@elinorbgr
Copy link
Member

The issue you pointed @PolyMeilex seems to have been reported already as rust-lang/rust#120949 and apparently has a coming fix rust-lang/rust#120960 .

The reason we have static mut here is IIRC historical, because it was the only way to have rustc accept the generation of cyclic graph of pointers for use by libwayland. It's possible that it's no longer needed, I suggest we wait for a next nightly with that fix and see what we can do from that.

@RalfJung
Copy link

RalfJung commented Feb 12, 2024

The fact that the error is encountered reference to mutable memory in const makes me wonder if rustc is not trying to do some const-promotion in the definition of the static, and causing the whole thing to fail. I'll try to make a minimal example.

What's happening is that the checks for whether consts and statics have a valid value have been tightened. Here you have a 'static shared reference to a mutable static; if anyone ever mutates that static, then reading this reference is UB. In fact references to static mut are basically never a good idea due to this; such global mutable state should only be touched with raw pointers.

The cycle error should be fixed soon, but this UB check is remaining.

Though it is strange that it says "in const" when in your snippet, the reference is created in a static. And if I take your code into playground it does not error on current nightly. Are you sure your snippet reflects what happens? It does look like the original problem does indeed involved promotion, but your snippet does not.

@elinorbgr
Copy link
Member

@RalfJung I think the problem with the code extract is that it was missing a level of indirection. This example does reproduce the issue: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=b12b75e175cc0fc7ca186ed0e2ec869f

Now, as I wrote earlier, it is indeed entirely possible that the use of static mut is no longer needed. All those statics are not intended to be mutated ever. But given it is a bunch of statics containing raw pointers to other statics, previously rustc refused this code if I didn't make the statics mut. But last time I checked this was probably a few years ago, so I plan to check how it fares now.

@RalfJung
Copy link

RalfJung commented Feb 12, 2024

I think the problem with the code extract is that it was missing a level of indirection. This example does reproduce the issue: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=b12b75e175cc0fc7ca186ed0e2ec869f

Ah! Yes there we have &[&WL_CALLBACK_INTERFACE] which is a promoted (specifically, the outer & need to be promoted to create a static slice).
rust-lang/rust#120960 should fix this code then, since it takes back the change where statics mentioned inside promoteds get validated recursively. This is an interesting testcase, we should add it to rustc. (I don't know if we necessarily want to endorse this as correct code; the unsafe is somewhat questionable. The point of the testcase would be to make us aware when we change its behavior.)

Now, as I wrote earlier, it is indeed entirely possible that the use of static mut is no longer needed. All those statics are not intended to be mutated ever. But given it is a bunch of statics containing raw pointers to other statics, previously rustc refused this code if I didn't make the statics mut. But last time I checked this was probably a few years ago, so I plan to check how it fares now.

Interesting. I'm not aware of how adding a mut would fix things if you don't plan to mutate anything. But we do relax some safety checks around static mut since they are horribly unsafe anyway, it's possible there are some surprising interactions here.

If static mut is still required, I'd be interested in seeing the example which demonstrates why static does not work. We certainly don't want to push people towards static mut.

@nvzqz
Copy link

nvzqz commented Feb 12, 2024

If static mut is still required, I'd be interested in seeing the example which demonstrates why static does not work. We certainly don't want to push people towards static mut.

It appears this issue also happens with interior mutability with types like OnceLock and AtomicUsize: rust-lang/rust#120968

@ids1024
Copy link
Member

ids1024 commented Feb 12, 2024

static mut seems to be avoidable here. Not sure if it was needed for anything else in the past, but it seems to be only needed to use a non-Sync (i.e. types containing pointers) type in the static: #700

Though CI passing there will require a nightly that fixes the "cycle detected when const-evaluating " issue, I guess.

@RalfJung
Copy link

Okay, good to know. :)

The fix landed, so a nightly with the fix should be released in a few hours.

@nvzqz
Copy link

nvzqz commented Feb 13, 2024

This seems to be fixed as of nightly-2024-02-13.

@ids1024
Copy link
Member

ids1024 commented Feb 13, 2024

Yeah, I think we can close this now.

#700 should be a bit better of a way to do things, but not make any difference in behavior baring compiler bugs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants