From 95b968ea6adbb25586a4514d941f692608f64343 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 21 Feb 2024 00:48:15 +0100 Subject: [PATCH] Move a bit of the logic to `match_simplified_candidates` --- .../rustc_mir_build/src/build/matches/mod.rs | 82 ++++++++++--------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index d25d6f833137..cf2ffc2a9843 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1260,9 +1260,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrows, ) } + [first, remaining @ ..] + if matches!(first.match_pairs[0].pattern.kind, PatKind::Or { .. }) => + { + // The first candidate has an or-pattern. + let remainder_start = self.cfg.start_new_block(); + // Test the or-pattern. + self.test_or_candidate( + span, + scrutinee_span, + first, + start_block, + remainder_start, + fake_borrows, + ); + // Test the remaining candidates. + self.match_candidates( + span, + scrutinee_span, + remainder_start, + otherwise_block, + remaining, + fake_borrows, + ); + } candidates => { - // The first candidate has some unsatisfied match pairs; we proceed to do more tests. - self.test_candidates_with_or( + // The first candidate has some unsatisfied match pairs that aren't or-patterns; we + // proceed to do more tests. + self.test_candidates( span, scrutinee_span, candidates, @@ -1350,8 +1375,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block } - /// Tests a candidate where there are only or-patterns left to test, or - /// forwards to [Builder::test_candidates]. + /// Tests a candidate whose first match-pair is an or-pattern. /// /// Given a pattern `(P | Q, R | S)` we (in principle) generate a CFG like /// so: @@ -1403,40 +1427,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// | /// ... /// ``` - fn test_candidates_with_or( + fn test_or_candidate( &mut self, span: Span, scrutinee_span: Span, - candidates: &mut [&mut Candidate<'_, 'tcx>], + candidate: &mut Candidate<'_, 'tcx>, start_block: BasicBlock, otherwise_block: BasicBlock, fake_borrows: &mut Option>>, ) { - let (first_candidate, remaining_candidates) = candidates.split_first_mut().unwrap(); - assert!(first_candidate.subcandidates.is_empty()); - if !matches!(first_candidate.match_pairs[0].pattern.kind, PatKind::Or { .. }) { - self.test_candidates( - span, - scrutinee_span, - candidates, - start_block, - otherwise_block, - fake_borrows, - ); - return; - } - - let match_pairs = mem::take(&mut first_candidate.match_pairs); + assert!(candidate.subcandidates.is_empty()); + let match_pairs = mem::take(&mut candidate.match_pairs); let (first_match_pair, remaining_match_pairs) = match_pairs.split_first().unwrap(); - let PatKind::Or { ref pats } = &first_match_pair.pattern.kind else { unreachable!() }; + let PatKind::Or { ref pats } = &first_match_pair.pattern.kind else { + bug!("Only call `test_or_candidate` if the first match pair is an or-pattern") + }; - let remainder_start = self.cfg.start_new_block(); let or_span = first_match_pair.pattern.span; // Test the alternatives of this or-pattern. self.test_or_pattern( - first_candidate, + candidate, start_block, - remainder_start, + otherwise_block, pats, or_span, &first_match_pair.place, @@ -1448,34 +1460,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // We could add them to the or-candidates before the call to `test_or_pattern` but this // would make it impossible to detect simplifiable or-patterns. That would guarantee // exponentially large CFGs for cases like `(1 | 2, 3 | 4, ...)`. - first_candidate.visit_leaves(|leaf_candidate| { + candidate.visit_leaves(|leaf_candidate| { assert!(leaf_candidate.match_pairs.is_empty()); leaf_candidate.match_pairs.extend(remaining_match_pairs.iter().cloned()); let or_start = leaf_candidate.pre_binding_block.unwrap(); // In a case like `(a | b, c | d)`, if `a` succeeds and `c | d` fails, we know `(b, // c | d)` will fail too. If there is no guard, we skip testing of `b` by branching - // directly to `remainder_start`. If there is a guard, we have to try `(b, c | d)`. - let or_otherwise = leaf_candidate.otherwise_block.unwrap_or(remainder_start); - self.test_candidates_with_or( + // directly to `otherwise_block`. If there is a guard, we have to try `(b, c | d)`. + let or_otherwise = leaf_candidate.otherwise_block.unwrap_or(otherwise_block); + self.match_simplified_candidates( span, scrutinee_span, - &mut [leaf_candidate], or_start, or_otherwise, + &mut [leaf_candidate], fake_borrows, ); }); } - - // Test the remaining candidates. - self.match_candidates( - span, - scrutinee_span, - remainder_start, - otherwise_block, - remaining_candidates, - fake_borrows, - ); } #[instrument(