@@ -506,6 +506,10 @@ impl<'tcx> Validator<'_, 'tcx> {
506506 match * elem {
507507 ProjectionElem :: Deref => {
508508 let mut not_promotable = true ;
509+ // This is a special treatment for cases like *&STATIC where STATIC is a
510+ // global static variable.
511+ // This pattern is generated only when global static variables are directly
512+ // accessed and is qualified for promotion safely.
509513 if let TempState :: Defined { location, .. } = self . temps [ local] {
510514 let def_stmt =
511515 self . body [ location. block ] . statements . get ( location. statement_index ) ;
@@ -517,7 +521,15 @@ impl<'tcx> Validator<'_, 'tcx> {
517521 {
518522 if let Some ( did) = c. check_static_ptr ( self . tcx ) {
519523 if let Some ( hir:: ConstContext :: Static ( ..) ) = self . const_kind {
520- if !self . tcx . is_thread_local_static ( did) {
524+ // The `is_empty` predicate is introduced to exclude the case
525+ // where the projection operations are [ .field, * ].
526+ // The reason is because promotion will be illegal if field
527+ // accesses preceed the dereferencing.
528+ // Discussion can be found at
529+ // https://github.com/rust-lang/rust/pull/74945#discussion_r463063247
530+ // There may be opportunity for generalization, but this needs to be
531+ // accounted for.
532+ if proj_base. is_empty ( ) && !self . tcx . is_thread_local_static ( did) {
521533 not_promotable = false ;
522534 }
523535 }
0 commit comments