@@ -506,6 +506,10 @@ impl<'tcx> Validator<'_, 'tcx> {
506
506
match * elem {
507
507
ProjectionElem :: Deref => {
508
508
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.
509
513
if let TempState :: Defined { location, .. } = self . temps [ local] {
510
514
let def_stmt =
511
515
self . body [ location. block ] . statements . get ( location. statement_index ) ;
@@ -517,7 +521,15 @@ impl<'tcx> Validator<'_, 'tcx> {
517
521
{
518
522
if let Some ( did) = c. check_static_ptr ( self . tcx ) {
519
523
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) {
521
533
not_promotable = false ;
522
534
}
523
535
}
0 commit comments