@@ -93,17 +93,8 @@ impl TempState {
93
93
/// returned value in a promoted MIR, unless it's a subset
94
94
/// of a larger candidate.
95
95
#[ 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 ,
107
98
}
108
99
109
100
struct Collector < ' a , ' tcx > {
@@ -167,7 +158,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
167
158
168
159
match * rvalue {
169
160
Rvalue :: Ref ( ..) => {
170
- self . candidates . push ( Candidate :: Ref ( location) ) ;
161
+ self . candidates . push ( Candidate { location } ) ;
171
162
}
172
163
_ => { }
173
164
}
@@ -209,36 +200,33 @@ struct Unpromotable;
209
200
210
201
impl < ' tcx > Validator < ' _ , ' tcx > {
211
202
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) ?;
230
214
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
+ }
236
220
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 ) ;
240
225
}
226
+
227
+ Ok ( ( ) )
241
228
}
229
+ _ => bug ! ( ) ,
242
230
}
243
231
}
244
232
@@ -871,58 +859,55 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
871
859
} ) )
872
860
} ;
873
861
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
+ )
925
909
}
910
+ _ => bug ! ( ) ,
926
911
}
927
912
} ;
928
913
@@ -964,25 +949,21 @@ pub fn promote_candidates<'tcx>(
964
949
965
950
let mut extra_statements = vec ! [ ] ;
966
951
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 ;
978
959
}
979
960
}
980
961
}
981
962
982
963
// Declare return place local so that `mir::Body::new` doesn't complain.
983
964
let initial_locals = iter:: once ( LocalDecl :: new ( tcx. types . never , body. span ) ) . collect ( ) ;
984
965
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 ( ) ;
986
967
scope. parent_scope = None ;
987
968
988
969
let promoted = Body :: new (
0 commit comments