about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/transform/promote_consts.rs14
-rw-r--r--src/test/ui/statics/static-promotion.rs10
2 files changed, 22 insertions, 2 deletions
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<T: 'static>(&'static T);
 struct B<T: 'static + ?Sized> {