Skip to content

{UnsafeCell,Cell}::from_mut on &mut [T; 0] then unsize-coerced in consteval reports UB in safe code #142948

Closed
@theemathas

Description

@theemathas

This code makes the compiler report undefined behavior in safe code during consteval.

use std::cell::UnsafeCell;
const X: &mut UnsafeCell<[i32]> = UnsafeCell::from_mut(&mut []);
error[E0080]: constructing invalid value at .<deref>: encountered `UnsafeCell` in read-only memory
 --> src/lib.rs:2:1
  |
2 | const X: &mut UnsafeCell<[i32]> = UnsafeCell::from_mut(&mut []);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: 16, align: 8) {
              ╾───────alloc3────────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
          }

For more information about this error, try `rustc --explain E0080`.
error: could not compile `playground` (lib) due to 1 previous error

UnsafeCell::from_mut has been stable in const since 1.84.0. The similar Cell::from_mut is about to be stabilized in const in 1.88.0, which is in a couple days. Using Cell instead of UnsafeCell results in a similar error.

Code using Cell
use std::cell::Cell;
const X: &Cell<[i32]> = Cell::from_mut(&mut []);
error[E0080]: constructing invalid value at .<deref>.value: encountered `UnsafeCell` in read-only memory
 --> src/lib.rs:2:1
  |
2 | const X: &Cell<[i32]> = Cell::from_mut(&mut []);
  | ^^^^^^^^^^^^^^^^^^^^^ 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: 16, align: 8) {
              ╾───────alloc3────────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
          }

For more information about this error, try `rustc --explain E0080`.
error: could not compile `playground` (lib) due to 1 previous error

Note that this issue only happens if there's an unsize coercion from [T; 0] to [T]. That is, the following code compiles fine:

use std::cell::UnsafeCell;
const X: &mut UnsafeCell<[i32; 0]> = UnsafeCell::from_mut(&mut []);

Note that storing a &mut in a const in safe code is only possible on empty arrays. See #140126.

Meta

Reproducible on the playground with 1.90.0-nightly (2025-06-23 706f244db581212cabf2)

@rustbot labels +A-const-eval +I-unsound

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-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions