about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/transform/promote_consts.rs28
-rw-r--r--src/test/ui/statics/static-promotion.rs15
2 files changed, 41 insertions, 2 deletions
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 59a8415ef96..5f62e19938b 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -502,9 +502,33 @@ impl<'tcx> Validator<'_, 'tcx> {
     fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> {
         match place {
             PlaceRef { local, projection: [] } => self.validate_local(local),
-            PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local, projection: [proj_base @ .., elem] } => {
                 match *elem {
-                    ProjectionElem::Deref | ProjectionElem::Downcast(..) => {
+                    ProjectionElem::Deref => {
+                        let mut not_promotable = true;
+                        if let TempState::Defined { location, .. } = self.temps[local] {
+                            let def_stmt =
+                                self.body[location.block].statements.get(location.statement_index);
+                            if let Some(Statement {
+                                kind:
+                                    StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(c)))),
+                                ..
+                            }) = def_stmt
+                            {
+                                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) {
+                                            not_promotable = false;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if not_promotable {
+                            return Err(Unpromotable);
+                        }
+                    }
+                    ProjectionElem::Downcast(..) => {
                         return Err(Unpromotable);
                     }
 
diff --git a/src/test/ui/statics/static-promotion.rs b/src/test/ui/statics/static-promotion.rs
new file mode 100644
index 00000000000..2d9237d11c9
--- /dev/null
+++ b/src/test/ui/statics/static-promotion.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+struct A<T: 'static>(&'static T);
+struct B<T: 'static + ?Sized> {
+    x: &'static T,
+}
+static C: A<B<B<[u8]>>> = {
+    A(&B {
+        x: &B { x: b"hi" as &[u8] },
+    })
+};
+
+fn main() {
+    assert_eq!(b"hi", C.0.x.x);
+}