@@ -93,16 +93,13 @@ 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 ) ,
96
+ pub struct Candidate {
97
+ location : Location ,
99
98
}
100
99
101
100
impl Candidate {
102
101
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 )
106
103
}
107
104
}
108
105
@@ -167,7 +164,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
167
164
168
165
match * rvalue {
169
166
Rvalue :: Ref ( ..) => {
170
- self . candidates . push ( Candidate :: Ref ( location) ) ;
167
+ self . candidates . push ( Candidate { location } ) ;
171
168
}
172
169
_ => { }
173
170
}
@@ -209,36 +206,33 @@ struct Unpromotable;
209
206
210
207
impl < ' tcx > Validator < ' _ , ' tcx > {
211
208
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) ?;
230
220
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
+ }
236
226
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 ) ;
240
231
}
232
+
233
+ Ok ( ( ) )
241
234
}
235
+ _ => bug ! ( ) ,
242
236
}
243
237
}
244
238
@@ -871,58 +865,55 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
871
865
} ) )
872
866
} ;
873
867
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
+ )
925
915
}
916
+ _ => bug ! ( ) ,
926
917
}
927
918
} ;
928
919
@@ -964,17 +955,13 @@ pub fn promote_candidates<'tcx>(
964
955
965
956
let mut extra_statements = vec ! [ ] ;
966
957
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 ;
978
965
}
979
966
}
980
967
}
0 commit comments