From 36e4fe5b5e73e24f0df6397151db16608d9f6de2 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:03:43 -0700 Subject: [PATCH 1/2] reject extern statics in promotion --- compiler/rustc_mir_transform/src/promote_consts.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 3694a0614a7b7..96057ad413802 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -317,6 +317,8 @@ impl<'tcx> Validator<'_, 'tcx> { // can only promote static accesses inside statics. && let Some(hir::ConstContext::Static(..)) = self.const_kind && !self.tcx.is_thread_local_static(did) + // Extern statics can never be read by CTFE, even inside a static. + && !self.tcx.is_foreign_item(did) { // Recurse. } else { From 9ac260686c2042fbff28381d69db5f6bc23fb3e6 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:03:56 -0700 Subject: [PATCH 2/2] re-bless tests --- ...0].SimplifyCfg-pre-optimizations.after.mir | 18 -------- ...motion_extern_static.FOO.PromoteTemps.diff | 44 ------------------- .../mir-opt/const_promotion_extern_static.rs | 7 --- .../extern-static-in-static-ice-143174.rs | 15 +++++++ .../extern-static-in-static-ice-143174.stderr | 18 ++++++++ .../extern-static-promotion-rejected.rs | 11 +++++ .../extern-static-promotion-rejected.stderr | 8 ++++ 7 files changed, 52 insertions(+), 69 deletions(-) delete mode 100644 tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-pre-optimizations.after.mir delete mode 100644 tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff create mode 100644 tests/ui/statics/extern-static-in-static-ice-143174.rs create mode 100644 tests/ui/statics/extern-static-in-static-ice-143174.stderr create mode 100644 tests/ui/statics/extern-static-promotion-rejected.rs create mode 100644 tests/ui/statics/extern-static-promotion-rejected.stderr diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-pre-optimizations.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-pre-optimizations.after.mir deleted file mode 100644 index 72cb64e275e36..0000000000000 --- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-pre-optimizations.after.mir +++ /dev/null @@ -1,18 +0,0 @@ -// MIR for `FOO::promoted[0]` after SimplifyCfg-pre-optimizations - -const FOO::promoted[0]: &[&i32; 1] = { - let mut _0: &[&i32; 1]; - let mut _1: [&i32; 1]; - let mut _2: &i32; - let mut _3: *const i32; - - bb0: { - _3 = const {ALLOC0: *const i32}; - _2 = &(*_3); - _1 = [move _2]; - _0 = &_1; - return; - } -} - -ALLOC0 (extern static: X) diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff deleted file mode 100644 index 0e4eed2c028d0..0000000000000 --- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ /dev/null @@ -1,44 +0,0 @@ -- // MIR for `FOO` before PromoteTemps -+ // MIR for `FOO` after PromoteTemps - - static mut FOO: *const &i32 = { - let mut _0: *const &i32; - let mut _1: &[&i32]; - let mut _2: &[&i32; 1]; - let _3: [&i32; 1]; - let mut _4: &i32; - let _5: *const i32; -+ let mut _6: &[&i32; 1]; - - bb0: { - StorageLive(_1); - StorageLive(_2); -- StorageLive(_3); -- StorageLive(_4); -- StorageLive(_5); -- _5 = const {ALLOC0: *const i32}; -- _4 = &(*_5); -- _3 = [move _4]; -- _2 = &_3; -+ _6 = const FOO::promoted[0]; -+ _2 = &(*_6); - _1 = move _2 as &[&i32] (PointerCoercion(Unsize, Implicit)); -- StorageDead(_4); - StorageDead(_2); - _0 = core::slice::::as_ptr(move _1) -> [return: bb1, unwind: bb2]; - } - - bb1: { -- StorageDead(_5); -- StorageDead(_3); - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } - } -- -- ALLOC0 (extern static: X) - diff --git a/tests/mir-opt/const_promotion_extern_static.rs b/tests/mir-opt/const_promotion_extern_static.rs index f16a53270a97d..ec9368094a752 100644 --- a/tests/mir-opt/const_promotion_extern_static.rs +++ b/tests/mir-opt/const_promotion_extern_static.rs @@ -1,18 +1,11 @@ //@ skip-filecheck //@ ignore-endian-big -extern "C" { - static X: i32; -} static Y: i32 = 42; // EMIT_MIR const_promotion_extern_static.BAR.PromoteTemps.diff // EMIT_MIR const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-pre-optimizations.after.mir static mut BAR: *const &i32 = [&Y].as_ptr(); -// EMIT_MIR const_promotion_extern_static.FOO.PromoteTemps.diff -// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-pre-optimizations.after.mir -static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); - // EMIT_MIR const_promotion_extern_static.BOP.built.after.mir static BOP: &i32 = &13; diff --git a/tests/ui/statics/extern-static-in-static-ice-143174.rs b/tests/ui/statics/extern-static-in-static-ice-143174.rs new file mode 100644 index 0000000000000..868d9bab73663 --- /dev/null +++ b/tests/ui/statics/extern-static-in-static-ice-143174.rs @@ -0,0 +1,15 @@ +// Regression test for #143174. + +#![crate_type = "lib"] + +type Fun = unsafe extern "C" fn(); + +struct Foo(Fun); + +static FOO: &Foo = &Foo(BAR); +//~^ ERROR cannot access extern static `BAR` [E0080] +//~| ERROR use of extern static is unsafe and requires unsafe function or block [E0133] + +unsafe extern "C" { + static BAR: Fun; +} diff --git a/tests/ui/statics/extern-static-in-static-ice-143174.stderr b/tests/ui/statics/extern-static-in-static-ice-143174.stderr new file mode 100644 index 0000000000000..f38968031ba66 --- /dev/null +++ b/tests/ui/statics/extern-static-in-static-ice-143174.stderr @@ -0,0 +1,18 @@ +error[E0080]: cannot access extern static `BAR` + --> $DIR/extern-static-in-static-ice-143174.rs:9:25 + | +LL | static FOO: &Foo = &Foo(BAR); + | ^^^ evaluation of `FOO` failed here + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/extern-static-in-static-ice-143174.rs:9:25 + | +LL | static FOO: &Foo = &Foo(BAR); + | ^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0080, E0133. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/statics/extern-static-promotion-rejected.rs b/tests/ui/statics/extern-static-promotion-rejected.rs new file mode 100644 index 0000000000000..f024f00490f74 --- /dev/null +++ b/tests/ui/statics/extern-static-promotion-rejected.rs @@ -0,0 +1,11 @@ +// previously part of tests/mir-opt/const_promotion_extern_static.rs +// promotion of extern statics is now rejected entirely, even if we're not trying to read its value + +unsafe extern "C" { + static X: i32; +} + +static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); +//~^ ERROR dangling pointer + +fn main() {} diff --git a/tests/ui/statics/extern-static-promotion-rejected.stderr b/tests/ui/statics/extern-static-promotion-rejected.stderr new file mode 100644 index 0000000000000..52e24a0bd942c --- /dev/null +++ b/tests/ui/statics/extern-static-promotion-rejected.stderr @@ -0,0 +1,8 @@ +error: encountered dangling pointer in final value of mutable static + --> $DIR/extern-static-promotion-rejected.rs:8:1 + | +LL | static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +