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