@@ -117,8 +117,7 @@ struct Qualifier<'a, 'tcx> {
117117 mode : Mode ,
118118 mir : & ' a Mir < ' tcx > ,
119119
120- local_qualif : & ' a IndexVec < Local , Option < Qualif > > ,
121- temp_promotion_state : & ' a IndexVec < Local , TempState > ,
120+ local_qualif : & ' a IndexVec < Local , Qualif > ,
122121}
123122
124123impl < ' a , ' tcx > Qualifier < ' a , ' tcx > {
@@ -127,24 +126,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx> {
127126 }
128127
129128 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]
148130 }
149131
150132 fn qualify_projection_elem ( & self , proj : & PlaceElem < ' tcx > ) -> Qualif {
@@ -467,7 +449,7 @@ struct Checker<'a, 'tcx> {
467449 mir : & ' a Mir < ' tcx > ,
468450 rpo : ReversePostorder < ' a , ' tcx > ,
469451
470- local_qualif : IndexVec < Local , Option < Qualif > > ,
452+ local_qualif : IndexVec < Local , Qualif > ,
471453 temp_promotion_state : IndexVec < Local , TempState > ,
472454 promotion_candidates : Vec < Candidate > ,
473455}
@@ -494,11 +476,22 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
494476
495477 let param_env = tcx. param_env ( def_id) ;
496478
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 ( ) ;
502495
503496 Checker {
504497 mode,
@@ -521,7 +514,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
521514 mode : self . mode ,
522515 mir : self . mir ,
523516 local_qualif : & self . local_qualif ,
524- temp_promotion_state : & self . temp_promotion_state ,
525517 }
526518 }
527519
@@ -559,10 +551,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
559551 && self . temp_promotion_state [ index] . is_promotable ( ) {
560552 debug ! ( "store to promotable temp {:?} ({:?})" , index, qualif) ;
561553 let slot = & mut self . local_qualif [ index] ;
562- if slot. is_some ( ) {
554+ if ! slot. is_empty ( ) {
563555 span_bug ! ( self . span, "multiple assignments to {:?}" , dest) ;
564556 }
565- * slot = Some ( qualif) ;
557+ * slot = qualif;
566558 }
567559 }
568560 return ;
@@ -605,7 +597,18 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
605597 // aggregates where we overwrite all fields via assignments, which would not get
606598 // that feature.
607599 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+ }
609612 }
610613
611614 /// Check a whole const, static initializer or const fn.
@@ -661,7 +664,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
661664 }
662665 }
663666
664- let mut qualif = self . local_qualif [ RETURN_PLACE ] . unwrap_or ( Qualif :: NOT_CONST ) ;
667+ let mut qualif = self . local_qualif [ RETURN_PLACE ] ;
665668
666669 // Account for errors in consts by using the
667670 // conservative type qualification instead.
@@ -698,16 +701,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
698701/// For functions (constant or not), it also records
699702/// candidates for promotion in `promotion_candidates`.
700703impl < ' 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-
711704 fn visit_place ( & mut self ,
712705 place : & Place < ' tcx > ,
713706 context : PlaceContext < ' tcx > ,
@@ -833,9 +826,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
833826 Operand :: Move ( ref place) => {
834827 // Mark the consumed locals to indicate later drops are noops.
835828 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 ;
839831 }
840832 }
841833 Operand :: Copy ( _) |
@@ -1137,9 +1129,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
11371129 // HACK(eddyb): emulate a bit of dataflow analysis,
11381130 // conservatively, that drop elaboration will do.
11391131 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 ) {
11431133 Some ( self . mir . local_decls [ local] . source_info . span )
11441134 } else {
11451135 None
@@ -1223,18 +1213,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
12231213 if let Place :: Local ( local) = * place {
12241214 if self . mir . local_kind ( local) == LocalKind :: Temp {
12251215 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) ;
12381227 }
12391228 }
12401229 }
0 commit comments