Change:
The below code compiles in 1.40.0 but not in 1.42.0 (stable). (minimized example from rust-phf) When built in 1.42.0, it produces the following error: The same error occurs using nightly. There's an issue from January mentioning this build error on the rust-phf repo (seems to occur in 1.41.0+), but no followup discussion/work that I could find.
Notes: the same error occurs if is a struct instead of an enum the error does not occur if is removed and the is stored directly on
Minimized: must be a for this to happen, with a it doesn't happen.
This happens on both 1.41.0 and 1.41.1, so it's not fallout from (which fixed in that release). There's no entry in the release notes or blog post for 1.41.0 that indicates that this is expected fallout. cc anyways re: borrowck
regressed nightly: nightly-2019-11-24 searched commits: from to regressed commit: modify labels to -E-needs-bisection
Nice, thanks Looks like is the cause then.
assign
This issue was . Tagging as and unnominating.
So... the bug is fairly simple, albeit not easy to fix. The problem is that any use of a static anywhere like becomes This has various positive effects on rustc, making many implementation things easier, but it also means that it broke promoting reading from statics within other statics, because we will never ever support promoting &*STATICREFtmpSTATICREF`, so this is the special case we're allowed to deref.

Discussion:
fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> { match place { PlaceRef { local, projection: [] } => self.validate_local(local), <del> PlaceRef { local: _, projection: [proj_base @ .., elem] } => { </del> <ins> PlaceRef { local, projection: [proj_base @ .., elem] } => { </ins> match *elem { <del> ProjectionElem::Deref | ProjectionElem::Downcast(..) => { </del> <ins> 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); 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 { // 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; } } } } } if not_promotable { return Err(Unpromotable); } } ProjectionElem::Downcast(..) => { </ins> return Err(Unpromotable); }

<ins> // 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> { x: &'static T, } static STR: &'static [u8] = b"hi"; static C: A<B<B<[u8]>>> = { A(&B { x: &B { x: STR }, }) }; pub struct Slice(&'static [i32]); static CONTENT: i32 = 42; pub static CONTENT_MAP: Slice = Slice(&[CONTENT]); pub static FOO: (i32, i32) = (42, 43); pub static CONTENT_MAP2: Slice = Slice(&[FOO.0]); fn main() { assert_eq!(b"hi", C.0.x.x); assert_eq!(&[42], CONTENT_MAP.0); assert_eq!(&[42], CONTENT_MAP2.0); } </ins>