@@ -93,16 +93,13 @@ impl TempState {
9393/// returned value in a promoted MIR, unless it's a subset
9494/// of a larger candidate.
9595#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
96- pub enum Candidate {
97- /// Borrow of a constant temporary, candidate for lifetime extension.
98- Ref ( Location ) ,
96+ pub struct Candidate {
97+ location : Location ,
9998}
10099
101100impl Candidate {
102101 fn source_info ( & self , body : & Body < ' _ > ) -> SourceInfo {
103- match self {
104- Candidate :: Ref ( location) => * body. source_info ( * location) ,
105- }
102+ * body. source_info ( self . location )
106103 }
107104}
108105
@@ -167,7 +164,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
167164
168165 match * rvalue {
169166 Rvalue :: Ref ( ..) => {
170- self . candidates . push ( Candidate :: Ref ( location) ) ;
167+ self . candidates . push ( Candidate { location } ) ;
171168 }
172169 _ => { }
173170 }
@@ -209,36 +206,33 @@ struct Unpromotable;
209206
210207impl < ' tcx > Validator < ' _ , ' tcx > {
211208 fn validate_candidate ( & self , candidate : Candidate ) -> Result < ( ) , Unpromotable > {
212- match candidate {
213- Candidate :: Ref ( loc) => {
214- let statement = & self . body [ loc. block ] . statements [ loc. statement_index ] ;
215- match & statement. kind {
216- StatementKind :: Assign ( box ( _, Rvalue :: Ref ( _, kind, place) ) ) => {
217- // We can only promote interior borrows of promotable temps (non-temps
218- // don't get promoted anyway).
219- self . validate_local ( place. local ) ?;
220-
221- // The reference operation itself must be promotable.
222- // (Needs to come after `validate_local` to avoid ICEs.)
223- self . validate_ref ( * kind, place) ?;
224-
225- // We do not check all the projections (they do not get promoted anyway),
226- // but we do stay away from promoting anything involving a dereference.
227- if place. projection . contains ( & ProjectionElem :: Deref ) {
228- return Err ( Unpromotable ) ;
229- }
209+ let loc = candidate. location ;
210+ let statement = & self . body [ loc. block ] . statements [ loc. statement_index ] ;
211+ match & statement. kind {
212+ StatementKind :: Assign ( box ( _, Rvalue :: Ref ( _, kind, place) ) ) => {
213+ // We can only promote interior borrows of promotable temps (non-temps
214+ // don't get promoted anyway).
215+ self . validate_local ( place. local ) ?;
216+
217+ // The reference operation itself must be promotable.
218+ // (Needs to come after `validate_local` to avoid ICEs.)
219+ self . validate_ref ( * kind, place) ?;
230220
231- // We cannot promote things that need dropping, since the promoted value
232- // would not get dropped .
233- if self . qualif_local :: < qualifs :: NeedsDrop > ( place . local ) {
234- return Err ( Unpromotable ) ;
235- }
221+ // We do not check all the projections (they do not get promoted anyway),
222+ // but we do stay away from promoting anything involving a dereference .
223+ if place . projection . contains ( & ProjectionElem :: Deref ) {
224+ return Err ( Unpromotable ) ;
225+ }
236226
237- Ok ( ( ) )
238- }
239- _ => bug ! ( ) ,
227+ // We cannot promote things that need dropping, since the promoted value
228+ // would not get dropped.
229+ if self . qualif_local :: < qualifs:: NeedsDrop > ( place. local ) {
230+ return Err ( Unpromotable ) ;
240231 }
232+
233+ Ok ( ( ) )
241234 }
235+ _ => bug ! ( ) ,
242236 }
243237 }
244238
@@ -871,58 +865,55 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
871865 } ) )
872866 } ;
873867 let ( blocks, local_decls) = self . source . basic_blocks_and_local_decls_mut ( ) ;
874- match candidate {
875- Candidate :: Ref ( loc) => {
876- let statement = & mut blocks[ loc. block ] . statements [ loc. statement_index ] ;
877- match statement. kind {
878- StatementKind :: Assign ( box (
879- _,
880- Rvalue :: Ref ( ref mut region, borrow_kind, ref mut place) ,
881- ) ) => {
882- // Use the underlying local for this (necessarily interior) borrow.
883- let ty = local_decls. local_decls ( ) [ place. local ] . ty ;
884- let span = statement. source_info . span ;
885-
886- let ref_ty = tcx. mk_ref (
887- tcx. lifetimes . re_erased ,
888- ty:: TypeAndMut { ty, mutbl : borrow_kind. to_mutbl_lossy ( ) } ,
889- ) ;
890-
891- * region = tcx. lifetimes . re_erased ;
892-
893- let mut projection = vec ! [ PlaceElem :: Deref ] ;
894- projection. extend ( place. projection ) ;
895- place. projection = tcx. intern_place_elems ( & projection) ;
896-
897- // Create a temp to hold the promoted reference.
898- // This is because `*r` requires `r` to be a local,
899- // otherwise we would use the `promoted` directly.
900- let mut promoted_ref = LocalDecl :: new ( ref_ty, span) ;
901- promoted_ref. source_info = statement. source_info ;
902- let promoted_ref = local_decls. push ( promoted_ref) ;
903- assert_eq ! ( self . temps. push( TempState :: Unpromotable ) , promoted_ref) ;
904-
905- let promoted_ref_statement = Statement {
906- source_info : statement. source_info ,
907- kind : StatementKind :: Assign ( Box :: new ( (
908- Place :: from ( promoted_ref) ,
909- Rvalue :: Use ( promoted_operand ( ref_ty, span) ) ,
910- ) ) ) ,
911- } ;
912- self . extra_statements . push ( ( loc, promoted_ref_statement) ) ;
913-
914- Rvalue :: Ref (
915- tcx. lifetimes . re_erased ,
916- borrow_kind,
917- Place {
918- local : mem:: replace ( & mut place. local , promoted_ref) ,
919- projection : List :: empty ( ) ,
920- } ,
921- )
922- }
923- _ => bug ! ( ) ,
924- }
868+ let loc = candidate. location ;
869+ let statement = & mut blocks[ loc. block ] . statements [ loc. statement_index ] ;
870+ match statement. kind {
871+ StatementKind :: Assign ( box (
872+ _,
873+ Rvalue :: Ref ( ref mut region, borrow_kind, ref mut place) ,
874+ ) ) => {
875+ // Use the underlying local for this (necessarily interior) borrow.
876+ let ty = local_decls. local_decls ( ) [ place. local ] . ty ;
877+ let span = statement. source_info . span ;
878+
879+ let ref_ty = tcx. mk_ref (
880+ tcx. lifetimes . re_erased ,
881+ ty:: TypeAndMut { ty, mutbl : borrow_kind. to_mutbl_lossy ( ) } ,
882+ ) ;
883+
884+ * region = tcx. lifetimes . re_erased ;
885+
886+ let mut projection = vec ! [ PlaceElem :: Deref ] ;
887+ projection. extend ( place. projection ) ;
888+ place. projection = tcx. intern_place_elems ( & projection) ;
889+
890+ // Create a temp to hold the promoted reference.
891+ // This is because `*r` requires `r` to be a local,
892+ // otherwise we would use the `promoted` directly.
893+ let mut promoted_ref = LocalDecl :: new ( ref_ty, span) ;
894+ promoted_ref. source_info = statement. source_info ;
895+ let promoted_ref = local_decls. push ( promoted_ref) ;
896+ assert_eq ! ( self . temps. push( TempState :: Unpromotable ) , promoted_ref) ;
897+
898+ let promoted_ref_statement = Statement {
899+ source_info : statement. source_info ,
900+ kind : StatementKind :: Assign ( Box :: new ( (
901+ Place :: from ( promoted_ref) ,
902+ Rvalue :: Use ( promoted_operand ( ref_ty, span) ) ,
903+ ) ) ) ,
904+ } ;
905+ self . extra_statements . push ( ( loc, promoted_ref_statement) ) ;
906+
907+ Rvalue :: Ref (
908+ tcx. lifetimes . re_erased ,
909+ borrow_kind,
910+ Place {
911+ local : mem:: replace ( & mut place. local , promoted_ref) ,
912+ projection : List :: empty ( ) ,
913+ } ,
914+ )
925915 }
916+ _ => bug ! ( ) ,
926917 }
927918 } ;
928919
@@ -964,17 +955,13 @@ pub fn promote_candidates<'tcx>(
964955
965956 let mut extra_statements = vec ! [ ] ;
966957 for candidate in candidates. into_iter ( ) . rev ( ) {
967- match candidate {
968- Candidate :: Ref ( Location { block, statement_index } ) => {
969- if let StatementKind :: Assign ( box ( place, _) ) =
970- & body[ block] . statements [ statement_index] . kind
971- {
972- if let Some ( local) = place. as_local ( ) {
973- if temps[ local] == TempState :: PromotedOut {
974- // Already promoted.
975- continue ;
976- }
977- }
958+ let Location { block, statement_index } = candidate. location ;
959+ if let StatementKind :: Assign ( box ( place, _) ) = & body[ block] . statements [ statement_index] . kind
960+ {
961+ if let Some ( local) = place. as_local ( ) {
962+ if temps[ local] == TempState :: PromotedOut {
963+ // Already promoted.
964+ continue ;
978965 }
979966 }
980967 }
0 commit comments