@@ -1235,53 +1235,43 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1235
1235
& mut self ,
1236
1236
span : Span ,
1237
1237
scrutinee_span : Span ,
1238
- start_block : BasicBlock ,
1238
+ mut start_block : BasicBlock ,
1239
1239
otherwise_block : BasicBlock ,
1240
1240
candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1241
1241
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1242
1242
) {
1243
- // The candidates are sorted by priority. Check to see whether the
1244
- // higher priority candidates (and hence at the front of the slice)
1245
- // have satisfied all their match pairs.
1246
- let fully_matched = candidates. iter ( ) . take_while ( |c| c. match_pairs . is_empty ( ) ) . count ( ) ;
1247
- debug ! ( "match_candidates: {:?} candidates fully matched" , fully_matched) ;
1248
- let ( matched_candidates, unmatched_candidates) = candidates. split_at_mut ( fully_matched) ;
1249
-
1250
- let block = if !matched_candidates. is_empty ( ) {
1251
- let otherwise_block =
1252
- self . select_matched_candidates ( matched_candidates, start_block, fake_borrows) ;
1253
-
1254
- if let Some ( last_otherwise_block) = otherwise_block {
1255
- last_otherwise_block
1256
- } else {
1257
- // Any remaining candidates are unreachable.
1258
- if unmatched_candidates. is_empty ( ) {
1259
- return ;
1260
- }
1261
- self . cfg . start_new_block ( )
1243
+ match candidates {
1244
+ [ ] => {
1245
+ // If there are no candidates that still need testing, we're done. Since all matches are
1246
+ // exhaustive, execution should never reach this point.
1247
+ let source_info = self . source_info ( span) ;
1248
+ self . cfg . goto ( start_block, source_info, otherwise_block) ;
1249
+ }
1250
+ [ first, remaining @ ..] if first. match_pairs . is_empty ( ) => {
1251
+ // The first candidate has satisfied all its match pairs; we link it up and continue
1252
+ // with the remaining candidates.
1253
+ start_block = self . select_matched_candidate ( first, start_block, fake_borrows) ;
1254
+ self . match_simplified_candidates (
1255
+ span,
1256
+ scrutinee_span,
1257
+ start_block,
1258
+ otherwise_block,
1259
+ remaining,
1260
+ fake_borrows,
1261
+ )
1262
+ }
1263
+ candidates => {
1264
+ // The first candidate has some unsatisfied match pairs; we proceed to do more tests.
1265
+ self . test_candidates_with_or (
1266
+ span,
1267
+ scrutinee_span,
1268
+ candidates,
1269
+ start_block,
1270
+ otherwise_block,
1271
+ fake_borrows,
1272
+ ) ;
1262
1273
}
1263
- } else {
1264
- start_block
1265
- } ;
1266
-
1267
- // If there are no candidates that still need testing, we're
1268
- // done. Since all matches are exhaustive, execution should
1269
- // never reach this point.
1270
- if unmatched_candidates. is_empty ( ) {
1271
- let source_info = self . source_info ( span) ;
1272
- self . cfg . goto ( block, source_info, otherwise_block) ;
1273
- return ;
1274
1274
}
1275
-
1276
- // Test for the remaining candidates.
1277
- self . test_candidates_with_or (
1278
- span,
1279
- scrutinee_span,
1280
- unmatched_candidates,
1281
- block,
1282
- otherwise_block,
1283
- fake_borrows,
1284
- ) ;
1285
1275
}
1286
1276
1287
1277
/// Link up matched candidates.
@@ -1303,47 +1293,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1303
1293
/// * the [otherwise block] of the third pattern to a block with an
1304
1294
/// [`Unreachable` terminator](TerminatorKind::Unreachable).
1305
1295
///
1306
- /// In addition, we add fake edges from the otherwise blocks to the
1296
+ /// In addition, we later add fake edges from the otherwise blocks to the
1307
1297
/// pre-binding block of the next candidate in the original set of
1308
1298
/// candidates.
1309
1299
///
1310
1300
/// [pre-binding block]: Candidate::pre_binding_block
1311
1301
/// [otherwise block]: Candidate::otherwise_block
1312
- fn select_matched_candidates (
1302
+ fn select_matched_candidate (
1313
1303
& mut self ,
1314
- matched_candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1304
+ candidate : & mut Candidate < ' _ , ' tcx > ,
1315
1305
start_block : BasicBlock ,
1316
1306
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1317
- ) -> Option < BasicBlock > {
1318
- debug_assert ! (
1319
- !matched_candidates. is_empty( ) ,
1320
- "select_matched_candidates called with no candidates" ,
1321
- ) ;
1322
- debug_assert ! (
1323
- matched_candidates. iter( ) . all( |c| c. subcandidates. is_empty( ) ) ,
1324
- "subcandidates should be empty in select_matched_candidates" ,
1325
- ) ;
1307
+ ) -> BasicBlock {
1308
+ assert ! ( candidate. otherwise_block. is_none( ) ) ;
1309
+ assert ! ( candidate. pre_binding_block. is_none( ) ) ;
1310
+ assert ! ( candidate. subcandidates. is_empty( ) ) ;
1326
1311
1327
- // Insert a borrows of prefixes of places that are bound and are
1328
- // behind a dereference projection.
1329
- //
1330
- // These borrows are taken to avoid situations like the following:
1331
- //
1332
- // match x[10] {
1333
- // _ if { x = &[0]; false } => (),
1334
- // y => (), // Out of bounds array access!
1335
- // }
1336
- //
1337
- // match *x {
1338
- // // y is bound by reference in the guard and then by copy in the
1339
- // // arm, so y is 2 in the arm!
1340
- // y if { y == 1 && (x = &2) == () } => y,
1341
- // _ => 3,
1342
- // }
1343
1312
if let Some ( fake_borrows) = fake_borrows {
1344
- for Binding { source, .. } in
1345
- matched_candidates. iter ( ) . flat_map ( |candidate| & candidate. bindings )
1346
- {
1313
+ // Insert a borrows of prefixes of places that are bound and are
1314
+ // behind a dereference projection.
1315
+ //
1316
+ // These borrows are taken to avoid situations like the following:
1317
+ //
1318
+ // match x[10] {
1319
+ // _ if { x = &[0]; false } => (),
1320
+ // y => (), // Out of bounds array access!
1321
+ // }
1322
+ //
1323
+ // match *x {
1324
+ // // y is bound by reference in the guard and then by copy in the
1325
+ // // arm, so y is 2 in the arm!
1326
+ // y if { y == 1 && (x = &2) == () } => y,
1327
+ // _ => 3,
1328
+ // }
1329
+ for Binding { source, .. } in & candidate. bindings {
1347
1330
if let Some ( i) =
1348
1331
source. projection . iter ( ) . rposition ( |elem| elem == ProjectionElem :: Deref )
1349
1332
{
@@ -1357,38 +1340,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1357
1340
}
1358
1341
}
1359
1342
1360
- let fully_matched_with_guard = matched_candidates
1361
- . iter ( )
1362
- . position ( |c| !c. has_guard )
1363
- . unwrap_or ( matched_candidates. len ( ) - 1 ) ;
1364
-
1365
- let ( reachable_candidates, unreachable_candidates) =
1366
- matched_candidates. split_at_mut ( fully_matched_with_guard + 1 ) ;
1367
-
1368
- let mut next_prebinding = start_block;
1369
-
1370
- for candidate in reachable_candidates. iter_mut ( ) {
1371
- assert ! ( candidate. otherwise_block. is_none( ) ) ;
1372
- assert ! ( candidate. pre_binding_block. is_none( ) ) ;
1373
- candidate. pre_binding_block = Some ( next_prebinding) ;
1374
- if candidate. has_guard {
1375
- // Create the otherwise block for this candidate, which is the
1376
- // pre-binding block for the next candidate.
1377
- next_prebinding = self . cfg . start_new_block ( ) ;
1378
- candidate. otherwise_block = Some ( next_prebinding) ;
1379
- }
1380
- }
1381
-
1382
- debug ! (
1383
- "match_candidates: add pre_binding_blocks for unreachable {:?}" ,
1384
- unreachable_candidates,
1385
- ) ;
1386
- for candidate in unreachable_candidates {
1387
- assert ! ( candidate. pre_binding_block. is_none( ) ) ;
1388
- candidate. pre_binding_block = Some ( self . cfg . start_new_block ( ) ) ;
1343
+ candidate. pre_binding_block = Some ( start_block) ;
1344
+ let otherwise_block = self . cfg . start_new_block ( ) ;
1345
+ if candidate. has_guard {
1346
+ // Create the otherwise block for this candidate, which is the
1347
+ // pre-binding block for the next candidate.
1348
+ candidate. otherwise_block = Some ( otherwise_block) ;
1389
1349
}
1390
-
1391
- reachable_candidates. last_mut ( ) . unwrap ( ) . otherwise_block
1350
+ otherwise_block
1392
1351
}
1393
1352
1394
1353
/// Tests a candidate where there are only or-patterns left to test, or
0 commit comments