Skip to content

const-eval can construct uninhabited values via recursive static initialization #143047

Open
@RalfJung

Description

@RalfJung

Based on an example by @theemathas:

enum Never {}

static X: &Never = weird(&X);

const fn weird(a: &&Never) -> &'static Never {
    // SAFETY: our argument type has an unsatisfiable
    // library invariant; therefore, this code is unreachable.
    unsafe { std::hint::unreachable_unchecked() };
}
error[E0080]: could not evaluate static initializer
   --> src/lib.rs:3:20
    |
3   | static X: &Never = weird(&X);
    |                    ^^^^^^^^^ entering unreachable code
    |
note: inside `weird`
   --> src/lib.rs:8:14
    |
8   |     unsafe { std::hint::unreachable_unchecked() };
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `unreachable_unchecked`
   --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/hint.rs:109:14
    |
109 |     unsafe { intrinsics::unreachable() }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here

I can't see anything wrong about weird. Therefore, this is UB from entirely sound code.

See below for an example that involves a library invariant instead of an uninhabited type.

Cc @rust-lang/opsem @rust-lang/wg-const-eval

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-lang-radarItems that are on lang's radar and will need eventual work or consideration.I-prioritizeIssue: Indicates that prioritization has been requested for this issue.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions