@@ -1207,7 +1207,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1207
1207
& mut self ,
1208
1208
span : Span ,
1209
1209
scrutinee_span : Span ,
1210
- start_block : BasicBlock ,
1210
+ mut start_block : BasicBlock ,
1211
1211
otherwise_block : BasicBlock ,
1212
1212
candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1213
1213
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
@@ -1219,14 +1219,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1219
1219
debug ! ( "match_candidates: {:?} candidates fully matched" , fully_matched) ;
1220
1220
let ( matched_candidates, unmatched_candidates) = candidates. split_at_mut ( fully_matched) ;
1221
1221
1222
- let block = self . select_matched_candidates ( matched_candidates, start_block, fake_borrows) ;
1222
+ for candidate in matched_candidates. iter_mut ( ) {
1223
+ start_block = self . select_matched_candidate ( candidate, start_block, fake_borrows) ;
1224
+ }
1223
1225
1224
1226
// If there are no candidates that still need testing, we're
1225
1227
// done. Since all matches are exhaustive, execution should
1226
1228
// never reach this point.
1227
1229
if unmatched_candidates. is_empty ( ) {
1228
1230
let source_info = self . source_info ( span) ;
1229
- self . cfg . goto ( block , source_info, otherwise_block) ;
1231
+ self . cfg . goto ( start_block , source_info, otherwise_block) ;
1230
1232
return ;
1231
1233
}
1232
1234
@@ -1235,7 +1237,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1235
1237
span,
1236
1238
scrutinee_span,
1237
1239
unmatched_candidates,
1238
- block ,
1240
+ start_block ,
1239
1241
otherwise_block,
1240
1242
fake_borrows,
1241
1243
) ;
@@ -1260,67 +1262,64 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1260
1262
/// * the [otherwise block] of the third pattern to a block with an
1261
1263
/// [`Unreachable` terminator](TerminatorKind::Unreachable).
1262
1264
///
1263
- /// In addition, we add fake edges from the otherwise blocks to the
1265
+ /// In addition, we later add fake edges from the otherwise blocks to the
1264
1266
/// pre-binding block of the next candidate in the original set of
1265
1267
/// candidates.
1266
1268
///
1267
1269
/// [pre-binding block]: Candidate::pre_binding_block
1268
1270
/// [otherwise block]: Candidate::otherwise_block
1269
- fn select_matched_candidates (
1271
+ fn select_matched_candidate (
1270
1272
& mut self ,
1271
- matched_candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1273
+ candidate : & mut Candidate < ' _ , ' tcx > ,
1272
1274
start_block : BasicBlock ,
1273
1275
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1274
1276
) -> BasicBlock {
1275
- let mut next_prebinding = start_block;
1276
- for candidate in matched_candidates. iter_mut ( ) {
1277
- assert ! ( candidate. otherwise_block. is_none( ) ) ;
1278
- assert ! ( candidate. pre_binding_block. is_none( ) ) ;
1279
- debug_assert ! (
1280
- candidate. subcandidates. is_empty( ) ,
1281
- "subcandidates should be empty in select_matched_candidates" ,
1282
- ) ;
1277
+ assert ! ( candidate. otherwise_block. is_none( ) ) ;
1278
+ assert ! ( candidate. pre_binding_block. is_none( ) ) ;
1279
+ debug_assert ! (
1280
+ candidate. subcandidates. is_empty( ) ,
1281
+ "subcandidates should be empty in select_matched_candidates" ,
1282
+ ) ;
1283
1283
1284
- if let Some ( fake_borrows) = fake_borrows {
1285
- // Insert a borrows of prefixes of places that are bound and are
1286
- // behind a dereference projection.
1287
- //
1288
- // These borrows are taken to avoid situations like the following:
1289
- //
1290
- // match x[10] {
1291
- // _ if { x = &[0]; false } => (),
1292
- // y => (), // Out of bounds array access!
1293
- // }
1294
- //
1295
- // match *x {
1296
- // // y is bound by reference in the guard and then by copy in the
1297
- // // arm, so y is 2 in the arm!
1298
- // y if { y == 1 && (x = &2) == () } => y,
1299
- // _ => 3,
1300
- // }
1301
- for Binding { source, .. } in & candidate. bindings {
1302
- if let Some ( i) =
1303
- source. projection . iter ( ) . rposition ( |elem| elem == ProjectionElem :: Deref )
1304
- {
1305
- let proj_base = & source. projection [ ..i] ;
1306
-
1307
- fake_borrows. insert ( Place {
1308
- local : source. local ,
1309
- projection : self . tcx . mk_place_elems ( proj_base) ,
1310
- } ) ;
1311
- }
1284
+ if let Some ( fake_borrows) = fake_borrows {
1285
+ // Insert a borrows of prefixes of places that are bound and are
1286
+ // behind a dereference projection.
1287
+ //
1288
+ // These borrows are taken to avoid situations like the following:
1289
+ //
1290
+ // match x[10] {
1291
+ // _ if { x = &[0]; false } => (),
1292
+ // y => (), // Out of bounds array access!
1293
+ // }
1294
+ //
1295
+ // match *x {
1296
+ // // y is bound by reference in the guard and then by copy in the
1297
+ // // arm, so y is 2 in the arm!
1298
+ // y if { y == 1 && (x = &2) == () } => y,
1299
+ // _ => 3,
1300
+ // }
1301
+ for Binding { source, .. } in & candidate. bindings {
1302
+ if let Some ( i) =
1303
+ source. projection . iter ( ) . rposition ( |elem| elem == ProjectionElem :: Deref )
1304
+ {
1305
+ let proj_base = & source. projection [ ..i] ;
1306
+
1307
+ fake_borrows. insert ( Place {
1308
+ local : source. local ,
1309
+ projection : self . tcx . mk_place_elems ( proj_base) ,
1310
+ } ) ;
1312
1311
}
1313
1312
}
1313
+ }
1314
1314
1315
- candidate. pre_binding_block = Some ( next_prebinding) ;
1316
- next_prebinding = self . cfg . start_new_block ( ) ;
1317
- if candidate. has_guard {
1318
- // Create the otherwise block for this candidate, which is the
1319
- // pre-binding block for the next candidate.
1320
- candidate. otherwise_block = Some ( next_prebinding) ;
1321
- }
1315
+ candidate. pre_binding_block = Some ( start_block) ;
1316
+ let otherwise_block = self . cfg . start_new_block ( ) ;
1317
+ if candidate. has_guard {
1318
+ // Create the otherwise block for this candidate, which is the
1319
+ // pre-binding block for the next candidate.
1320
+ candidate. otherwise_block = Some ( otherwise_block) ;
1322
1321
}
1323
- next_prebinding
1322
+ otherwise_block
1324
1323
}
1325
1324
1326
1325
/// Tests a candidate where there are only or-patterns left to test, or
0 commit comments