@@ -117,8 +117,7 @@ struct Qualifier<'a, 'tcx> {
117
117
mode : Mode ,
118
118
mir : & ' a Mir < ' tcx > ,
119
119
120
- local_qualif : & ' a IndexVec < Local , Option < Qualif > > ,
121
- temp_promotion_state : & ' a IndexVec < Local , TempState > ,
120
+ local_qualif : & ' a IndexVec < Local , Qualif > ,
122
121
}
123
122
124
123
impl < ' a , ' tcx > Qualifier < ' a , ' tcx > {
@@ -127,24 +126,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx> {
127
126
}
128
127
129
128
fn qualify_local ( & self , local : Local ) -> Qualif {
130
- let kind = self . mir . local_kind ( local) ;
131
- match kind {
132
- LocalKind :: ReturnPointer => Qualif :: NOT_CONST ,
133
- LocalKind :: Var if self . mode == Mode :: Fn => Qualif :: NOT_CONST ,
134
-
135
- LocalKind :: Var |
136
- LocalKind :: Arg |
137
- LocalKind :: Temp => {
138
- let mut qualif = self . local_qualif [ local]
139
- . unwrap_or ( Qualif :: NOT_CONST ) ;
140
-
141
- if !self . temp_promotion_state [ local] . is_promotable ( ) {
142
- qualif = qualif | Qualif :: NOT_PROMOTABLE ;
143
- }
144
-
145
- qualif
146
- }
147
- }
129
+ self . local_qualif [ local]
148
130
}
149
131
150
132
fn qualify_projection_elem ( & self , proj : & PlaceElem < ' tcx > ) -> Qualif {
@@ -467,7 +449,7 @@ struct Checker<'a, 'tcx> {
467
449
mir : & ' a Mir < ' tcx > ,
468
450
rpo : ReversePostorder < ' a , ' tcx > ,
469
451
470
- local_qualif : IndexVec < Local , Option < Qualif > > ,
452
+ local_qualif : IndexVec < Local , Qualif > ,
471
453
temp_promotion_state : IndexVec < Local , TempState > ,
472
454
promotion_candidates : Vec < Candidate > ,
473
455
}
@@ -494,11 +476,22 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
494
476
495
477
let param_env = tcx. param_env ( def_id) ;
496
478
497
- let mut local_qualif = IndexVec :: from_elem ( None , & mir. local_decls ) ;
498
- for arg in mir. args_iter ( ) {
499
- let qualif = Qualif :: any_value_of_ty ( mir. local_decls [ arg] . ty , tcx, param_env) ;
500
- local_qualif[ arg] = Some ( Qualif :: NOT_PROMOTABLE | qualif) ;
501
- }
479
+ let local_qualif = mir. local_decls . iter_enumerated ( ) . map ( |( local, decl) | {
480
+ match mir. local_kind ( local) {
481
+ LocalKind :: Arg => {
482
+ Qualif :: any_value_of_ty ( decl. ty , tcx, param_env) |
483
+ Qualif :: NOT_PROMOTABLE
484
+ }
485
+
486
+ LocalKind :: Var if mode == Mode :: Fn => Qualif :: NOT_CONST ,
487
+
488
+ LocalKind :: Temp if !temps[ local] . is_promotable ( ) => {
489
+ Qualif :: NOT_PROMOTABLE
490
+ }
491
+
492
+ _ => Qualif :: empty ( ) ,
493
+ }
494
+ } ) . collect ( ) ;
502
495
503
496
Checker {
504
497
mode,
@@ -521,7 +514,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
521
514
mode : self . mode ,
522
515
mir : self . mir ,
523
516
local_qualif : & self . local_qualif ,
524
- temp_promotion_state : & self . temp_promotion_state ,
525
517
}
526
518
}
527
519
@@ -559,10 +551,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
559
551
&& self . temp_promotion_state [ index] . is_promotable ( ) {
560
552
debug ! ( "store to promotable temp {:?} ({:?})" , index, qualif) ;
561
553
let slot = & mut self . local_qualif [ index] ;
562
- if slot. is_some ( ) {
554
+ if ! slot. is_empty ( ) {
563
555
span_bug ! ( self . span, "multiple assignments to {:?}" , dest) ;
564
556
}
565
- * slot = Some ( qualif) ;
557
+ * slot = qualif;
566
558
}
567
559
}
568
560
return ;
@@ -605,7 +597,18 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
605
597
// aggregates where we overwrite all fields via assignments, which would not get
606
598
// that feature.
607
599
let slot = & mut self . local_qualif [ index] ;
608
- * slot = Some ( slot. unwrap_or ( Qualif :: empty ( ) ) | qualif) ;
600
+ * slot = * slot | qualif;
601
+
602
+ // Ensure we keep the `NOT_PROMOTABLE` flag is preserved.
603
+ // NOTE(eddyb) this is actually unnecessary right now, as
604
+ // we never replace the local's qualif (but we might in
605
+ // the future) - also, if `NOT_PROMOTABLE` only matters
606
+ // for `Mode::Fn`, then this is also pointless.
607
+ if self . mir . local_kind ( index) == LocalKind :: Temp {
608
+ if !self . temp_promotion_state [ index] . is_promotable ( ) {
609
+ * slot = * slot | Qualif :: NOT_PROMOTABLE ;
610
+ }
611
+ }
609
612
}
610
613
611
614
/// Check a whole const, static initializer or const fn.
@@ -661,7 +664,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
661
664
}
662
665
}
663
666
664
- let mut qualif = self . local_qualif [ RETURN_PLACE ] . unwrap_or ( Qualif :: NOT_CONST ) ;
667
+ let mut qualif = self . local_qualif [ RETURN_PLACE ] ;
665
668
666
669
// Account for errors in consts by using the
667
670
// conservative type qualification instead.
@@ -698,16 +701,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
698
701
/// For functions (constant or not), it also records
699
702
/// candidates for promotion in `promotion_candidates`.
700
703
impl < ' a , ' tcx > Visitor < ' tcx > for Checker < ' a , ' tcx > {
701
- fn visit_local ( & mut self ,
702
- & local: & Local ,
703
- _: PlaceContext < ' tcx > ,
704
- _: Location ) {
705
- debug ! ( "visit_local: local={:?}" , local) ;
706
- if self . local_qualif [ local] . is_none ( ) {
707
- self . not_const ( ) ;
708
- }
709
- }
710
-
711
704
fn visit_place ( & mut self ,
712
705
place : & Place < ' tcx > ,
713
706
context : PlaceContext < ' tcx > ,
@@ -833,9 +826,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
833
826
Operand :: Move ( ref place) => {
834
827
// Mark the consumed locals to indicate later drops are noops.
835
828
if let Place :: Local ( local) = * place {
836
- self . local_qualif [ local] = self . local_qualif [ local] . map ( |q|
837
- q - Qualif :: NEEDS_DROP
838
- ) ;
829
+ let slot = & mut self . local_qualif [ local] ;
830
+ * slot = * slot - Qualif :: NEEDS_DROP ;
839
831
}
840
832
}
841
833
Operand :: Copy ( _) |
@@ -1137,9 +1129,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1137
1129
// HACK(eddyb): emulate a bit of dataflow analysis,
1138
1130
// conservatively, that drop elaboration will do.
1139
1131
let needs_drop = if let Place :: Local ( local) = * place {
1140
- let local_needs_drop = self . local_qualif [ local]
1141
- . map_or ( true , |q| q. contains ( Qualif :: NEEDS_DROP ) ) ;
1142
- if local_needs_drop {
1132
+ if self . local_qualif [ local] . contains ( Qualif :: NEEDS_DROP ) {
1143
1133
Some ( self . mir . local_decls [ local] . source_info . span )
1144
1134
} else {
1145
1135
None
@@ -1223,18 +1213,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1223
1213
if let Place :: Local ( local) = * place {
1224
1214
if self . mir . local_kind ( local) == LocalKind :: Temp {
1225
1215
debug ! ( "qualify_consts: promotion candidate: local={:?}" , local) ;
1226
- if let Some ( qualif) = self . local_qualif [ local] {
1227
- // The borrowed place doesn't have `MUTABLE_INTERIOR`
1228
- // (from `qualify_rvalue`), so we can safely ignore
1229
- // `MUTABLE_INTERIOR` from the local's qualifications.
1230
- // This allows borrowing fields which don't have
1231
- // `MUTABLE_INTERIOR`, from a type that does, e.g.:
1232
- // `let _: &'static _ = &(Cell::new(1), 2).1;`
1233
- debug ! ( "qualify_consts: promotion candidate: qualif={:?}" , qualif) ;
1234
- if ( qualif - Qualif :: MUTABLE_INTERIOR ) . is_empty ( ) {
1235
- debug ! ( "qualify_consts: promotion candidate: {:?}" , candidate) ;
1236
- self . promotion_candidates . push ( candidate) ;
1237
- }
1216
+ let qualif = self . local_qualif [ local] ;
1217
+ // The borrowed place doesn't have `MUTABLE_INTERIOR`
1218
+ // (from `qualify_rvalue`), so we can safely ignore
1219
+ // `MUTABLE_INTERIOR` from the local's qualifications.
1220
+ // This allows borrowing fields which don't have
1221
+ // `MUTABLE_INTERIOR`, from a type that does, e.g.:
1222
+ // `let _: &'static _ = &(Cell::new(1), 2).1;`
1223
+ debug ! ( "qualify_consts: promotion candidate: qualif={:?}" , qualif) ;
1224
+ if ( qualif - Qualif :: MUTABLE_INTERIOR ) . is_empty ( ) {
1225
+ debug ! ( "qualify_consts: promotion candidate: {:?}" , candidate) ;
1226
+ self . promotion_candidates . push ( candidate) ;
1238
1227
}
1239
1228
}
1240
1229
}
0 commit comments