@@ -93,17 +93,8 @@ 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 ) ,
99- }
100-
101- impl Candidate {
102- fn source_info ( & self , body : & Body < ' _ > ) -> SourceInfo {
103- match self {
104- Candidate :: Ref ( location) => * body. source_info ( * location) ,
105- }
106- }
96+ pub struct Candidate {
97+ location : Location ,
10798}
10899
109100struct Collector < ' a , ' tcx > {
@@ -167,7 +158,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
167158
168159 match * rvalue {
169160 Rvalue :: Ref ( ..) => {
170- self . candidates . push ( Candidate :: Ref ( location) ) ;
161+ self . candidates . push ( Candidate { location } ) ;
171162 }
172163 _ => { }
173164 }
@@ -209,36 +200,33 @@ struct Unpromotable;
209200
210201impl < ' tcx > Validator < ' _ , ' tcx > {
211202 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- }
203+ let loc = candidate. location ;
204+ let statement = & self . body [ loc. block ] . statements [ loc. statement_index ] ;
205+ match & statement. kind {
206+ StatementKind :: Assign ( box ( _, Rvalue :: Ref ( _, kind, place) ) ) => {
207+ // We can only promote interior borrows of promotable temps (non-temps
208+ // don't get promoted anyway).
209+ self . validate_local ( place. local ) ?;
210+
211+ // The reference operation itself must be promotable.
212+ // (Needs to come after `validate_local` to avoid ICEs.)
213+ self . validate_ref ( * kind, place) ?;
230214
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- }
215+ // We do not check all the projections (they do not get promoted anyway),
216+ // but we do stay away from promoting anything involving a dereference .
217+ if place . projection . contains ( & ProjectionElem :: Deref ) {
218+ return Err ( Unpromotable ) ;
219+ }
236220
237- Ok ( ( ) )
238- }
239- _ => bug ! ( ) ,
221+ // We cannot promote things that need dropping, since the promoted value
222+ // would not get dropped.
223+ if self . qualif_local :: < qualifs:: NeedsDrop > ( place. local ) {
224+ return Err ( Unpromotable ) ;
240225 }
226+
227+ Ok ( ( ) )
241228 }
229+ _ => bug ! ( ) ,
242230 }
243231 }
244232
@@ -871,58 +859,55 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
871859 } ) )
872860 } ;
873861 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- }
862+ let loc = candidate. location ;
863+ let statement = & mut blocks[ loc. block ] . statements [ loc. statement_index ] ;
864+ match statement. kind {
865+ StatementKind :: Assign ( box (
866+ _,
867+ Rvalue :: Ref ( ref mut region, borrow_kind, ref mut place) ,
868+ ) ) => {
869+ // Use the underlying local for this (necessarily interior) borrow.
870+ let ty = local_decls. local_decls ( ) [ place. local ] . ty ;
871+ let span = statement. source_info . span ;
872+
873+ let ref_ty = tcx. mk_ref (
874+ tcx. lifetimes . re_erased ,
875+ ty:: TypeAndMut { ty, mutbl : borrow_kind. to_mutbl_lossy ( ) } ,
876+ ) ;
877+
878+ * region = tcx. lifetimes . re_erased ;
879+
880+ let mut projection = vec ! [ PlaceElem :: Deref ] ;
881+ projection. extend ( place. projection ) ;
882+ place. projection = tcx. intern_place_elems ( & projection) ;
883+
884+ // Create a temp to hold the promoted reference.
885+ // This is because `*r` requires `r` to be a local,
886+ // otherwise we would use the `promoted` directly.
887+ let mut promoted_ref = LocalDecl :: new ( ref_ty, span) ;
888+ promoted_ref. source_info = statement. source_info ;
889+ let promoted_ref = local_decls. push ( promoted_ref) ;
890+ assert_eq ! ( self . temps. push( TempState :: Unpromotable ) , promoted_ref) ;
891+
892+ let promoted_ref_statement = Statement {
893+ source_info : statement. source_info ,
894+ kind : StatementKind :: Assign ( Box :: new ( (
895+ Place :: from ( promoted_ref) ,
896+ Rvalue :: Use ( promoted_operand ( ref_ty, span) ) ,
897+ ) ) ) ,
898+ } ;
899+ self . extra_statements . push ( ( loc, promoted_ref_statement) ) ;
900+
901+ Rvalue :: Ref (
902+ tcx. lifetimes . re_erased ,
903+ borrow_kind,
904+ Place {
905+ local : mem:: replace ( & mut place. local , promoted_ref) ,
906+ projection : List :: empty ( ) ,
907+ } ,
908+ )
925909 }
910+ _ => bug ! ( ) ,
926911 }
927912 } ;
928913
@@ -964,25 +949,21 @@ pub fn promote_candidates<'tcx>(
964949
965950 let mut extra_statements = vec ! [ ] ;
966951 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- }
952+ let Location { block, statement_index } = candidate. location ;
953+ if let StatementKind :: Assign ( box ( place, _) ) = & body[ block] . statements [ statement_index] . kind
954+ {
955+ if let Some ( local) = place. as_local ( ) {
956+ if temps[ local] == TempState :: PromotedOut {
957+ // Already promoted.
958+ continue ;
978959 }
979960 }
980961 }
981962
982963 // Declare return place local so that `mir::Body::new` doesn't complain.
983964 let initial_locals = iter:: once ( LocalDecl :: new ( tcx. types . never , body. span ) ) . collect ( ) ;
984965
985- let mut scope = body. source_scopes [ candidate . source_info ( body ) . scope ] . clone ( ) ;
966+ let mut scope = body. source_scopes [ body . source_info ( candidate . location ) . scope ] . clone ( ) ;
986967 scope. parent_scope = None ;
987968
988969 let promoted = Body :: new (
0 commit comments