From ddbe69a5b2f268042d7d68b0bb5d2cac0055519b Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Thu, 30 Jul 2020 18:33:34 +0800 Subject: [PATCH] Special treatment for dereferencing a borrow to a static definition --- src/librustc_mir/transform/promote_consts.rs | 28 ++++++++++++++++++-- src/test/ui/statics/static-promotion.rs | 15 +++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/statics/static-promotion.rs 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(&'static T); +struct B { + x: &'static T, +} +static C: A>> = { + A(&B { + x: &B { x: b"hi" as &[u8] }, + }) +}; + +fn main() { + assert_eq!(b"hi", C.0.x.x); +}