@@ -24,7 +24,6 @@ use syntax::symbol::sym;
24
24
use syntax_pos:: { Span , DUMMY_SP } ;
25
25
26
26
use rustc_index:: vec:: { IndexVec , Idx } ;
27
- use rustc_index:: bit_set:: HybridBitSet ;
28
27
use rustc_target:: spec:: abi:: Abi ;
29
28
30
29
use std:: cell:: Cell ;
@@ -35,10 +34,8 @@ use crate::transform::check_consts::{qualifs, Item, ConstKind, is_lang_panic_fn}
35
34
36
35
/// A `MirPass` for promotion.
37
36
///
38
- /// In this case, "promotion" entails the following:
39
- /// - Extract promotable temps in `fn` and `const fn` into their own MIR bodies.
40
- /// - Extend lifetimes in `const` and `static` by removing `Drop` and `StorageDead`.
41
- /// - Emit errors if the requirements of `#[rustc_args_required_const]` are not met.
37
+ /// Promotion is the extraction of promotable temps into separate MIR bodies. This pass also emits
38
+ /// errors when promotion of `#[rustc_args_required_const]` arguments fails.
42
39
///
43
40
/// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each
44
41
/// newly created `StaticKind::Promoted`.
@@ -63,26 +60,13 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
63
60
64
61
let def_id = src. def_id ( ) ;
65
62
66
- let item = Item :: new ( tcx, def_id, body) ;
67
63
let mut rpo = traversal:: reverse_postorder ( body) ;
68
64
let ( temps, all_candidates) = collect_temps_and_candidates ( tcx, body, & mut rpo) ;
69
65
70
66
let promotable_candidates = validate_candidates ( tcx, body, def_id, & temps, & all_candidates) ;
71
67
72
- // For now, lifetime extension is done in `const` and `static`s without creating promoted
73
- // MIR fragments by removing `Drop` and `StorageDead` for each referent. However, this will
74
- // not work inside loops when they are allowed in `const`s.
75
- //
76
- // FIXME: use promoted MIR fragments everywhere?
77
- let promoted_fragments = if should_create_promoted_mir_fragments ( item. const_kind ) {
78
- promote_candidates ( def_id, body, tcx, temps, promotable_candidates)
79
- } else {
80
- // FIXME: promote const array initializers in consts.
81
- remove_drop_and_storage_dead_on_promoted_locals ( tcx, body, & promotable_candidates) ;
82
- IndexVec :: new ( )
83
- } ;
84
-
85
- self . promoted_fragments . set ( promoted_fragments) ;
68
+ let promoted = promote_candidates ( def_id, body, tcx, temps, promotable_candidates) ;
69
+ self . promoted_fragments . set ( promoted) ;
86
70
}
87
71
}
88
72
@@ -1188,83 +1172,3 @@ crate fn should_suggest_const_in_array_repeat_expressions_attribute<'tcx>(
1188
1172
should_promote={:?} feature_flag={:?}", mir_def_id, should_promote, feature_flag) ;
1189
1173
should_promote && !feature_flag
1190
1174
}
1191
-
1192
- fn should_create_promoted_mir_fragments ( const_kind : Option < ConstKind > ) -> bool {
1193
- match const_kind {
1194
- Some ( ConstKind :: ConstFn ) | None => true ,
1195
- Some ( ConstKind :: Const ) | Some ( ConstKind :: Static ) | Some ( ConstKind :: StaticMut ) => false ,
1196
- }
1197
- }
1198
-
1199
- /// In `const` and `static` everything without `StorageDead`
1200
- /// is `'static`, we don't have to create promoted MIR fragments,
1201
- /// just remove `Drop` and `StorageDead` on "promoted" locals.
1202
- fn remove_drop_and_storage_dead_on_promoted_locals (
1203
- tcx : TyCtxt < ' tcx > ,
1204
- body : & mut Body < ' tcx > ,
1205
- promotable_candidates : & [ Candidate ] ,
1206
- ) {
1207
- debug ! ( "run_pass: promotable_candidates={:?}" , promotable_candidates) ;
1208
-
1209
- // Removing `StorageDead` will cause errors for temps declared inside a loop body. For now we
1210
- // simply skip promotion if a loop exists, since loops are not yet allowed in a `const`.
1211
- //
1212
- // FIXME: Just create MIR fragments for `const`s instead of using this hackish approach?
1213
- if body. is_cfg_cyclic ( ) {
1214
- tcx. sess . delay_span_bug ( body. span , "Control-flow cycle detected in `const`" ) ;
1215
- return ;
1216
- }
1217
-
1218
- // The underlying local for promotion contexts like `&temp` and `&(temp.proj)`.
1219
- let mut requires_lifetime_extension = HybridBitSet :: new_empty ( body. local_decls . len ( ) ) ;
1220
-
1221
- promotable_candidates
1222
- . iter ( )
1223
- . filter_map ( |c| {
1224
- match c {
1225
- Candidate :: Ref ( loc) => Some ( loc) ,
1226
- Candidate :: Repeat ( _) | Candidate :: Argument { .. } => None ,
1227
- }
1228
- } )
1229
- . map ( |& Location { block, statement_index } | {
1230
- // FIXME: store the `Local` for each `Candidate` when it is created.
1231
- let place = match & body[ block] . statements [ statement_index] . kind {
1232
- StatementKind :: Assign ( box ( _, Rvalue :: Ref ( _, _, place) ) ) => place,
1233
- _ => bug ! ( "`Candidate::Ref` without corresponding assignment" ) ,
1234
- } ;
1235
-
1236
- match place. base {
1237
- PlaceBase :: Local ( local) => local,
1238
- PlaceBase :: Static ( _) => bug ! ( "`Candidate::Ref` for a non-local" ) ,
1239
- }
1240
- } )
1241
- . for_each ( |local| {
1242
- requires_lifetime_extension. insert ( local) ;
1243
- } ) ;
1244
-
1245
- // Remove `Drop` terminators and `StorageDead` statements for all promotable temps that require
1246
- // lifetime extension.
1247
- for block in body. basic_blocks_mut ( ) {
1248
- block. statements . retain ( |statement| {
1249
- match statement. kind {
1250
- StatementKind :: StorageDead ( index) => !requires_lifetime_extension. contains ( index) ,
1251
- _ => true
1252
- }
1253
- } ) ;
1254
- let terminator = block. terminator_mut ( ) ;
1255
- match & terminator. kind {
1256
- TerminatorKind :: Drop {
1257
- location,
1258
- target,
1259
- ..
1260
- } => {
1261
- if let Some ( index) = location. as_local ( ) {
1262
- if requires_lifetime_extension. contains ( index) {
1263
- terminator. kind = TerminatorKind :: Goto { target : * target } ;
1264
- }
1265
- }
1266
- }
1267
- _ => { }
1268
- }
1269
- }
1270
- }
0 commit comments