Description
It is possible to create references to statics while you're still initializing it. Normally, attempting to read from such a reference will cause a compile-time error, with the message "encountered static that tried to initialize itself with itself". However, reading from such a reference with std::ptr::copy()
(and also std::ptr::copy_nonoverlapping()
and std::ptr::read_unaligned()
, but not std::ptr::read()
) does not cause this error. For example:
use std::mem::MaybeUninit;
pub static X: (i32, MaybeUninit<i32>) = (1, foo(&X.0));
const fn foo(x: &i32) -> MaybeUninit<i32> {
let mut temp = MaybeUninit::<i32>::uninit();
unsafe {
std::ptr::copy(x, temp.as_mut_ptr(), 1);
}
temp
}
This code compiles fine, and leaves X.1
as an uninitialized value.
This can cause supposedly-sound API using unsafe code to become unsound. For example:
Example unsoundness
mod module {
use std::mem::MaybeUninit;
// SAFETY invariant: The MaybeUninit is always initialized
pub struct YesInit(MaybeUninit<i32>);
impl YesInit {
pub const fn new(x: &i32) -> Self {
let ptr = &raw const *x;
let mut temp = MaybeUninit::<i32>::uninit();
unsafe {
// SAFETY: We're reading from a reference into a local variable.
// So, both pointers are valid.
std::ptr::copy(ptr, temp.as_mut_ptr(), 1);
}
// SAFETY: We just initialized it from a reference, which must be initialized
Self(temp)
}
pub fn to_inner(&self) -> i32 {
unsafe {
// SAFETY: Guaranteed by safety invariant
self.0.assume_init()
}
}
}
}
use module::YesInit;
static X: (i32, YesInit) = (1, YesInit::new(&X.0));
fn main() {
println!("{}", X.1.to_inner());
}
In this code, the YesInit
type exposes an API that I think should be sound. However, the weirdness with std::ptr::copy
means that this API can be used to cause undefined behavior. Running this code with Miri reports: "error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory" inside the to_inner()
call, which happens at run time, not compile time.
See also #142404 for shenanigans with uninitialized statics.
Meta
Reproducible on the playground with 1.89.0-nightly (2025-06-11 e703dff8fe220b78195c)
@rustbot labels +I-unsound +A-const-eval