diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 5f62e19938b..688f48f32b1 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -506,6 +506,10 @@ impl<'tcx> Validator<'_, 'tcx> { match *elem { ProjectionElem::Deref => { let mut not_promotable = true; + // This is a special treatment for cases like *&STATIC where STATIC is a + // global static variable. + // This pattern is generated only when global static variables are directly + // accessed and is qualified for promotion safely. if let TempState::Defined { location, .. } = self.temps[local] { let def_stmt = self.body[location.block].statements.get(location.statement_index); @@ -517,7 +521,15 @@ impl<'tcx> Validator<'_, 'tcx> { { if let Some(did) = c.check_static_ptr(self.tcx) { if let Some(hir::ConstContext::Static(..)) = self.const_kind { - if !self.tcx.is_thread_local_static(did) { + // The `is_empty` predicate is introduced to exclude the case + // where the projection operations are [ .field, * ]. + // The reason is because promotion will be illegal if field + // accesses preceed the dereferencing. + // Discussion can be found at + // https://github.com/rust-lang/rust/pull/74945#discussion_r463063247 + // There may be opportunity for generalization, but this needs to be + // accounted for. + if proj_base.is_empty() && !self.tcx.is_thread_local_static(did) { not_promotable = false; } } diff --git a/src/test/ui/statics/static-promotion.rs b/src/test/ui/statics/static-promotion.rs index 2d9237d11c9..500af1e15e1 100644 --- a/src/test/ui/statics/static-promotion.rs +++ b/src/test/ui/statics/static-promotion.rs @@ -1,4 +1,12 @@ -// run-pass +// check-pass + +// Use of global static variables in literal values should be allowed for +// promotion. +// This test is to demonstrate the issue raised in +// https://github.com/rust-lang/rust/issues/70584 + +// Literal values were previously promoted into local static values when +// other global static variables are used. struct A(&'static T); struct B {