Skip to content

Const validity checks are stricter for static than for static mut. #146773

@theemathas

Description

@theemathas

I'm not sure if this is a bug, or a surprising behavior caused by #140942.

#[repr(transparent)]
struct SyncPtr(*const ());
unsafe impl Sync for SyncPtr {}

static DATA: () = ();
const MAYBE_NULL: SyncPtr = SyncPtr((&raw const DATA).wrapping_byte_add(8));

static mut YES_MUT: SyncPtr = MAYBE_NULL;
static NOT_MUT: SyncPtr = MAYBE_NULL;

const WORKS: &&() = unsafe { &*(&raw const YES_MUT).cast::<&()>() };
const FAILS: &&() = unsafe { &*(&raw const NOT_MUT).cast::<&()>() };

In the above code, WORKS compiles, but FAILS doesn't. I find this surprising, since, intuitively, a static should be usable in the same way as a static mut that is never mutated. The error message is below:

error[E0080]: constructing invalid value at .<deref>: encountered a null reference
  --> src/lib.rs:12:1
   |
12 | const FAILS: &&() = unsafe { &*(&raw const NOT_MUT).cast::<&()>() };
   | ^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
   |
   = 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) {
               ╾─────alloc5<imm>─────╼                         │ ╾──────╼
           }

For more information about this error, try `rustc --explain E0080`.

It seems to me that the const validity check performs checks recursively in each const, including through static allocations, but won't recurse through static mut allocations. (Although this explanation seems to contradict how #144719 behaves, where the compiler seems to recurse into a static only once the const is used in a pattern.)

Meta

Reproducible on the playground with version 1.92.0-nightly (2025-09-18 7c275d09ea6b953d2cca)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)C-bugCategory: This is a bug.T-langRelevant to the language teamT-opsemRelevant to the opsem teamneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions