@@ -1235,53 +1235,43 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12351235 & mut self ,
12361236 span : Span ,
12371237 scrutinee_span : Span ,
1238- start_block : BasicBlock ,
1238+ mut start_block : BasicBlock ,
12391239 otherwise_block : BasicBlock ,
12401240 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
12411241 fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
12421242 ) {
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+ ) ;
12621273 }
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 ;
12741274 }
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- ) ;
12851275 }
12861276
12871277 /// Link up matched candidates.
@@ -1303,47 +1293,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13031293 /// * the [otherwise block] of the third pattern to a block with an
13041294 /// [`Unreachable` terminator](TerminatorKind::Unreachable).
13051295 ///
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
13071297 /// pre-binding block of the next candidate in the original set of
13081298 /// candidates.
13091299 ///
13101300 /// [pre-binding block]: Candidate::pre_binding_block
13111301 /// [otherwise block]: Candidate::otherwise_block
1312- fn select_matched_candidates (
1302+ fn select_matched_candidate (
13131303 & mut self ,
1314- matched_candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1304+ candidate : & mut Candidate < ' _ , ' tcx > ,
13151305 start_block : BasicBlock ,
13161306 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( ) ) ;
13261311
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- // }
13431312 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 {
13471330 if let Some ( i) =
13481331 source. projection . iter ( ) . rposition ( |elem| elem == ProjectionElem :: Deref )
13491332 {
@@ -1357,38 +1340,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13571340 }
13581341 }
13591342
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) ;
13891349 }
1390-
1391- reachable_candidates. last_mut ( ) . unwrap ( ) . otherwise_block
1350+ otherwise_block
13921351 }
13931352
13941353 /// Tests a candidate where there are only or-patterns left to test, or
0 commit comments