From 585ca16e0bfa14e4f1d4b9235926034385bf9d7b Mon Sep 17 00:00:00 2001 From: Greaka Date: Sat, 6 Jul 2024 13:49:02 +0200 Subject: [PATCH 01/14] as_simd: fix comment to be in line with 507583a (#121201) --- library/core/src/slice/mod.rs | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 521c324820446..68508e85f8e14 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3959,17 +3959,8 @@ impl [T] { /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. /// - /// This is a safe wrapper around [`slice::align_to`], so has the same weak - /// postconditions as that method. You're only assured that - /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`. - /// - /// Notably, all of the following are possible: - /// - `prefix.len() >= LANES`. - /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`. - /// - `suffix.len() >= LANES`. - /// - /// That said, this is a safe method, so if you're only writing safe code, - /// then this can at most cause incorrect logic, not unsoundness. + /// This is a safe wrapper around [`slice::align_to`], so inherits the same + /// guarantees as that method. /// /// # Panics /// @@ -4033,17 +4024,8 @@ impl [T] { /// Split a mutable slice into a mutable prefix, a middle of aligned SIMD types, /// and a mutable suffix. /// - /// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak - /// postconditions as that method. You're only assured that - /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`. - /// - /// Notably, all of the following are possible: - /// - `prefix.len() >= LANES`. - /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`. - /// - `suffix.len() >= LANES`. - /// - /// That said, this is a safe method, so if you're only writing safe code, - /// then this can at most cause incorrect logic, not unsoundness. + /// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same + /// guarantees as that method. /// /// This is the mutable version of [`slice::as_simd`]; see that for examples. /// From 5bf50e66f9a7b1de3e074c276afc2e048afe65d1 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 30 Jun 2024 12:12:34 +0200 Subject: [PATCH 02/14] Move a function --- .../rustc_mir_build/src/build/matches/mod.rs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 5695c881ecc22..cc46a5603c3d5 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1624,6 +1624,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block } + /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new + /// subcandidate. Any candidate that has been expanded that way should be passed to + /// `finalize_or_candidate` after its subcandidates have been processed. + fn create_or_subcandidates<'pat>( + &mut self, + candidate: &mut Candidate<'pat, 'tcx>, + match_pair: MatchPair<'pat, 'tcx>, + ) { + let TestCase::Or { pats } = match_pair.test_case else { bug!() }; + debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats); + candidate.or_span = Some(match_pair.pattern.span); + candidate.subcandidates = pats + .into_vec() + .into_iter() + .map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard)) + .collect(); + candidate.subcandidates[0].false_edge_start_block = candidate.false_edge_start_block; + } + /// Simplify subcandidates and process any leftover match pairs. The candidate should have been /// expanded with `create_or_subcandidates`. /// @@ -1724,25 +1743,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new - /// subcandidate. Any candidate that has been expanded that way should be passed to - /// `finalize_or_candidate` after its subcandidates have been processed. - fn create_or_subcandidates<'pat>( - &mut self, - candidate: &mut Candidate<'pat, 'tcx>, - match_pair: MatchPair<'pat, 'tcx>, - ) { - let TestCase::Or { pats } = match_pair.test_case else { bug!() }; - debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats); - candidate.or_span = Some(match_pair.pattern.span); - candidate.subcandidates = pats - .into_vec() - .into_iter() - .map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard)) - .collect(); - candidate.subcandidates[0].false_edge_start_block = candidate.false_edge_start_block; - } - /// Try to merge all of the subcandidates of the given candidate into one. This avoids /// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The candidate should have been /// expanded with `create_or_subcandidates`. From bff4d213fac5ba32b51d320800700124205f6565 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 30 Jun 2024 12:18:31 +0200 Subject: [PATCH 03/14] Factor out the special handling of or-patterns --- .../rustc_mir_build/src/build/matches/mod.rs | 185 ++++++++++-------- 1 file changed, 104 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index cc46a5603c3d5..47f4fd0d07b59 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1427,108 +1427,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Note how we test `x` twice. This is the tradeoff of backtracking automata: we prefer smaller /// code size at the expense of non-optimal code paths. #[instrument(skip(self), level = "debug")] - fn match_candidates<'pat>( + fn match_candidates( &mut self, span: Span, scrutinee_span: Span, start_block: BasicBlock, otherwise_block: BasicBlock, - candidates: &mut [&mut Candidate<'pat, 'tcx>], + candidates: &mut [&mut Candidate<'_, 'tcx>], ) { - // We process or-patterns here. If any candidate starts with an or-pattern, we have to - // expand the or-pattern before we can proceed further. - // - // We can't expand them freely however. The rule is: if the candidate has an or-pattern as - // its only remaining match pair, we can expand it freely. If it has other match pairs, we - // can expand it but we can't process more candidates after it. - // - // If we didn't stop, the `otherwise` cases could get mixed up. E.g. in the following, - // or-pattern simplification (in `merge_trivial_subcandidates`) makes it so the `1` and `2` - // cases branch to a same block (which then tests `false`). If we took `(2, _)` in the same - // set of candidates, when we reach the block that tests `false` we don't know whether we - // came from `1` or `2`, hence we can't know where to branch on failure. - // ```ignore(illustrative) - // match (1, true) { - // (1 | 2, false) => {}, - // (2, _) => {}, - // _ => {} - // } - // ``` - // - // We therefore split the `candidates` slice in two, expand or-patterns in the first half, - // and process both halves separately. - let mut expand_until = 0; - for (i, candidate) in candidates.iter().enumerate() { - if matches!( + // If any candidate starts with an or-pattern, we have to expand the or-pattern before we + // can proceed further. + let expand_ors = candidates.iter().any(|candidate| { + matches!( &*candidate.match_pairs, [MatchPair { test_case: TestCase::Or { .. }, .. }, ..] - ) { - expand_until = i + 1; - if candidate.match_pairs.len() > 1 { - break; - } - } - if expand_until != 0 { - expand_until = i + 1; - } - } - let (candidates_to_expand, remaining_candidates) = candidates.split_at_mut(expand_until); - + ) + }); ensure_sufficient_stack(|| { - if candidates_to_expand.is_empty() { + if !expand_ors { // No candidates start with an or-pattern, we can continue. self.match_expanded_candidates( span, scrutinee_span, start_block, otherwise_block, - remaining_candidates, + candidates, ); } else { - // Expand one level of or-patterns for each candidate in `candidates_to_expand`. - let mut expanded_candidates = Vec::new(); - for candidate in candidates_to_expand.iter_mut() { - if let [MatchPair { test_case: TestCase::Or { .. }, .. }, ..] = - &*candidate.match_pairs - { - let or_match_pair = candidate.match_pairs.remove(0); - // Expand the or-pattern into subcandidates. - self.create_or_subcandidates(candidate, or_match_pair); - // Collect the newly created subcandidates. - for subcandidate in candidate.subcandidates.iter_mut() { - expanded_candidates.push(subcandidate); - } - } else { - expanded_candidates.push(candidate); - } - } - - // Process the expanded candidates. - let remainder_start = self.cfg.start_new_block(); - // There might be new or-patterns obtained from expanding the old ones, so we call - // `match_candidates` again. - self.match_candidates( + self.expand_and_match_or_candidates( span, scrutinee_span, start_block, - remainder_start, - expanded_candidates.as_mut_slice(), - ); - - // Simplify subcandidates and process any leftover match pairs. - for candidate in candidates_to_expand { - if !candidate.subcandidates.is_empty() { - self.finalize_or_candidate(span, scrutinee_span, candidate); - } - } - - // Process the remaining candidates. - self.match_candidates( - span, - scrutinee_span, - remainder_start, otherwise_block, - remaining_candidates, + candidates, ); } }); @@ -1624,6 +1555,98 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block } + /// Takes a list of candidates such that some of the candidates' first match pairs are + /// or-patterns, expands as many or-patterns as possible, and processes the resulting + /// candidates. + fn expand_and_match_or_candidates( + &mut self, + span: Span, + scrutinee_span: Span, + start_block: BasicBlock, + otherwise_block: BasicBlock, + candidates: &mut [&mut Candidate<'_, 'tcx>], + ) { + // We can't expand or-patterns freely. The rule is: if the candidate has an + // or-pattern as its only remaining match pair, we can expand it freely. If it has + // other match pairs, we can expand it but we can't process more candidates after + // it. + // + // If we didn't stop, the `otherwise` cases could get mixed up. E.g. in the + // following, or-pattern simplification (in `merge_trivial_subcandidates`) makes it + // so the `1` and `2` cases branch to a same block (which then tests `false`). If we + // took `(2, _)` in the same set of candidates, when we reach the block that tests + // `false` we don't know whether we came from `1` or `2`, hence we can't know where + // to branch on failure. + // + // ```ignore(illustrative) + // match (1, true) { + // (1 | 2, false) => {}, + // (2, _) => {}, + // _ => {} + // } + // ``` + // + // We therefore split the `candidates` slice in two, expand or-patterns in the first half, + // and process the rest separately. + let mut expand_until = 0; + for (i, candidate) in candidates.iter().enumerate() { + expand_until = i + 1; + if candidate.match_pairs.len() > 1 + && matches!(&candidate.match_pairs[0].test_case, TestCase::Or { .. }) + { + // The candidate has an or-pattern as well as more match pairs: we must + // split the candidates list here. + break; + } + } + let (candidates_to_expand, remaining_candidates) = candidates.split_at_mut(expand_until); + + // Expand one level of or-patterns for each candidate in `candidates_to_expand`. + let mut expanded_candidates = Vec::new(); + for candidate in candidates_to_expand.iter_mut() { + if let [MatchPair { test_case: TestCase::Or { .. }, .. }, ..] = &*candidate.match_pairs + { + let or_match_pair = candidate.match_pairs.remove(0); + // Expand the or-pattern into subcandidates. + self.create_or_subcandidates(candidate, or_match_pair); + // Collect the newly created subcandidates. + for subcandidate in candidate.subcandidates.iter_mut() { + expanded_candidates.push(subcandidate); + } + } else { + expanded_candidates.push(candidate); + } + } + + // Process the expanded candidates. + let remainder_start = self.cfg.start_new_block(); + // There might be new or-patterns obtained from expanding the old ones, so we call + // `match_candidates` again. + self.match_candidates( + span, + scrutinee_span, + start_block, + remainder_start, + expanded_candidates.as_mut_slice(), + ); + + // Simplify subcandidates and process any leftover match pairs. + for candidate in candidates_to_expand { + if !candidate.subcandidates.is_empty() { + self.finalize_or_candidate(span, scrutinee_span, candidate); + } + } + + // Process the remaining candidates. + self.match_candidates( + span, + scrutinee_span, + remainder_start, + otherwise_block, + remaining_candidates, + ); + } + /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new /// subcandidate. Any candidate that has been expanded that way should be passed to /// `finalize_or_candidate` after its subcandidates have been processed. From c5062f73181778af278321827ceedf1682ee0a8b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 30 Jun 2024 12:25:07 +0200 Subject: [PATCH 04/14] Move or-pattern expansion inside the main part of the algorithm --- .../rustc_mir_build/src/build/matches/mod.rs | 60 ++++++++----------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 47f4fd0d07b59..cc8a0e4b03822 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1119,6 +1119,11 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> { } } + /// Returns whether the first match pair of this candidate is an or-pattern. + fn starts_with_or_pattern(&self) -> bool { + matches!(&*self.match_pairs, [MatchPair { test_case: TestCase::Or { .. }, .. }, ..]) + } + /// Visit the leaf candidates (those with no subcandidates) contained in /// this candidate. fn visit_leaves<'a>(&'a mut self, mut visit_leaf: impl FnMut(&'a mut Self)) { @@ -1435,39 +1440,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block: BasicBlock, candidates: &mut [&mut Candidate<'_, 'tcx>], ) { - // If any candidate starts with an or-pattern, we have to expand the or-pattern before we - // can proceed further. - let expand_ors = candidates.iter().any(|candidate| { - matches!( - &*candidate.match_pairs, - [MatchPair { test_case: TestCase::Or { .. }, .. }, ..] - ) - }); ensure_sufficient_stack(|| { - if !expand_ors { - // No candidates start with an or-pattern, we can continue. - self.match_expanded_candidates( - span, - scrutinee_span, - start_block, - otherwise_block, - candidates, - ); - } else { - self.expand_and_match_or_candidates( - span, - scrutinee_span, - start_block, - otherwise_block, - candidates, - ); - } + self.match_candidates_with_enough_stack( + span, + scrutinee_span, + start_block, + otherwise_block, + candidates, + ) }); } - /// Construct the decision tree for `candidates`. Caller must ensure that no candidate in - /// `candidates` starts with an or-pattern. - fn match_expanded_candidates( + /// Construct the decision tree for `candidates`. Don't call this, call `match_candidates` + /// instead to reserve sufficient stack space. + fn match_candidates_with_enough_stack( &mut self, span: Span, scrutinee_span: Span, @@ -1492,12 +1478,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // The first candidate has satisfied all its match pairs; we link it up and continue // with the remaining candidates. start_block = self.select_matched_candidate(first, start_block); - self.match_expanded_candidates( + self.match_candidates(span, scrutinee_span, start_block, otherwise_block, remaining) + } + candidates if candidates.iter().any(|candidate| candidate.starts_with_or_pattern()) => { + // If any candidate starts with an or-pattern, we have to expand the or-pattern before we + // can proceed further. + self.expand_and_match_or_candidates( span, scrutinee_span, start_block, otherwise_block, - remaining, + candidates, ) } candidates => { @@ -1591,9 +1582,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut expand_until = 0; for (i, candidate) in candidates.iter().enumerate() { expand_until = i + 1; - if candidate.match_pairs.len() > 1 - && matches!(&candidate.match_pairs[0].test_case, TestCase::Or { .. }) - { + if candidate.match_pairs.len() > 1 && candidate.starts_with_or_pattern() { // The candidate has an or-pattern as well as more match pairs: we must // split the candidates list here. break; @@ -1604,8 +1593,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Expand one level of or-patterns for each candidate in `candidates_to_expand`. let mut expanded_candidates = Vec::new(); for candidate in candidates_to_expand.iter_mut() { - if let [MatchPair { test_case: TestCase::Or { .. }, .. }, ..] = &*candidate.match_pairs - { + if candidate.starts_with_or_pattern() { let or_match_pair = candidate.match_pairs.remove(0); // Expand the or-pattern into subcandidates. self.create_or_subcandidates(candidate, or_match_pair); From 8a222ffd6bb37a79bf517b3552008d9695cc8ae1 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 30 Jun 2024 12:29:46 +0200 Subject: [PATCH 05/14] Don't try to save an extra block This is preparation for the next commit. --- .../rustc_mir_build/src/build/matches/mod.rs | 22 ++-- .../issue_101867.main.built.after.mir | 18 ++- .../building/issue_49232.main.built.after.mir | 34 ++--- ...n_conditional.test_complex.built.after.mir | 122 ++++++++++-------- ...se_edges.full_tested_match.built.after.mir | 50 +++---- ...e_edges.full_tested_match2.built.after.mir | 54 ++++---- .../match_false_edges.main.built.after.mir | 34 ++--- .../simple_match.match_bool.built.after.mir | 8 +- .../simple_match.match_enum.built.after.mir | 26 ++-- ....constant_eq.SimplifyCfg-initial.after.mir | 28 ++-- ...mment_2.DeduplicateBlocks.panic-abort.diff | 48 ++++--- ...ment_2.DeduplicateBlocks.panic-unwind.diff | 48 ++++--- ...fg-initial.after-ElaborateDrops.after.diff | 26 ++-- ...fg-initial.after-ElaborateDrops.after.diff | 26 ++-- ...ut_second_or.SimplifyCfg-initial.after.mir | 8 +- 15 files changed, 284 insertions(+), 268 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index cc8a0e4b03822..458e2c5c40693 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2021,19 +2021,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // The block that we should branch to if none of the // `target_candidates` match. - let remainder_start = if !remaining_candidates.is_empty() { - let remainder_start = self.cfg.start_new_block(); - self.match_candidates( - span, - scrutinee_span, - remainder_start, - otherwise_block, - remaining_candidates, - ); - remainder_start - } else { - otherwise_block - }; + let remainder_start = self.cfg.start_new_block(); // For each outcome of test, process the candidates that still apply. let target_blocks: FxIndexMap<_, _> = target_candidates @@ -2061,6 +2049,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &test, target_blocks, ); + + self.match_candidates( + span, + scrutinee_span, + remainder_start, + otherwise_block, + remaining_candidates, + ); } } diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index 5c50b3db5cad6..728b5b23c6a63 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -27,13 +27,13 @@ fn main() -> () { StorageLive(_5); PlaceMention(_1); _6 = discriminant(_1); - switchInt(move _6) -> [1: bb4, otherwise: bb3]; + switchInt(move _6) -> [1: bb5, otherwise: bb4]; } bb1: { StorageLive(_3); StorageLive(_4); - _4 = begin_panic::<&str>(const "explicit panic") -> bb8; + _4 = begin_panic::<&str>(const "explicit panic") -> bb9; } bb2: { @@ -43,18 +43,22 @@ fn main() -> () { } bb3: { - goto -> bb7; + goto -> bb8; } bb4: { - falseEdge -> [real: bb6, imaginary: bb3]; + goto -> bb3; } bb5: { - goto -> bb3; + falseEdge -> [real: bb7, imaginary: bb3]; } bb6: { + goto -> bb4; + } + + bb7: { _5 = ((_1 as Some).0: u8); _0 = const (); StorageDead(_5); @@ -62,12 +66,12 @@ fn main() -> () { return; } - bb7: { + bb8: { StorageDead(_5); goto -> bb1; } - bb8 (cleanup): { + bb9 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir index d09a1748a8b36..ac7e530520a34 100644 --- a/tests/mir-opt/building/issue_49232.main.built.after.mir +++ b/tests/mir-opt/building/issue_49232.main.built.after.mir @@ -17,7 +17,7 @@ fn main() -> () { } bb1: { - falseUnwind -> [real: bb2, unwind: bb14]; + falseUnwind -> [real: bb2, unwind: bb15]; } bb2: { @@ -25,7 +25,7 @@ fn main() -> () { StorageLive(_3); _3 = const true; PlaceMention(_3); - switchInt(_3) -> [0: bb4, otherwise: bb6]; + switchInt(_3) -> [0: bb5, otherwise: bb7]; } bb3: { @@ -34,45 +34,49 @@ fn main() -> () { } bb4: { - falseEdge -> [real: bb8, imaginary: bb6]; + goto -> bb3; } bb5: { - goto -> bb3; + falseEdge -> [real: bb9, imaginary: bb7]; } bb6: { - _0 = const (); - goto -> bb13; + goto -> bb4; } bb7: { - goto -> bb3; + _0 = const (); + goto -> bb14; } bb8: { - _2 = const 4_i32; - goto -> bb11; + goto -> bb4; } bb9: { - unreachable; + _2 = const 4_i32; + goto -> bb12; } bb10: { - goto -> bb11; + unreachable; } bb11: { + goto -> bb12; + } + + bb12: { FakeRead(ForLet(None), _2); StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = &_2; - _5 = std::mem::drop::<&i32>(move _6) -> [return: bb12, unwind: bb14]; + _5 = std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb15]; } - bb12: { + bb13: { StorageDead(_6); StorageDead(_5); _1 = const (); @@ -80,13 +84,13 @@ fn main() -> () { goto -> bb1; } - bb13: { + bb14: { StorageDead(_3); StorageDead(_2); return; } - bb14 (cleanup): { + bb15 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir index 3e16efe6980d9..395b8b82bff41 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir +++ b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir @@ -19,180 +19,188 @@ fn test_complex() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = E::f() -> [return: bb1, unwind: bb34]; + _2 = E::f() -> [return: bb1, unwind: bb36]; } bb1: { PlaceMention(_2); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb3, otherwise: bb2]; + switchInt(move _3) -> [0: bb4, otherwise: bb3]; } bb2: { - goto -> bb21; + goto -> bb22; } bb3: { - falseEdge -> [real: bb5, imaginary: bb2]; + goto -> bb2; } bb4: { - goto -> bb2; + falseEdge -> [real: bb6, imaginary: bb2]; } bb5: { - StorageLive(_4); - _4 = always_true() -> [return: bb6, unwind: bb34]; + goto -> bb3; } bb6: { - switchInt(move _4) -> [0: bb8, otherwise: bb7]; + StorageLive(_4); + _4 = always_true() -> [return: bb7, unwind: bb36]; } bb7: { + switchInt(move _4) -> [0: bb9, otherwise: bb8]; + } + + bb8: { StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = Droppy(const 0_u8); _6 = (_7.0: u8); _5 = Gt(move _6, const 0_u8); - switchInt(move _5) -> [0: bb10, otherwise: bb9]; - } - - bb8: { - goto -> bb14; + switchInt(move _5) -> [0: bb11, otherwise: bb10]; } bb9: { - drop(_7) -> [return: bb11, unwind: bb34]; + goto -> bb15; } bb10: { - goto -> bb12; + drop(_7) -> [return: bb12, unwind: bb36]; } bb11: { - StorageDead(_7); - StorageDead(_6); - goto -> bb18; + goto -> bb13; } bb12: { - drop(_7) -> [return: bb13, unwind: bb34]; + StorageDead(_7); + StorageDead(_6); + goto -> bb19; } bb13: { + drop(_7) -> [return: bb14, unwind: bb36]; + } + + bb14: { StorageDead(_7); StorageDead(_6); - goto -> bb14; + goto -> bb15; } - bb14: { + bb15: { StorageLive(_8); StorageLive(_9); StorageLive(_10); _10 = Droppy(const 1_u8); _9 = (_10.0: u8); _8 = Gt(move _9, const 1_u8); - switchInt(move _8) -> [0: bb16, otherwise: bb15]; - } - - bb15: { - drop(_10) -> [return: bb17, unwind: bb34]; + switchInt(move _8) -> [0: bb17, otherwise: bb16]; } bb16: { - goto -> bb19; + drop(_10) -> [return: bb18, unwind: bb36]; } bb17: { - StorageDead(_10); - StorageDead(_9); - goto -> bb18; + goto -> bb20; } bb18: { - _1 = const (); - goto -> bb22; + StorageDead(_10); + StorageDead(_9); + goto -> bb19; } bb19: { - drop(_10) -> [return: bb20, unwind: bb34]; + _1 = const (); + goto -> bb23; } bb20: { - StorageDead(_10); - StorageDead(_9); - goto -> bb21; + drop(_10) -> [return: bb21, unwind: bb36]; } bb21: { - _1 = const (); + StorageDead(_10); + StorageDead(_9); goto -> bb22; } bb22: { + _1 = const (); + goto -> bb23; + } + + bb23: { StorageDead(_8); StorageDead(_5); StorageDead(_4); StorageDead(_2); StorageDead(_1); StorageLive(_11); - _11 = always_true() -> [return: bb23, unwind: bb34]; - } - - bb23: { - switchInt(move _11) -> [0: bb25, otherwise: bb24]; + _11 = always_true() -> [return: bb24, unwind: bb36]; } bb24: { - goto -> bb32; + switchInt(move _11) -> [0: bb26, otherwise: bb25]; } bb25: { - goto -> bb26; + goto -> bb34; } bb26: { - StorageLive(_12); - _12 = E::f() -> [return: bb27, unwind: bb34]; + goto -> bb27; } bb27: { - PlaceMention(_12); - _13 = discriminant(_12); - switchInt(move _13) -> [1: bb29, otherwise: bb28]; + StorageLive(_12); + _12 = E::f() -> [return: bb28, unwind: bb36]; } bb28: { - goto -> bb32; + PlaceMention(_12); + _13 = discriminant(_12); + switchInt(move _13) -> [1: bb31, otherwise: bb30]; } bb29: { - falseEdge -> [real: bb31, imaginary: bb28]; + goto -> bb34; } bb30: { - goto -> bb28; + goto -> bb29; } bb31: { - _0 = const (); - goto -> bb33; + falseEdge -> [real: bb33, imaginary: bb29]; } bb32: { - _0 = const (); - goto -> bb33; + goto -> bb30; } bb33: { + _0 = const (); + goto -> bb35; + } + + bb34: { + _0 = const (); + goto -> bb35; + } + + bb35: { StorageDead(_11); StorageDead(_12); return; } - bb34 (cleanup): { + bb36 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir index bade0fa4b45c8..623dd51c35849 100644 --- a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _4 = discriminant(_2); - switchInt(move _4) -> [0: bb5, 1: bb2, otherwise: bb1]; + switchInt(move _4) -> [0: bb6, 1: bb3, otherwise: bb2]; } bb1: { @@ -37,39 +37,43 @@ fn full_tested_match() -> () { } bb2: { - falseEdge -> [real: bb7, imaginary: bb3]; + goto -> bb1; } bb3: { - falseEdge -> [real: bb12, imaginary: bb5]; + falseEdge -> [real: bb8, imaginary: bb4]; } bb4: { - goto -> bb1; + falseEdge -> [real: bb13, imaginary: bb6]; } bb5: { - _1 = (const 3_i32, const 3_i32); - goto -> bb13; + goto -> bb2; } bb6: { - goto -> bb1; + _1 = (const 3_i32, const 3_i32); + goto -> bb14; } bb7: { + goto -> bb2; + } + + bb8: { StorageLive(_6); _6 = &((_2 as Some).0: i32); _3 = &fake shallow _2; StorageLive(_7); - _7 = guard() -> [return: bb8, unwind: bb16]; + _7 = guard() -> [return: bb9, unwind: bb17]; } - bb8: { - switchInt(move _7) -> [0: bb10, otherwise: bb9]; + bb9: { + switchInt(move _7) -> [0: bb11, otherwise: bb10]; } - bb9: { + bb10: { StorageDead(_7); FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _6); @@ -81,20 +85,20 @@ fn full_tested_match() -> () { StorageDead(_8); StorageDead(_5); StorageDead(_6); - goto -> bb13; + goto -> bb14; } - bb10: { - goto -> bb11; + bb11: { + goto -> bb12; } - bb11: { + bb12: { StorageDead(_7); StorageDead(_6); - goto -> bb3; + goto -> bb4; } - bb12: { + bb13: { StorageLive(_9); _9 = ((_2 as Some).0: i32); StorageLive(_10); @@ -102,10 +106,10 @@ fn full_tested_match() -> () { _1 = (const 2_i32, move _10); StorageDead(_10); StorageDead(_9); - goto -> bb13; + goto -> bb14; } - bb13: { + bb14: { PlaceMention(_1); StorageDead(_2); StorageDead(_1); @@ -113,16 +117,16 @@ fn full_tested_match() -> () { return; } - bb14: { + bb15: { FakeRead(ForMatchedPlace(None), _1); unreachable; } - bb15: { - goto -> bb14; + bb16: { + goto -> bb15; } - bb16 (cleanup): { + bb17 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir index 0d78bb8b23587..3cb037bf95601 100644 --- a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match2() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _4 = discriminant(_2); - switchInt(move _4) -> [0: bb5, 1: bb2, otherwise: bb1]; + switchInt(move _4) -> [0: bb6, 1: bb3, otherwise: bb2]; } bb1: { @@ -37,10 +37,14 @@ fn full_tested_match2() -> () { } bb2: { - falseEdge -> [real: bb7, imaginary: bb5]; + goto -> bb1; } bb3: { + falseEdge -> [real: bb8, imaginary: bb6]; + } + + bb4: { StorageLive(_9); _9 = ((_2 as Some).0: i32); StorageLive(_10); @@ -48,34 +52,34 @@ fn full_tested_match2() -> () { _1 = (const 2_i32, move _10); StorageDead(_10); StorageDead(_9); - goto -> bb13; - } - - bb4: { - goto -> bb1; + goto -> bb14; } bb5: { - falseEdge -> [real: bb12, imaginary: bb3]; + goto -> bb2; } bb6: { - goto -> bb1; + falseEdge -> [real: bb13, imaginary: bb4]; } bb7: { + goto -> bb2; + } + + bb8: { StorageLive(_6); _6 = &((_2 as Some).0: i32); _3 = &fake shallow _2; StorageLive(_7); - _7 = guard() -> [return: bb8, unwind: bb16]; + _7 = guard() -> [return: bb9, unwind: bb17]; } - bb8: { - switchInt(move _7) -> [0: bb10, otherwise: bb9]; + bb9: { + switchInt(move _7) -> [0: bb11, otherwise: bb10]; } - bb9: { + bb10: { StorageDead(_7); FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _6); @@ -87,25 +91,25 @@ fn full_tested_match2() -> () { StorageDead(_8); StorageDead(_5); StorageDead(_6); - goto -> bb13; + goto -> bb14; } - bb10: { - goto -> bb11; + bb11: { + goto -> bb12; } - bb11: { + bb12: { StorageDead(_7); StorageDead(_6); - falseEdge -> [real: bb3, imaginary: bb5]; + falseEdge -> [real: bb4, imaginary: bb6]; } - bb12: { + bb13: { _1 = (const 3_i32, const 3_i32); - goto -> bb13; + goto -> bb14; } - bb13: { + bb14: { PlaceMention(_1); StorageDead(_2); StorageDead(_1); @@ -113,16 +117,16 @@ fn full_tested_match2() -> () { return; } - bb14: { + bb15: { FakeRead(ForMatchedPlace(None), _1); unreachable; } - bb15: { - goto -> bb14; + bb16: { + goto -> bb15; } - bb16 (cleanup): { + bb17 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir index ebb75ae141a33..134517ad2aec2 100644 --- a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir @@ -38,8 +38,8 @@ fn main() -> () { StorageLive(_2); _2 = Option::::Some(const 1_i32); PlaceMention(_2); - _5 = discriminant(_2); - switchInt(move _5) -> [1: bb8, otherwise: bb2]; + _4 = discriminant(_2); + switchInt(move _4) -> [1: bb3, otherwise: bb2]; } bb1: { @@ -48,40 +48,40 @@ fn main() -> () { } bb2: { - falseEdge -> [real: bb15, imaginary: bb3]; + falseEdge -> [real: bb15, imaginary: bb5]; } bb3: { - _4 = discriminant(_2); - switchInt(move _4) -> [1: bb6, otherwise: bb4]; + falseEdge -> [real: bb10, imaginary: bb2]; } bb4: { - StorageLive(_14); - _14 = _2; - _1 = const 4_i32; - StorageDead(_14); - goto -> bb21; + goto -> bb2; } bb5: { - goto -> bb1; + _5 = discriminant(_2); + switchInt(move _5) -> [1: bb7, otherwise: bb6]; } bb6: { - falseEdge -> [real: bb16, imaginary: bb4]; + StorageLive(_14); + _14 = _2; + _1 = const 4_i32; + StorageDead(_14); + goto -> bb21; } bb7: { - goto -> bb4; + falseEdge -> [real: bb16, imaginary: bb6]; } bb8: { - falseEdge -> [real: bb10, imaginary: bb2]; + goto -> bb6; } bb9: { - goto -> bb2; + goto -> bb1; } bb10: { @@ -115,7 +115,7 @@ fn main() -> () { bb14: { StorageDead(_8); StorageDead(_7); - falseEdge -> [real: bb9, imaginary: bb2]; + falseEdge -> [real: bb4, imaginary: bb2]; } bb15: { @@ -161,7 +161,7 @@ fn main() -> () { StorageDead(_13); StorageDead(_12); StorageDead(_11); - falseEdge -> [real: bb7, imaginary: bb4]; + falseEdge -> [real: bb8, imaginary: bb6]; } bb21: { diff --git a/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir b/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir index faa2456fd1007..81b5ce304d0e9 100644 --- a/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir +++ b/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir @@ -6,7 +6,7 @@ fn match_bool(_1: bool) -> usize { bb0: { PlaceMention(_1); - switchInt(_1) -> [0: bb2, otherwise: bb4]; + switchInt(_1) -> [0: bb2, otherwise: bb3]; } bb1: { @@ -20,15 +20,15 @@ fn match_bool(_1: bool) -> usize { } bb3: { - goto -> bb1; + falseEdge -> [real: bb6, imaginary: bb2]; } bb4: { - falseEdge -> [real: bb6, imaginary: bb2]; + goto -> bb2; } bb5: { - goto -> bb2; + goto -> bb1; } bb6: { diff --git a/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir b/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir index 905aa19da706a..c2ea5bd441c31 100644 --- a/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir +++ b/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir @@ -8,7 +8,7 @@ fn match_enum(_1: E1) -> bool { bb0: { PlaceMention(_1); _2 = discriminant(_1); - switchInt(move _2) -> [0: bb3, 1: bb5, 2: bb7, otherwise: bb2]; + switchInt(move _2) -> [0: bb4, 1: bb6, 2: bb8, otherwise: bb3]; } bb1: { @@ -21,40 +21,44 @@ fn match_enum(_1: E1) -> bool { } bb3: { - goto -> bb9; + goto -> bb2; } bb4: { - goto -> bb2; + goto -> bb10; } bb5: { - goto -> bb9; + goto -> bb3; } bb6: { - goto -> bb2; + goto -> bb10; } bb7: { - _0 = const false; - goto -> bb11; + goto -> bb3; } bb8: { - goto -> bb2; + _0 = const false; + goto -> bb12; } bb9: { - falseEdge -> [real: bb10, imaginary: bb7]; + goto -> bb3; } bb10: { - _0 = const true; - goto -> bb11; + falseEdge -> [real: bb11, imaginary: bb8]; } bb11: { + _0 = const true; + goto -> bb12; + } + + bb12: { return; } } diff --git a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir index 060cd6132e3a0..2b5dbacc2d928 100644 --- a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir @@ -23,52 +23,52 @@ fn constant_eq(_1: &str, _2: bool) -> u32 { StorageDead(_5); StorageDead(_4); PlaceMention(_3); - _9 = ::eq((_3.0: &str), const "a") -> [return: bb11, unwind: bb19]; + _9 = ::eq((_3.0: &str), const "a") -> [return: bb9, unwind: bb19]; } bb1: { - switchInt((_3.1: bool)) -> [0: bb2, otherwise: bb3]; + switchInt((_3.1: bool)) -> [0: bb10, otherwise: bb11]; } bb2: { - _0 = const 5_u32; - goto -> bb18; + falseEdge -> [real: bb12, imaginary: bb5]; } bb3: { - falseEdge -> [real: bb17, imaginary: bb2]; + switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb4]; } bb4: { - falseEdge -> [real: bb12, imaginary: bb7]; + falseEdge -> [real: bb16, imaginary: bb1]; } bb5: { - switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb6]; + _8 = ::eq((_3.0: &str), const "b") -> [return: bb8, unwind: bb19]; } bb6: { - falseEdge -> [real: bb16, imaginary: bb1]; + switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb7]; } bb7: { - _8 = ::eq((_3.0: &str), const "b") -> [return: bb10, unwind: bb19]; + falseEdge -> [real: bb15, imaginary: bb3]; } bb8: { - switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb9]; + switchInt(move _8) -> [0: bb1, otherwise: bb6]; } bb9: { - falseEdge -> [real: bb15, imaginary: bb5]; + switchInt(move _9) -> [0: bb5, otherwise: bb2]; } bb10: { - switchInt(move _8) -> [0: bb1, otherwise: bb8]; + _0 = const 5_u32; + goto -> bb18; } bb11: { - switchInt(move _9) -> [0: bb7, otherwise: bb4]; + falseEdge -> [real: bb17, imaginary: bb10]; } bb12: { @@ -89,7 +89,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 { bb14: { StorageDead(_10); - falseEdge -> [real: bb5, imaginary: bb7]; + falseEdge -> [real: bb3, imaginary: bb5]; } bb15: { diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff index 938b9bb14ade2..3a5762e4f3d1e 100644 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff +++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff @@ -22,59 +22,55 @@ bb1: { StorageDead(_3); - _7 = Len((*_2)); - _8 = const 4_usize; - _9 = Ge(move _7, move _8); -- switchInt(move _9) -> [0: bb2, otherwise: bb7]; -+ switchInt(move _9) -> [0: bb2, otherwise: bb6]; + _4 = Len((*_2)); + _5 = const 4_usize; + _6 = Ge(move _4, move _5); + switchInt(move _6) -> [0: bb2, otherwise: bb3]; } bb2: { - _4 = Len((*_2)); - _5 = const 3_usize; - _6 = Ge(move _4, move _5); -- switchInt(move _6) -> [0: bb3, otherwise: bb4]; -+ switchInt(move _6) -> [0: bb10, otherwise: bb3]; + _7 = Len((*_2)); + _8 = const 3_usize; + _9 = Ge(move _7, move _8); +- switchInt(move _9) -> [0: bb7, otherwise: bb8]; ++ switchInt(move _9) -> [0: bb10, otherwise: bb7]; } bb3: { -- _0 = const false; -- goto -> bb14; -+ switchInt((*_2)[0 of 3]) -> [47: bb4, otherwise: bb10]; + switchInt((*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; } bb4: { -- switchInt((*_2)[0 of 3]) -> [47: bb5, otherwise: bb3]; -+ switchInt((*_2)[1 of 3]) -> [47: bb5, otherwise: bb10]; + switchInt((*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; } bb5: { -- switchInt((*_2)[1 of 3]) -> [47: bb6, otherwise: bb3]; -+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10]; + switchInt((*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; } bb6: { -- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb3]; -+ switchInt((*_2)[0 of 4]) -> [47: bb7, otherwise: bb2]; +- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; ++ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2]; } bb7: { -- switchInt((*_2)[0 of 4]) -> [47: bb8, otherwise: bb2]; -+ switchInt((*_2)[1 of 4]) -> [47: bb8, otherwise: bb2]; +- _0 = const false; +- goto -> bb14; ++ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10]; } bb8: { -- switchInt((*_2)[1 of 4]) -> [47: bb9, otherwise: bb2]; -+ switchInt((*_2)[2 of 4]) -> [47: bb9, otherwise: bb2]; +- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; ++ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10]; } bb9: { -- switchInt((*_2)[2 of 4]) -> [47: bb10, otherwise: bb2]; -+ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2]; +- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; ++ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10]; } bb10: { -- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; +- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7]; - } - - bb11: { diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff index ce89694076b04..21b197d2f270c 100644 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff +++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff @@ -22,59 +22,55 @@ bb1: { StorageDead(_3); - _7 = Len((*_2)); - _8 = const 4_usize; - _9 = Ge(move _7, move _8); -- switchInt(move _9) -> [0: bb2, otherwise: bb7]; -+ switchInt(move _9) -> [0: bb2, otherwise: bb6]; + _4 = Len((*_2)); + _5 = const 4_usize; + _6 = Ge(move _4, move _5); + switchInt(move _6) -> [0: bb2, otherwise: bb3]; } bb2: { - _4 = Len((*_2)); - _5 = const 3_usize; - _6 = Ge(move _4, move _5); -- switchInt(move _6) -> [0: bb3, otherwise: bb4]; -+ switchInt(move _6) -> [0: bb10, otherwise: bb3]; + _7 = Len((*_2)); + _8 = const 3_usize; + _9 = Ge(move _7, move _8); +- switchInt(move _9) -> [0: bb7, otherwise: bb8]; ++ switchInt(move _9) -> [0: bb10, otherwise: bb7]; } bb3: { -- _0 = const false; -- goto -> bb14; -+ switchInt((*_2)[0 of 3]) -> [47: bb4, otherwise: bb10]; + switchInt((*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; } bb4: { -- switchInt((*_2)[0 of 3]) -> [47: bb5, otherwise: bb3]; -+ switchInt((*_2)[1 of 3]) -> [47: bb5, otherwise: bb10]; + switchInt((*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; } bb5: { -- switchInt((*_2)[1 of 3]) -> [47: bb6, otherwise: bb3]; -+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10]; + switchInt((*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; } bb6: { -- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb3]; -+ switchInt((*_2)[0 of 4]) -> [47: bb7, otherwise: bb2]; +- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; ++ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2]; } bb7: { -- switchInt((*_2)[0 of 4]) -> [47: bb8, otherwise: bb2]; -+ switchInt((*_2)[1 of 4]) -> [47: bb8, otherwise: bb2]; +- _0 = const false; +- goto -> bb14; ++ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10]; } bb8: { -- switchInt((*_2)[1 of 4]) -> [47: bb9, otherwise: bb2]; -+ switchInt((*_2)[2 of 4]) -> [47: bb9, otherwise: bb2]; +- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; ++ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10]; } bb9: { -- switchInt((*_2)[2 of 4]) -> [47: bb10, otherwise: bb2]; -+ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2]; +- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; ++ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10]; } bb10: { -- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; +- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7]; - } - - bb11: { diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 209f0d09c2943..4f29e5244d7c2 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -32,25 +32,33 @@ bb0: { PlaceMention(_2); -- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1]; +- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1]; + switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1]; } bb1: { -- switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2]; +- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3]; + switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2]; } bb2: { -- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3]; +- falseEdge -> [real: bb8, imaginary: bb1]; + switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; } bb3: { -- falseEdge -> [real: bb20, imaginary: bb4]; +- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5]; - } - - bb4: { +- falseEdge -> [real: bb13, imaginary: bb3]; +- } +- +- bb5: { +- falseEdge -> [real: bb20, imaginary: bb6]; +- } +- +- bb6: { StorageLive(_15); _15 = (_2.1: bool); StorageLive(_16); @@ -59,14 +67,6 @@ + goto -> bb16; } -- bb5: { -- falseEdge -> [real: bb13, imaginary: bb2]; -- } -- -- bb6: { -- falseEdge -> [real: bb8, imaginary: bb1]; -- } -- - bb7: { + bb4: { _0 = const 1_i32; @@ -184,7 +184,7 @@ StorageDead(_12); StorageDead(_8); StorageDead(_6); -- falseEdge -> [real: bb2, imaginary: bb2]; +- falseEdge -> [real: bb3, imaginary: bb3]; + goto -> bb2; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 209f0d09c2943..4f29e5244d7c2 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -32,25 +32,33 @@ bb0: { PlaceMention(_2); -- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1]; +- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1]; + switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1]; } bb1: { -- switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2]; +- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3]; + switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2]; } bb2: { -- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3]; +- falseEdge -> [real: bb8, imaginary: bb1]; + switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; } bb3: { -- falseEdge -> [real: bb20, imaginary: bb4]; +- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5]; - } - - bb4: { +- falseEdge -> [real: bb13, imaginary: bb3]; +- } +- +- bb5: { +- falseEdge -> [real: bb20, imaginary: bb6]; +- } +- +- bb6: { StorageLive(_15); _15 = (_2.1: bool); StorageLive(_16); @@ -59,14 +67,6 @@ + goto -> bb16; } -- bb5: { -- falseEdge -> [real: bb13, imaginary: bb2]; -- } -- -- bb6: { -- falseEdge -> [real: bb8, imaginary: bb1]; -- } -- - bb7: { + bb4: { _0 = const 1_i32; @@ -184,7 +184,7 @@ StorageDead(_12); StorageDead(_8); StorageDead(_6); -- falseEdge -> [real: bb2, imaginary: bb2]; +- falseEdge -> [real: bb3, imaginary: bb3]; + goto -> bb2; } diff --git a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir index 56edd38a6da4c..775bc8afd7bdb 100644 --- a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir @@ -18,7 +18,7 @@ fn shortcut_second_or() -> () { _1 = (move _2, const 0_i32); StorageDead(_2); PlaceMention(_1); - switchInt(((_1.0: (i32, i32)).0: i32)) -> [0: bb4, otherwise: bb2]; + switchInt(((_1.0: (i32, i32)).0: i32)) -> [0: bb3, otherwise: bb2]; } bb1: { @@ -27,15 +27,15 @@ fn shortcut_second_or() -> () { } bb2: { - switchInt(((_1.0: (i32, i32)).1: i32)) -> [1: bb3, otherwise: bb1]; + switchInt(((_1.0: (i32, i32)).1: i32)) -> [1: bb4, otherwise: bb1]; } bb3: { - switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb1]; + switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb1]; } bb4: { - switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb1]; + switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb1]; } bb5: { From fc40247c6b8d67da1a48d0ee73f42d9a239d2ae0 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 30 Jun 2024 12:56:13 +0200 Subject: [PATCH 06/14] Factor out the "process remaining candidates" cases --- .../rustc_mir_build/src/build/matches/mod.rs | 74 ++++++++----------- 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 458e2c5c40693..6eb8efc54ec3c 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1457,7 +1457,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, span: Span, scrutinee_span: Span, - mut start_block: BasicBlock, + start_block: BasicBlock, otherwise_block: BasicBlock, candidates: &mut [&mut Candidate<'_, 'tcx>], ) { @@ -1467,41 +1467,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - match candidates { + // Process a prefix of the candidates. + let rest = match candidates { [] => { - // If there are no candidates that still need testing, we're done. Since all matches are - // exhaustive, execution should never reach this point. + // If there are no candidates that still need testing, we're done. let source_info = self.source_info(span); self.cfg.goto(start_block, source_info, otherwise_block); + return; } [first, remaining @ ..] if first.match_pairs.is_empty() => { // The first candidate has satisfied all its match pairs; we link it up and continue // with the remaining candidates. - start_block = self.select_matched_candidate(first, start_block); - self.match_candidates(span, scrutinee_span, start_block, otherwise_block, remaining) + let remainder_start = self.select_matched_candidate(first, start_block); + remainder_start.and(remaining) } candidates if candidates.iter().any(|candidate| candidate.starts_with_or_pattern()) => { // If any candidate starts with an or-pattern, we have to expand the or-pattern before we // can proceed further. - self.expand_and_match_or_candidates( - span, - scrutinee_span, - start_block, - otherwise_block, - candidates, - ) + self.expand_and_match_or_candidates(span, scrutinee_span, start_block, candidates) } candidates => { // The first candidate has some unsatisfied match pairs; we proceed to do more tests. - self.test_candidates( - span, - scrutinee_span, - candidates, - start_block, - otherwise_block, - ); + self.test_candidates(span, scrutinee_span, candidates, start_block) } - } + }; + + // Process any candidates that remain. + let BlockAnd(start_block, remaining_candidates) = rest; + self.match_candidates( + span, + scrutinee_span, + start_block, + otherwise_block, + remaining_candidates, + ); } /// Link up matched candidates. @@ -1547,16 +1546,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /// Takes a list of candidates such that some of the candidates' first match pairs are - /// or-patterns, expands as many or-patterns as possible, and processes the resulting - /// candidates. - fn expand_and_match_or_candidates( + /// or-patterns. This expands as many or-patterns as possible and processes the resulting + /// candidates. Returns the unprocessed candidates if any. + fn expand_and_match_or_candidates<'pat, 'b, 'c>( &mut self, span: Span, scrutinee_span: Span, start_block: BasicBlock, - otherwise_block: BasicBlock, - candidates: &mut [&mut Candidate<'_, 'tcx>], - ) { + candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], + ) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> { // We can't expand or-patterns freely. The rule is: if the candidate has an // or-pattern as its only remaining match pair, we can expand it freely. If it has // other match pairs, we can expand it but we can't process more candidates after @@ -1625,14 +1623,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - // Process the remaining candidates. - self.match_candidates( - span, - scrutinee_span, - remainder_start, - otherwise_block, - remaining_candidates, - ); + remainder_start.and(remaining_candidates) } /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new @@ -2003,14 +1994,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// } /// # } /// ``` + /// + /// We return the unprocessed candidates. fn test_candidates<'pat, 'b, 'c>( &mut self, span: Span, scrutinee_span: Span, candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], start_block: BasicBlock, - otherwise_block: BasicBlock, - ) { + ) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> { // Extract the match-pair from the highest priority candidate and build a test from it. let (match_place, test) = self.pick_test(candidates); @@ -2050,13 +2042,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { target_blocks, ); - self.match_candidates( - span, - scrutinee_span, - remainder_start, - otherwise_block, - remaining_candidates, - ); + remainder_start.and(remaining_candidates) } } From 3e030b38ef1593592d6f4eb4144630d9abeb43b4 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 30 Jun 2024 13:21:12 +0200 Subject: [PATCH 07/14] Return the `otherwise_block` instead of passing it as argument This saves a few blocks and matches the common `unpack!` paradigm. --- .../rustc_mir_build/src/build/matches/mod.rs | 86 +++++------- .../issue_101867.main.built.after.mir | 18 +-- .../building/issue_49232.main.built.after.mir | 34 +++-- ...n_conditional.test_complex.built.after.mir | 122 ++++++++---------- ...se_edges.full_tested_match.built.after.mir | 50 +++---- ...e_edges.full_tested_match2.built.after.mir | 54 ++++---- .../match_false_edges.main.built.after.mir | 84 ++++++------ .../simple_match.match_bool.built.after.mir | 22 ++-- .../simple_match.match_enum.built.after.mir | 28 ++-- ...e_out.move_out_by_subslice.built.after.mir | 34 +++-- ...move_out.move_out_from_end.built.after.mir | 34 +++-- tests/mir-opt/issue_72181.bar.built.after.mir | 4 - .../mir-opt/issue_72181.main.built.after.mir | 16 +-- tests/mir-opt/issue_72181_1.f.built.after.mir | 6 +- tests/mir-opt/issue_91633.bar.built.after.mir | 14 +- tests/mir-opt/issue_91633.hey.built.after.mir | 8 +- .../issue_99325.main.built.after.32bit.mir | 82 ++++++------ .../issue_99325.main.built.after.64bit.mir | 82 ++++++------ ...ut_second_or.SimplifyCfg-initial.after.mir | 16 +-- 19 files changed, 333 insertions(+), 461 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 6eb8efc54ec3c..2fc510a222b60 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1313,11 +1313,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidates: &mut [&mut Candidate<'pat, 'tcx>], refutable: bool, ) -> BasicBlock { + // This will generate code to test scrutinee_place and branch to the appropriate arm block. // See the doc comment on `match_candidates` for why we have an otherwise block. - let otherwise_block = self.cfg.start_new_block(); - - // This will generate code to test scrutinee_place and branch to the appropriate arm block - self.match_candidates(match_start_span, scrutinee_span, block, otherwise_block, candidates); + let otherwise_block = + self.match_candidates(match_start_span, scrutinee_span, block, candidates); // Link each leaf candidate to the `false_edge_start_block` of the next one. let mut previous_candidate: Option<&mut Candidate<'_, '_>> = None; @@ -1368,27 +1367,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block } - /// The main match algorithm. It begins with a set of candidates - /// `candidates` and has the job of generating code to determine - /// which of these candidates, if any, is the correct one. The + /// The main match algorithm. It begins with a set of candidates `candidates` and has the job of + /// generating code that branches to an appropriate block if the scrutinee matches one of these + /// candidates. The /// candidates are sorted such that the first item in the list /// has the highest priority. When a candidate is found to match /// the value, we will set and generate a branch to the appropriate /// pre-binding block. /// - /// If we find that *NONE* of the candidates apply, we branch to `otherwise_block`. + /// If none of the candidates apply, we continue to the returned `otherwise_block`. /// /// It might be surprising that the input can be non-exhaustive. - /// Indeed, initially, it is not, because all matches are + /// Indeed, for matches, initially, it is not, because all matches are /// exhaustive in Rust. But during processing we sometimes divide /// up the list of candidates and recurse with a non-exhaustive /// list. This is how our lowering approach (called "backtracking /// automaton" in the literature) works. /// See [`Builder::test_candidates`] for more details. /// - /// If `fake_borrows` is `Some`, then places which need fake borrows - /// will be added to it. - /// /// For an example of how we use `otherwise_block`, consider: /// ``` /// # fn foo((x, y): (bool, bool)) -> u32 { @@ -1413,7 +1409,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// } /// if y { /// if x { - /// // This is actually unreachable because the `(true, true)` case was handled above. + /// // This is actually unreachable because the `(true, true)` case was handled above, + /// // but we don't know that from within the lowering algorithm. /// // continue /// } else { /// return 3 @@ -1430,25 +1427,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// the algorithm. For more details on why we lower like this, see [`Builder::test_candidates`]. /// /// Note how we test `x` twice. This is the tradeoff of backtracking automata: we prefer smaller - /// code size at the expense of non-optimal code paths. + /// code size so we accept non-optimal code paths. #[instrument(skip(self), level = "debug")] fn match_candidates( &mut self, span: Span, scrutinee_span: Span, start_block: BasicBlock, - otherwise_block: BasicBlock, candidates: &mut [&mut Candidate<'_, 'tcx>], - ) { + ) -> BasicBlock { ensure_sufficient_stack(|| { - self.match_candidates_with_enough_stack( - span, - scrutinee_span, - start_block, - otherwise_block, - candidates, - ) - }); + self.match_candidates_with_enough_stack(span, scrutinee_span, start_block, candidates) + }) } /// Construct the decision tree for `candidates`. Don't call this, call `match_candidates` @@ -1458,9 +1448,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, scrutinee_span: Span, start_block: BasicBlock, - otherwise_block: BasicBlock, candidates: &mut [&mut Candidate<'_, 'tcx>], - ) { + ) -> BasicBlock { if let [first, ..] = candidates { if first.false_edge_start_block.is_none() { first.false_edge_start_block = Some(start_block); @@ -1471,9 +1460,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rest = match candidates { [] => { // If there are no candidates that still need testing, we're done. - let source_info = self.source_info(span); - self.cfg.goto(start_block, source_info, otherwise_block); - return; + return start_block; } [first, remaining @ ..] if first.match_pairs.is_empty() => { // The first candidate has satisfied all its match pairs; we link it up and continue @@ -1494,13 +1481,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Process any candidates that remain. let BlockAnd(start_block, remaining_candidates) = rest; - self.match_candidates( - span, - scrutinee_span, - start_block, - otherwise_block, - remaining_candidates, - ); + self.match_candidates(span, scrutinee_span, start_block, remaining_candidates) } /// Link up matched candidates. @@ -1605,14 +1586,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } // Process the expanded candidates. - let remainder_start = self.cfg.start_new_block(); - // There might be new or-patterns obtained from expanding the old ones, so we call - // `match_candidates` again. - self.match_candidates( + let remainder_start = self.match_candidates( span, scrutinee_span, start_block, - remainder_start, expanded_candidates.as_mut_slice(), ); @@ -1711,6 +1688,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.merge_trivial_subcandidates(candidate); if !candidate.match_pairs.is_empty() { + let or_span = candidate.or_span.unwrap_or(candidate.extra_data.span); + let source_info = self.source_info(or_span); // If more match pairs remain, test them after each subcandidate. // 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 @@ -1724,6 +1703,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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(); + let otherwise = + self.match_candidates(span, scrutinee_span, or_start, &mut [leaf_candidate]); // In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q, // R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching // directly to `last_otherwise`. If there is a guard, @@ -1734,13 +1715,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { last_otherwise.unwrap() }; - self.match_candidates( - span, - scrutinee_span, - or_start, - or_otherwise, - &mut [leaf_candidate], - ); + self.cfg.goto(otherwise, source_info, or_otherwise); }); } } @@ -2019,15 +1994,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let target_blocks: FxIndexMap<_, _> = target_candidates .into_iter() .map(|(branch, mut candidates)| { - let candidate_start = self.cfg.start_new_block(); - self.match_candidates( - span, - scrutinee_span, - candidate_start, - remainder_start, - &mut *candidates, - ); - (branch, candidate_start) + let branch_start = self.cfg.start_new_block(); + let branch_otherwise = + self.match_candidates(span, scrutinee_span, branch_start, &mut *candidates); + let source_info = self.source_info(span); + self.cfg.goto(branch_otherwise, source_info, remainder_start); + (branch, branch_start) }) .collect(); diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index 728b5b23c6a63..5c50b3db5cad6 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -27,13 +27,13 @@ fn main() -> () { StorageLive(_5); PlaceMention(_1); _6 = discriminant(_1); - switchInt(move _6) -> [1: bb5, otherwise: bb4]; + switchInt(move _6) -> [1: bb4, otherwise: bb3]; } bb1: { StorageLive(_3); StorageLive(_4); - _4 = begin_panic::<&str>(const "explicit panic") -> bb9; + _4 = begin_panic::<&str>(const "explicit panic") -> bb8; } bb2: { @@ -43,22 +43,18 @@ fn main() -> () { } bb3: { - goto -> bb8; + goto -> bb7; } bb4: { - goto -> bb3; + falseEdge -> [real: bb6, imaginary: bb3]; } bb5: { - falseEdge -> [real: bb7, imaginary: bb3]; + goto -> bb3; } bb6: { - goto -> bb4; - } - - bb7: { _5 = ((_1 as Some).0: u8); _0 = const (); StorageDead(_5); @@ -66,12 +62,12 @@ fn main() -> () { return; } - bb8: { + bb7: { StorageDead(_5); goto -> bb1; } - bb9 (cleanup): { + bb8 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir index ac7e530520a34..d09a1748a8b36 100644 --- a/tests/mir-opt/building/issue_49232.main.built.after.mir +++ b/tests/mir-opt/building/issue_49232.main.built.after.mir @@ -17,7 +17,7 @@ fn main() -> () { } bb1: { - falseUnwind -> [real: bb2, unwind: bb15]; + falseUnwind -> [real: bb2, unwind: bb14]; } bb2: { @@ -25,7 +25,7 @@ fn main() -> () { StorageLive(_3); _3 = const true; PlaceMention(_3); - switchInt(_3) -> [0: bb5, otherwise: bb7]; + switchInt(_3) -> [0: bb4, otherwise: bb6]; } bb3: { @@ -34,49 +34,45 @@ fn main() -> () { } bb4: { - goto -> bb3; + falseEdge -> [real: bb8, imaginary: bb6]; } bb5: { - falseEdge -> [real: bb9, imaginary: bb7]; + goto -> bb3; } bb6: { - goto -> bb4; + _0 = const (); + goto -> bb13; } bb7: { - _0 = const (); - goto -> bb14; + goto -> bb3; } bb8: { - goto -> bb4; + _2 = const 4_i32; + goto -> bb11; } bb9: { - _2 = const 4_i32; - goto -> bb12; + unreachable; } bb10: { - unreachable; + goto -> bb11; } bb11: { - goto -> bb12; - } - - bb12: { FakeRead(ForLet(None), _2); StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = &_2; - _5 = std::mem::drop::<&i32>(move _6) -> [return: bb13, unwind: bb15]; + _5 = std::mem::drop::<&i32>(move _6) -> [return: bb12, unwind: bb14]; } - bb13: { + bb12: { StorageDead(_6); StorageDead(_5); _1 = const (); @@ -84,13 +80,13 @@ fn main() -> () { goto -> bb1; } - bb14: { + bb13: { StorageDead(_3); StorageDead(_2); return; } - bb15 (cleanup): { + bb14 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir index 395b8b82bff41..3e16efe6980d9 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir +++ b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir @@ -19,188 +19,180 @@ fn test_complex() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = E::f() -> [return: bb1, unwind: bb36]; + _2 = E::f() -> [return: bb1, unwind: bb34]; } bb1: { PlaceMention(_2); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb4, otherwise: bb3]; + switchInt(move _3) -> [0: bb3, otherwise: bb2]; } bb2: { - goto -> bb22; + goto -> bb21; } bb3: { - goto -> bb2; + falseEdge -> [real: bb5, imaginary: bb2]; } bb4: { - falseEdge -> [real: bb6, imaginary: bb2]; + goto -> bb2; } bb5: { - goto -> bb3; + StorageLive(_4); + _4 = always_true() -> [return: bb6, unwind: bb34]; } bb6: { - StorageLive(_4); - _4 = always_true() -> [return: bb7, unwind: bb36]; + switchInt(move _4) -> [0: bb8, otherwise: bb7]; } bb7: { - switchInt(move _4) -> [0: bb9, otherwise: bb8]; - } - - bb8: { StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = Droppy(const 0_u8); _6 = (_7.0: u8); _5 = Gt(move _6, const 0_u8); - switchInt(move _5) -> [0: bb11, otherwise: bb10]; + switchInt(move _5) -> [0: bb10, otherwise: bb9]; + } + + bb8: { + goto -> bb14; } bb9: { - goto -> bb15; + drop(_7) -> [return: bb11, unwind: bb34]; } bb10: { - drop(_7) -> [return: bb12, unwind: bb36]; + goto -> bb12; } bb11: { - goto -> bb13; - } - - bb12: { StorageDead(_7); StorageDead(_6); - goto -> bb19; + goto -> bb18; } - bb13: { - drop(_7) -> [return: bb14, unwind: bb36]; + bb12: { + drop(_7) -> [return: bb13, unwind: bb34]; } - bb14: { + bb13: { StorageDead(_7); StorageDead(_6); - goto -> bb15; + goto -> bb14; } - bb15: { + bb14: { StorageLive(_8); StorageLive(_9); StorageLive(_10); _10 = Droppy(const 1_u8); _9 = (_10.0: u8); _8 = Gt(move _9, const 1_u8); - switchInt(move _8) -> [0: bb17, otherwise: bb16]; + switchInt(move _8) -> [0: bb16, otherwise: bb15]; } - bb16: { - drop(_10) -> [return: bb18, unwind: bb36]; + bb15: { + drop(_10) -> [return: bb17, unwind: bb34]; } - bb17: { - goto -> bb20; + bb16: { + goto -> bb19; } - bb18: { + bb17: { StorageDead(_10); StorageDead(_9); - goto -> bb19; + goto -> bb18; } - bb19: { + bb18: { _1 = const (); - goto -> bb23; + goto -> bb22; } - bb20: { - drop(_10) -> [return: bb21, unwind: bb36]; + bb19: { + drop(_10) -> [return: bb20, unwind: bb34]; } - bb21: { + bb20: { StorageDead(_10); StorageDead(_9); - goto -> bb22; + goto -> bb21; } - bb22: { + bb21: { _1 = const (); - goto -> bb23; + goto -> bb22; } - bb23: { + bb22: { StorageDead(_8); StorageDead(_5); StorageDead(_4); StorageDead(_2); StorageDead(_1); StorageLive(_11); - _11 = always_true() -> [return: bb24, unwind: bb36]; + _11 = always_true() -> [return: bb23, unwind: bb34]; + } + + bb23: { + switchInt(move _11) -> [0: bb25, otherwise: bb24]; } bb24: { - switchInt(move _11) -> [0: bb26, otherwise: bb25]; + goto -> bb32; } bb25: { - goto -> bb34; + goto -> bb26; } bb26: { - goto -> bb27; + StorageLive(_12); + _12 = E::f() -> [return: bb27, unwind: bb34]; } bb27: { - StorageLive(_12); - _12 = E::f() -> [return: bb28, unwind: bb36]; + PlaceMention(_12); + _13 = discriminant(_12); + switchInt(move _13) -> [1: bb29, otherwise: bb28]; } bb28: { - PlaceMention(_12); - _13 = discriminant(_12); - switchInt(move _13) -> [1: bb31, otherwise: bb30]; + goto -> bb32; } bb29: { - goto -> bb34; + falseEdge -> [real: bb31, imaginary: bb28]; } bb30: { - goto -> bb29; + goto -> bb28; } bb31: { - falseEdge -> [real: bb33, imaginary: bb29]; - } - - bb32: { - goto -> bb30; - } - - bb33: { _0 = const (); - goto -> bb35; + goto -> bb33; } - bb34: { + bb32: { _0 = const (); - goto -> bb35; + goto -> bb33; } - bb35: { + bb33: { StorageDead(_11); StorageDead(_12); return; } - bb36 (cleanup): { + bb34 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir index 623dd51c35849..9ebfff18f4830 100644 --- a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _4 = discriminant(_2); - switchInt(move _4) -> [0: bb6, 1: bb3, otherwise: bb2]; + switchInt(move _4) -> [0: bb5, 1: bb2, otherwise: bb1]; } bb1: { @@ -37,43 +37,39 @@ fn full_tested_match() -> () { } bb2: { - goto -> bb1; + falseEdge -> [real: bb7, imaginary: bb3]; } bb3: { - falseEdge -> [real: bb8, imaginary: bb4]; + falseEdge -> [real: bb12, imaginary: bb5]; } bb4: { - falseEdge -> [real: bb13, imaginary: bb6]; + goto -> bb1; } bb5: { - goto -> bb2; + _1 = (const 3_i32, const 3_i32); + goto -> bb13; } bb6: { - _1 = (const 3_i32, const 3_i32); - goto -> bb14; + goto -> bb1; } bb7: { - goto -> bb2; - } - - bb8: { StorageLive(_6); _6 = &((_2 as Some).0: i32); _3 = &fake shallow _2; StorageLive(_7); - _7 = guard() -> [return: bb9, unwind: bb17]; + _7 = guard() -> [return: bb8, unwind: bb15]; } - bb9: { - switchInt(move _7) -> [0: bb11, otherwise: bb10]; + bb8: { + switchInt(move _7) -> [0: bb10, otherwise: bb9]; } - bb10: { + bb9: { StorageDead(_7); FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _6); @@ -85,20 +81,20 @@ fn full_tested_match() -> () { StorageDead(_8); StorageDead(_5); StorageDead(_6); - goto -> bb14; + goto -> bb13; } - bb11: { - goto -> bb12; + bb10: { + goto -> bb11; } - bb12: { + bb11: { StorageDead(_7); StorageDead(_6); - goto -> bb4; + goto -> bb3; } - bb13: { + bb12: { StorageLive(_9); _9 = ((_2 as Some).0: i32); StorageLive(_10); @@ -106,10 +102,10 @@ fn full_tested_match() -> () { _1 = (const 2_i32, move _10); StorageDead(_10); StorageDead(_9); - goto -> bb14; + goto -> bb13; } - bb14: { + bb13: { PlaceMention(_1); StorageDead(_2); StorageDead(_1); @@ -117,16 +113,12 @@ fn full_tested_match() -> () { return; } - bb15: { + bb14: { FakeRead(ForMatchedPlace(None), _1); unreachable; } - bb16: { - goto -> bb15; - } - - bb17 (cleanup): { + bb15 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir index 3cb037bf95601..4d2989ea93ece 100644 --- a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match2() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _4 = discriminant(_2); - switchInt(move _4) -> [0: bb6, 1: bb3, otherwise: bb2]; + switchInt(move _4) -> [0: bb5, 1: bb2, otherwise: bb1]; } bb1: { @@ -37,14 +37,10 @@ fn full_tested_match2() -> () { } bb2: { - goto -> bb1; + falseEdge -> [real: bb7, imaginary: bb5]; } bb3: { - falseEdge -> [real: bb8, imaginary: bb6]; - } - - bb4: { StorageLive(_9); _9 = ((_2 as Some).0: i32); StorageLive(_10); @@ -52,34 +48,34 @@ fn full_tested_match2() -> () { _1 = (const 2_i32, move _10); StorageDead(_10); StorageDead(_9); - goto -> bb14; + goto -> bb13; + } + + bb4: { + goto -> bb1; } bb5: { - goto -> bb2; + falseEdge -> [real: bb12, imaginary: bb3]; } bb6: { - falseEdge -> [real: bb13, imaginary: bb4]; + goto -> bb1; } bb7: { - goto -> bb2; - } - - bb8: { StorageLive(_6); _6 = &((_2 as Some).0: i32); _3 = &fake shallow _2; StorageLive(_7); - _7 = guard() -> [return: bb9, unwind: bb17]; + _7 = guard() -> [return: bb8, unwind: bb15]; } - bb9: { - switchInt(move _7) -> [0: bb11, otherwise: bb10]; + bb8: { + switchInt(move _7) -> [0: bb10, otherwise: bb9]; } - bb10: { + bb9: { StorageDead(_7); FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _6); @@ -91,25 +87,25 @@ fn full_tested_match2() -> () { StorageDead(_8); StorageDead(_5); StorageDead(_6); - goto -> bb14; + goto -> bb13; } - bb11: { - goto -> bb12; + bb10: { + goto -> bb11; } - bb12: { + bb11: { StorageDead(_7); StorageDead(_6); - falseEdge -> [real: bb4, imaginary: bb6]; + falseEdge -> [real: bb3, imaginary: bb5]; } - bb13: { + bb12: { _1 = (const 3_i32, const 3_i32); - goto -> bb14; + goto -> bb13; } - bb14: { + bb13: { PlaceMention(_1); StorageDead(_2); StorageDead(_1); @@ -117,16 +113,12 @@ fn full_tested_match2() -> () { return; } - bb15: { + bb14: { FakeRead(ForMatchedPlace(None), _1); unreachable; } - bb16: { - goto -> bb15; - } - - bb17 (cleanup): { + bb15 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir index 134517ad2aec2..4ed9361070662 100644 --- a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir +++ b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir @@ -39,64 +39,60 @@ fn main() -> () { _2 = Option::::Some(const 1_i32); PlaceMention(_2); _4 = discriminant(_2); - switchInt(move _4) -> [1: bb3, otherwise: bb2]; + switchInt(move _4) -> [1: bb2, otherwise: bb1]; } bb1: { - FakeRead(ForMatchedPlace(None), _2); - unreachable; + falseEdge -> [real: bb14, imaginary: bb4]; } bb2: { - falseEdge -> [real: bb15, imaginary: bb5]; + falseEdge -> [real: bb9, imaginary: bb1]; } bb3: { - falseEdge -> [real: bb10, imaginary: bb2]; + goto -> bb1; } bb4: { - goto -> bb2; - } - - bb5: { _5 = discriminant(_2); - switchInt(move _5) -> [1: bb7, otherwise: bb6]; + switchInt(move _5) -> [1: bb6, otherwise: bb5]; } - bb6: { + bb5: { StorageLive(_14); _14 = _2; _1 = const 4_i32; StorageDead(_14); - goto -> bb21; + goto -> bb20; + } + + bb6: { + falseEdge -> [real: bb15, imaginary: bb5]; } bb7: { - falseEdge -> [real: bb16, imaginary: bb6]; + goto -> bb5; } bb8: { - goto -> bb6; + FakeRead(ForMatchedPlace(None), _2); + unreachable; } bb9: { - goto -> bb1; - } - - bb10: { StorageLive(_7); _7 = &((_2 as Some).0: i32); _3 = &fake shallow _2; StorageLive(_8); - _8 = guard() -> [return: bb11, unwind: bb24]; + _8 = guard() -> [return: bb10, unwind: bb22]; } - bb11: { - switchInt(move _8) -> [0: bb13, otherwise: bb12]; + bb10: { + switchInt(move _8) -> [0: bb12, otherwise: bb11]; } - bb12: { + bb11: { StorageDead(_8); FakeRead(ForMatchGuard, _3); FakeRead(ForGuardBinding, _7); @@ -105,42 +101,42 @@ fn main() -> () { _1 = const 1_i32; StorageDead(_6); StorageDead(_7); - goto -> bb21; + goto -> bb20; } - bb13: { - goto -> bb14; + bb12: { + goto -> bb13; } - bb14: { + bb13: { StorageDead(_8); StorageDead(_7); - falseEdge -> [real: bb4, imaginary: bb2]; + falseEdge -> [real: bb3, imaginary: bb1]; } - bb15: { + bb14: { StorageLive(_9); _9 = _2; _1 = const 2_i32; StorageDead(_9); - goto -> bb21; + goto -> bb20; } - bb16: { + bb15: { StorageLive(_11); _11 = &((_2 as Some).0: i32); _3 = &fake shallow _2; StorageLive(_12); StorageLive(_13); _13 = (*_11); - _12 = guard2(move _13) -> [return: bb17, unwind: bb24]; + _12 = guard2(move _13) -> [return: bb16, unwind: bb22]; } - bb17: { - switchInt(move _12) -> [0: bb19, otherwise: bb18]; + bb16: { + switchInt(move _12) -> [0: bb18, otherwise: bb17]; } - bb18: { + bb17: { StorageDead(_13); StorageDead(_12); FakeRead(ForMatchGuard, _3); @@ -150,21 +146,21 @@ fn main() -> () { _1 = const 3_i32; StorageDead(_10); StorageDead(_11); - goto -> bb21; + goto -> bb20; } - bb19: { - goto -> bb20; + bb18: { + goto -> bb19; } - bb20: { + bb19: { StorageDead(_13); StorageDead(_12); StorageDead(_11); - falseEdge -> [real: bb8, imaginary: bb6]; + falseEdge -> [real: bb7, imaginary: bb5]; } - bb21: { + bb20: { PlaceMention(_1); StorageDead(_2); StorageDead(_1); @@ -172,16 +168,12 @@ fn main() -> () { return; } - bb22: { + bb21: { FakeRead(ForMatchedPlace(None), _1); unreachable; } - bb23: { - goto -> bb22; - } - - bb24 (cleanup): { + bb22 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir b/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir index 81b5ce304d0e9..b0ebdc37b067d 100644 --- a/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir +++ b/tests/mir-opt/building/match/simple_match.match_bool.built.after.mir @@ -6,37 +6,33 @@ fn match_bool(_1: bool) -> usize { bb0: { PlaceMention(_1); - switchInt(_1) -> [0: bb2, otherwise: bb3]; + switchInt(_1) -> [0: bb1, otherwise: bb2]; } bb1: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; + _0 = const 20_usize; + goto -> bb6; } bb2: { - _0 = const 20_usize; - goto -> bb7; + falseEdge -> [real: bb5, imaginary: bb1]; } bb3: { - falseEdge -> [real: bb6, imaginary: bb2]; + goto -> bb1; } bb4: { - goto -> bb2; + FakeRead(ForMatchedPlace(None), _1); + unreachable; } bb5: { - goto -> bb1; - } - - bb6: { _0 = const 10_usize; - goto -> bb7; + goto -> bb6; } - bb7: { + bb6: { return; } } diff --git a/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir b/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir index c2ea5bd441c31..5e685f43cd612 100644 --- a/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir +++ b/tests/mir-opt/building/match/simple_match.match_enum.built.after.mir @@ -8,7 +8,7 @@ fn match_enum(_1: E1) -> bool { bb0: { PlaceMention(_1); _2 = discriminant(_1); - switchInt(move _2) -> [0: bb4, 1: bb6, 2: bb8, otherwise: bb3]; + switchInt(move _2) -> [0: bb2, 1: bb4, 2: bb6, otherwise: bb1]; } bb1: { @@ -17,48 +17,40 @@ fn match_enum(_1: E1) -> bool { } bb2: { - goto -> bb1; + goto -> bb8; } bb3: { - goto -> bb2; + goto -> bb1; } bb4: { - goto -> bb10; + goto -> bb8; } bb5: { - goto -> bb3; + goto -> bb1; } bb6: { + _0 = const false; goto -> bb10; } bb7: { - goto -> bb3; + goto -> bb1; } bb8: { - _0 = const false; - goto -> bb12; + falseEdge -> [real: bb9, imaginary: bb6]; } bb9: { - goto -> bb3; - } - - bb10: { - falseEdge -> [real: bb11, imaginary: bb8]; - } - - bb11: { _0 = const true; - goto -> bb12; + goto -> bb10; } - bb12: { + bb10: { return; } } diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir index db758368a1388..6d3b2cf291038 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir @@ -26,7 +26,7 @@ fn move_out_by_subslice() -> () { StorageLive(_2); _3 = SizeOf(i32); _4 = AlignOf(i32); - _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb14]; + _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb13]; } bb1: { @@ -34,7 +34,7 @@ fn move_out_by_subslice() -> () { _6 = ShallowInitBox(move _5, i32); (*_6) = const 1_i32; _2 = move _6; - drop(_6) -> [return: bb2, unwind: bb13]; + drop(_6) -> [return: bb2, unwind: bb12]; } bb2: { @@ -42,7 +42,7 @@ fn move_out_by_subslice() -> () { StorageLive(_7); _8 = SizeOf(i32); _9 = AlignOf(i32); - _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb13]; + _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb12]; } bb3: { @@ -50,18 +50,18 @@ fn move_out_by_subslice() -> () { _11 = ShallowInitBox(move _10, i32); (*_11) = const 2_i32; _7 = move _11; - drop(_11) -> [return: bb4, unwind: bb12]; + drop(_11) -> [return: bb4, unwind: bb11]; } bb4: { StorageDead(_11); _1 = [move _2, move _7]; - drop(_7) -> [return: bb5, unwind: bb13]; + drop(_7) -> [return: bb5, unwind: bb12]; } bb5: { StorageDead(_7); - drop(_2) -> [return: bb6, unwind: bb14]; + drop(_2) -> [return: bb6, unwind: bb13]; } bb6: { @@ -71,7 +71,7 @@ fn move_out_by_subslice() -> () { StorageLive(_12); _12 = move _1[0..2]; _0 = const (); - drop(_12) -> [return: bb9, unwind: bb11]; + drop(_12) -> [return: bb8, unwind: bb10]; } bb7: { @@ -80,32 +80,28 @@ fn move_out_by_subslice() -> () { } bb8: { - goto -> bb7; - } - - bb9: { StorageDead(_12); - drop(_1) -> [return: bb10, unwind: bb14]; + drop(_1) -> [return: bb9, unwind: bb13]; } - bb10: { + bb9: { StorageDead(_1); return; } + bb10 (cleanup): { + drop(_1) -> [return: bb13, unwind terminate(cleanup)]; + } + bb11 (cleanup): { - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; + drop(_7) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { - drop(_7) -> [return: bb13, unwind terminate(cleanup)]; + drop(_2) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { - drop(_2) -> [return: bb14, unwind terminate(cleanup)]; - } - - bb14 (cleanup): { resume; } } diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir index 84cd557715c2a..003b90a912d25 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir @@ -26,7 +26,7 @@ fn move_out_from_end() -> () { StorageLive(_2); _3 = SizeOf(i32); _4 = AlignOf(i32); - _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb14]; + _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb13]; } bb1: { @@ -34,7 +34,7 @@ fn move_out_from_end() -> () { _6 = ShallowInitBox(move _5, i32); (*_6) = const 1_i32; _2 = move _6; - drop(_6) -> [return: bb2, unwind: bb13]; + drop(_6) -> [return: bb2, unwind: bb12]; } bb2: { @@ -42,7 +42,7 @@ fn move_out_from_end() -> () { StorageLive(_7); _8 = SizeOf(i32); _9 = AlignOf(i32); - _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb13]; + _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb12]; } bb3: { @@ -50,18 +50,18 @@ fn move_out_from_end() -> () { _11 = ShallowInitBox(move _10, i32); (*_11) = const 2_i32; _7 = move _11; - drop(_11) -> [return: bb4, unwind: bb12]; + drop(_11) -> [return: bb4, unwind: bb11]; } bb4: { StorageDead(_11); _1 = [move _2, move _7]; - drop(_7) -> [return: bb5, unwind: bb13]; + drop(_7) -> [return: bb5, unwind: bb12]; } bb5: { StorageDead(_7); - drop(_2) -> [return: bb6, unwind: bb14]; + drop(_2) -> [return: bb6, unwind: bb13]; } bb6: { @@ -71,7 +71,7 @@ fn move_out_from_end() -> () { StorageLive(_12); _12 = move _1[1 of 2]; _0 = const (); - drop(_12) -> [return: bb9, unwind: bb11]; + drop(_12) -> [return: bb8, unwind: bb10]; } bb7: { @@ -80,32 +80,28 @@ fn move_out_from_end() -> () { } bb8: { - goto -> bb7; - } - - bb9: { StorageDead(_12); - drop(_1) -> [return: bb10, unwind: bb14]; + drop(_1) -> [return: bb9, unwind: bb13]; } - bb10: { + bb9: { StorageDead(_1); return; } + bb10 (cleanup): { + drop(_1) -> [return: bb13, unwind terminate(cleanup)]; + } + bb11 (cleanup): { - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; + drop(_7) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { - drop(_7) -> [return: bb13, unwind terminate(cleanup)]; + drop(_2) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { - drop(_2) -> [return: bb14, unwind terminate(cleanup)]; - } - - bb14 (cleanup): { resume; } } diff --git a/tests/mir-opt/issue_72181.bar.built.after.mir b/tests/mir-opt/issue_72181.bar.built.after.mir index 3ab9152f8bb6b..b6cc7d2219569 100644 --- a/tests/mir-opt/issue_72181.bar.built.after.mir +++ b/tests/mir-opt/issue_72181.bar.built.after.mir @@ -19,8 +19,4 @@ fn bar(_1: [(Never, u32); 1]) -> u32 { FakeRead(ForMatchedPlace(None), _1); unreachable; } - - bb2: { - goto -> bb1; - } } diff --git a/tests/mir-opt/issue_72181.main.built.after.mir b/tests/mir-opt/issue_72181.main.built.after.mir index fa101512d729f..89d351d5172ce 100644 --- a/tests/mir-opt/issue_72181.main.built.after.mir +++ b/tests/mir-opt/issue_72181.main.built.after.mir @@ -20,7 +20,7 @@ fn main() -> () { bb0: { StorageLive(_1); - _1 = std::mem::size_of::() -> [return: bb1, unwind: bb7]; + _1 = std::mem::size_of::() -> [return: bb1, unwind: bb5]; } bb1: { @@ -40,7 +40,7 @@ fn main() -> () { _6 = const 0_usize; _7 = Len(_2); _8 = Lt(_6, _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb4, unwind: bb7]; + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb5]; } bb2: { @@ -49,10 +49,6 @@ fn main() -> () { } bb3: { - goto -> bb2; - } - - bb4: { _5 = (_2[_6].0: u64); PlaceMention(_5); StorageDead(_6); @@ -62,16 +58,12 @@ fn main() -> () { return; } - bb5: { + bb4: { FakeRead(ForMatchedPlace(None), _5); unreachable; } - bb6: { - goto -> bb5; - } - - bb7 (cleanup): { + bb5 (cleanup): { resume; } } diff --git a/tests/mir-opt/issue_72181_1.f.built.after.mir b/tests/mir-opt/issue_72181_1.f.built.after.mir index 674a4013fe773..89da9a8011361 100644 --- a/tests/mir-opt/issue_72181_1.f.built.after.mir +++ b/tests/mir-opt/issue_72181_1.f.built.after.mir @@ -6,15 +6,11 @@ fn f(_1: Void) -> ! { bb0: { PlaceMention(_1); - goto -> bb1; - } - - bb1: { FakeRead(ForMatchedPlace(None), _1); unreachable; } - bb2: { + bb1: { return; } } diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir index 3dcdcab9dea3d..53829588a1b36 100644 --- a/tests/mir-opt/issue_91633.bar.built.after.mir +++ b/tests/mir-opt/issue_91633.bar.built.after.mir @@ -12,7 +12,7 @@ fn bar(_1: Box<[T]>) -> () { StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = <[T] as Index>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb5]; + _2 = <[T] as Index>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb4]; } bb1: { @@ -20,7 +20,7 @@ fn bar(_1: Box<[T]>) -> () { PlaceMention((*_2)); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb4, unwind: bb6]; + drop(_1) -> [return: bb3, unwind: bb5]; } bb2: { @@ -29,18 +29,14 @@ fn bar(_1: Box<[T]>) -> () { } bb3: { - goto -> bb2; - } - - bb4: { return; } - bb5 (cleanup): { - drop(_1) -> [return: bb6, unwind terminate(cleanup)]; + bb4 (cleanup): { + drop(_1) -> [return: bb5, unwind terminate(cleanup)]; } - bb6 (cleanup): { + bb5 (cleanup): { resume; } } diff --git a/tests/mir-opt/issue_91633.hey.built.after.mir b/tests/mir-opt/issue_91633.hey.built.after.mir index e782f4d1a23fa..a537e509996d7 100644 --- a/tests/mir-opt/issue_91633.hey.built.after.mir +++ b/tests/mir-opt/issue_91633.hey.built.after.mir @@ -14,7 +14,7 @@ fn hey(_1: &[T]) -> () { StorageLive(_3); StorageLive(_4); _4 = &(*_1); - _3 = <[T] as Index>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb4]; + _3 = <[T] as Index>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb3]; } bb1: { @@ -32,11 +32,7 @@ fn hey(_1: &[T]) -> () { unreachable; } - bb3: { - goto -> bb2; - } - - bb4 (cleanup): { + bb3 (cleanup): { resume; } } diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index b7a054b5d5409..72e7f4794f980 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -67,7 +67,7 @@ fn main() -> () { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb25]; + _4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb23]; } bb1: { @@ -91,7 +91,7 @@ fn main() -> () { _11 = &(*_8); StorageLive(_12); _12 = &(*_9); - _10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb4, unwind: bb25]; + _10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb3, unwind: bb23]; } bb2: { @@ -100,24 +100,20 @@ fn main() -> () { } bb3: { - goto -> bb2; + switchInt(move _10) -> [0: bb5, otherwise: bb4]; } bb4: { - switchInt(move _10) -> [0: bb6, otherwise: bb5]; - } - - bb5: { StorageDead(_12); StorageDead(_11); - goto -> bb10; + goto -> bb9; } - bb6: { - goto -> bb7; + bb5: { + goto -> bb6; } - bb7: { + bb6: { StorageDead(_12); StorageDead(_11); StorageLive(_14); @@ -136,10 +132,10 @@ fn main() -> () { _19 = &(*_20); StorageLive(_21); _21 = Option::>::None; - _15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb25; + _15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb23; } - bb8: { + bb7: { StorageDead(_21); StorageDead(_19); StorageDead(_17); @@ -151,23 +147,23 @@ fn main() -> () { unreachable; } - bb9: { - goto -> bb11; + bb8: { + goto -> bb10; } - bb10: { + bb9: { _1 = const (); - goto -> bb11; + goto -> bb10; } - bb11: { + bb10: { StorageDead(_10); StorageDead(_9); StorageDead(_8); - goto -> bb12; + goto -> bb11; } - bb12: { + bb11: { StorageDead(_7); StorageDead(_6); StorageDead(_4); @@ -177,10 +173,10 @@ fn main() -> () { StorageLive(_23); StorageLive(_24); StorageLive(_25); - _25 = function_with_bytes::<&*b"AAAA">() -> [return: bb13, unwind: bb25]; + _25 = function_with_bytes::<&*b"AAAA">() -> [return: bb12, unwind: bb23]; } - bb13: { + bb12: { _24 = &_25; StorageLive(_26); StorageLive(_27); @@ -199,33 +195,29 @@ fn main() -> () { _31 = &(*_28); StorageLive(_32); _32 = &(*_29); - _30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb16, unwind: bb25]; + _30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb14, unwind: bb23]; } - bb14: { + bb13: { FakeRead(ForMatchedPlace(None), _23); unreachable; } - bb15: { - goto -> bb14; - } - - bb16: { - switchInt(move _30) -> [0: bb18, otherwise: bb17]; + bb14: { + switchInt(move _30) -> [0: bb16, otherwise: bb15]; } - bb17: { + bb15: { StorageDead(_32); StorageDead(_31); - goto -> bb22; + goto -> bb20; } - bb18: { - goto -> bb19; + bb16: { + goto -> bb17; } - bb19: { + bb17: { StorageDead(_32); StorageDead(_31); StorageLive(_34); @@ -244,10 +236,10 @@ fn main() -> () { _39 = &(*_40); StorageLive(_41); _41 = Option::>::None; - _35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb25; + _35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb23; } - bb20: { + bb18: { StorageDead(_41); StorageDead(_39); StorageDead(_37); @@ -259,23 +251,23 @@ fn main() -> () { unreachable; } - bb21: { - goto -> bb23; + bb19: { + goto -> bb21; } - bb22: { + bb20: { _22 = const (); - goto -> bb23; + goto -> bb21; } - bb23: { + bb21: { StorageDead(_30); StorageDead(_29); StorageDead(_28); - goto -> bb24; + goto -> bb22; } - bb24: { + bb22: { StorageDead(_27); StorageDead(_25); StorageDead(_23); @@ -284,7 +276,7 @@ fn main() -> () { return; } - bb25 (cleanup): { + bb23 (cleanup): { resume; } } diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index b7a054b5d5409..72e7f4794f980 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -67,7 +67,7 @@ fn main() -> () { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb25]; + _4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb23]; } bb1: { @@ -91,7 +91,7 @@ fn main() -> () { _11 = &(*_8); StorageLive(_12); _12 = &(*_9); - _10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb4, unwind: bb25]; + _10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb3, unwind: bb23]; } bb2: { @@ -100,24 +100,20 @@ fn main() -> () { } bb3: { - goto -> bb2; + switchInt(move _10) -> [0: bb5, otherwise: bb4]; } bb4: { - switchInt(move _10) -> [0: bb6, otherwise: bb5]; - } - - bb5: { StorageDead(_12); StorageDead(_11); - goto -> bb10; + goto -> bb9; } - bb6: { - goto -> bb7; + bb5: { + goto -> bb6; } - bb7: { + bb6: { StorageDead(_12); StorageDead(_11); StorageLive(_14); @@ -136,10 +132,10 @@ fn main() -> () { _19 = &(*_20); StorageLive(_21); _21 = Option::>::None; - _15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb25; + _15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb23; } - bb8: { + bb7: { StorageDead(_21); StorageDead(_19); StorageDead(_17); @@ -151,23 +147,23 @@ fn main() -> () { unreachable; } - bb9: { - goto -> bb11; + bb8: { + goto -> bb10; } - bb10: { + bb9: { _1 = const (); - goto -> bb11; + goto -> bb10; } - bb11: { + bb10: { StorageDead(_10); StorageDead(_9); StorageDead(_8); - goto -> bb12; + goto -> bb11; } - bb12: { + bb11: { StorageDead(_7); StorageDead(_6); StorageDead(_4); @@ -177,10 +173,10 @@ fn main() -> () { StorageLive(_23); StorageLive(_24); StorageLive(_25); - _25 = function_with_bytes::<&*b"AAAA">() -> [return: bb13, unwind: bb25]; + _25 = function_with_bytes::<&*b"AAAA">() -> [return: bb12, unwind: bb23]; } - bb13: { + bb12: { _24 = &_25; StorageLive(_26); StorageLive(_27); @@ -199,33 +195,29 @@ fn main() -> () { _31 = &(*_28); StorageLive(_32); _32 = &(*_29); - _30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb16, unwind: bb25]; + _30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb14, unwind: bb23]; } - bb14: { + bb13: { FakeRead(ForMatchedPlace(None), _23); unreachable; } - bb15: { - goto -> bb14; - } - - bb16: { - switchInt(move _30) -> [0: bb18, otherwise: bb17]; + bb14: { + switchInt(move _30) -> [0: bb16, otherwise: bb15]; } - bb17: { + bb15: { StorageDead(_32); StorageDead(_31); - goto -> bb22; + goto -> bb20; } - bb18: { - goto -> bb19; + bb16: { + goto -> bb17; } - bb19: { + bb17: { StorageDead(_32); StorageDead(_31); StorageLive(_34); @@ -244,10 +236,10 @@ fn main() -> () { _39 = &(*_40); StorageLive(_41); _41 = Option::>::None; - _35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb25; + _35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb23; } - bb20: { + bb18: { StorageDead(_41); StorageDead(_39); StorageDead(_37); @@ -259,23 +251,23 @@ fn main() -> () { unreachable; } - bb21: { - goto -> bb23; + bb19: { + goto -> bb21; } - bb22: { + bb20: { _22 = const (); - goto -> bb23; + goto -> bb21; } - bb23: { + bb21: { StorageDead(_30); StorageDead(_29); StorageDead(_28); - goto -> bb24; + goto -> bb22; } - bb24: { + bb22: { StorageDead(_27); StorageDead(_25); StorageDead(_23); @@ -284,7 +276,7 @@ fn main() -> () { return; } - bb25 (cleanup): { + bb23 (cleanup): { resume; } } diff --git a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir index 775bc8afd7bdb..e357e785e33ee 100644 --- a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir @@ -18,24 +18,24 @@ fn shortcut_second_or() -> () { _1 = (move _2, const 0_i32); StorageDead(_2); PlaceMention(_1); - switchInt(((_1.0: (i32, i32)).0: i32)) -> [0: bb3, otherwise: bb2]; + switchInt(((_1.0: (i32, i32)).0: i32)) -> [0: bb2, otherwise: bb1]; } bb1: { - _0 = const (); - goto -> bb14; + switchInt(((_1.0: (i32, i32)).1: i32)) -> [1: bb4, otherwise: bb3]; } bb2: { - switchInt(((_1.0: (i32, i32)).1: i32)) -> [1: bb4, otherwise: bb1]; + switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb3]; } bb3: { - switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb1]; + _0 = const (); + goto -> bb14; } bb4: { - switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb1]; + switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb3]; } bb5: { @@ -43,7 +43,7 @@ fn shortcut_second_or() -> () { } bb6: { - falseEdge -> [real: bb11, imaginary: bb2]; + falseEdge -> [real: bb11, imaginary: bb1]; } bb7: { @@ -51,7 +51,7 @@ fn shortcut_second_or() -> () { } bb8: { - falseEdge -> [real: bb13, imaginary: bb1]; + falseEdge -> [real: bb13, imaginary: bb3]; } bb9: { From 42772e98e0d1d3ca0f6660c697e881f5de4b392e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 5 Jul 2024 22:23:14 +0200 Subject: [PATCH 08/14] Address review comments --- compiler/rustc_mir_build/src/build/matches/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 2fc510a222b60..841ef2719c99d 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1437,17 +1437,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidates: &mut [&mut Candidate<'_, 'tcx>], ) -> BasicBlock { ensure_sufficient_stack(|| { - self.match_candidates_with_enough_stack(span, scrutinee_span, start_block, candidates) + self.match_candidates_inner(span, scrutinee_span, start_block, candidates) }) } /// Construct the decision tree for `candidates`. Don't call this, call `match_candidates` /// instead to reserve sufficient stack space. - fn match_candidates_with_enough_stack( + fn match_candidates_inner( &mut self, span: Span, scrutinee_span: Span, - start_block: BasicBlock, + mut start_block: BasicBlock, candidates: &mut [&mut Candidate<'_, 'tcx>], ) -> BasicBlock { if let [first, ..] = candidates { @@ -1480,7 +1480,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; // Process any candidates that remain. - let BlockAnd(start_block, remaining_candidates) = rest; + let remaining_candidates = unpack!(start_block = rest); self.match_candidates(span, scrutinee_span, start_block, remaining_candidates) } From 08a2992d6bed7be4e673989965949b610c46e7e8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 11 Jul 2024 21:17:09 +1000 Subject: [PATCH 09/14] compiletest: Better error message for bad `normalize-*` headers --- src/tools/compiletest/src/header.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 7479be90797ee..7f5d4f4b41690 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -991,13 +991,19 @@ impl Config { } fn parse_custom_normalization(&self, line: &str, prefix: &str) -> Option<(String, String)> { - if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match { - let (regex, replacement) = parse_normalize_rule(line) - .unwrap_or_else(|| panic!("couldn't parse custom normalization rule: `{line}`")); - Some((regex, replacement)) - } else { - None + let parsed = parse_cfg_name_directive(self, line, prefix); + if parsed.outcome != MatchOutcome::Match { + return None; } + let name = parsed.name.expect("successful match always has a name"); + + let Some((regex, replacement)) = parse_normalize_rule(line) else { + panic!( + "couldn't parse custom normalization rule: `{line}`\n\ + help: expected syntax is: `{prefix}-{name}: \"REGEX\" -> \"REPLACEMENT\"`" + ); + }; + Some((regex, replacement)) } fn parse_name_directive(&self, line: &str, directive: &str) -> bool { From b77d3ef7c470f1d37a54665a0f21b5df22f4f86a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Jul 2024 15:31:34 -0400 Subject: [PATCH 10/14] Mark builtin syntax as internal --- compiler/rustc_feature/src/unstable.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c05cac155b74b..27a0a71a4d2c0 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -248,6 +248,8 @@ declare_features! ( (unstable, auto_traits, "1.50.0", Some(13231)), /// Allows using `box` in patterns (RFC 469). (unstable, box_patterns, "1.0.0", Some(29641)), + /// Allows builtin # foo() syntax + (internal, builtin_syntax, "1.71.0", Some(110680)), /// Allows `#[doc(notable_trait)]`. /// Renamed from `doc_spotlight`. (unstable, doc_notable_trait, "1.52.0", Some(45040)), @@ -361,8 +363,6 @@ declare_features! ( (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. (unstable, async_for_loop, "1.77.0", Some(118898)), - /// Allows builtin # foo() syntax - (unstable, builtin_syntax, "1.71.0", Some(110680)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. From d9021791eb097ae80bb1f1dd691e7e47c8e16f59 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Thu, 11 Jul 2024 22:38:34 +0200 Subject: [PATCH 11/14] Revert accidental comment deletion --- compiler/rustc_borrowck/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index d258c68b9598b..9ad941dabbe65 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -821,6 +821,8 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> | TerminatorKind::Return | TerminatorKind::TailCall { .. } | TerminatorKind::CoroutineDrop => { + // Returning from the function implicitly kills storage for all locals and statics. + // Often, the storage will already have been killed by an explicit // StorageDead, but we don't always emit those (notably on unwind paths), // so this "extra check" serves as a kind of backup. let borrow_set = self.borrow_set.clone(); From d9170dc6666211902c7fbfa4f229c43cc286890c Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 11 Jul 2024 22:20:53 +0000 Subject: [PATCH 12/14] Add regression test for issue 127545 --- .../transforming-option-ref-issue-127545.rs | 6 ++++++ .../transforming-option-ref-issue-127545.stderr | 14 ++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs create mode 100644 tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr diff --git a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs new file mode 100644 index 0000000000000..5ba58e7427581 --- /dev/null +++ b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs @@ -0,0 +1,6 @@ +// Regression test for . +#![crate_type = "lib"] + +pub fn foo(arg: Option<&Vec>) -> Option<&[i32]> { + arg //~ ERROR 5:5: 5:8: mismatched types [E0308] +} diff --git a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr new file mode 100644 index 0000000000000..798a4da23b0d7 --- /dev/null +++ b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/transforming-option-ref-issue-127545.rs:5:5 + | +LL | pub fn foo(arg: Option<&Vec>) -> Option<&[i32]> { + | -------------- expected `Option<&[i32]>` because of return type +LL | arg + | ^^^ expected `Option<&[i32]>`, found `Option<&Vec>` + | + = note: expected enum `Option<&[i32]>` + found enum `Option<&Vec>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 872d7b82e181235bdf8842847c76592f70419b09 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 11 Jul 2024 22:15:48 +0000 Subject: [PATCH 13/14] Add suggestion for `Option<&Vec> -> Option<&[T]` --- .../src/fn_ctxt/suggestions.rs | 49 +++++++++++++------ ...ransforming-option-ref-issue-127545.stderr | 4 ++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 8d380caf91628..50c4e9d5d6076 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -466,21 +466,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { borrow_removal_span, }); return true; - } else if let Some((deref_ty, _)) = - self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1) - && self.can_eq(self.param_env, deref_ty, peeled) - && error_tys_equate_as_ref - { - let sugg = prefix_wrap(".as_deref()"); - err.subdiagnostic(errors::SuggestConvertViaMethod { - span: expr.span.shrink_to_hi(), - sugg, - expected, - found, - borrow_removal_span, - }); - return true; - } else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind() + } else if let ty::Ref(_, peeled_found_ty, _) = found_ty_inner.kind() + && let ty::Adt(adt, _) = peeled_found_ty.peel_refs().kind() && self.tcx.is_lang_item(adt.did(), LangItem::String) && peeled.is_str() // `Result::map`, conversely, does not take ref of the error type. @@ -496,6 +483,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); return true; + } else { + if !error_tys_equate_as_ref { + return false; + } + let mut steps = self.autoderef(expr.span, found_ty_inner).silence_errors(); + if let Some((deref_ty, _)) = steps.nth(1) + && self.can_eq(self.param_env, deref_ty, peeled) + { + let sugg = prefix_wrap(".as_deref()"); + err.subdiagnostic(errors::SuggestConvertViaMethod { + span: expr.span.shrink_to_hi(), + sugg, + expected, + found, + borrow_removal_span, + }); + return true; + } + for (deref_ty, n_step) in steps { + if self.can_eq(self.param_env, deref_ty, peeled) { + let explicit_deref = "*".repeat(n_step); + let sugg = prefix_wrap(&format!(".map(|v| &{explicit_deref}v)")); + err.subdiagnostic(errors::SuggestConvertViaMethod { + span: expr.span.shrink_to_hi(), + sugg, + expected, + found, + borrow_removal_span, + }); + return true; + } + } } } diff --git a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr index 798a4da23b0d7..b7c7202113a16 100644 --- a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr +++ b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr @@ -8,6 +8,10 @@ LL | arg | = note: expected enum `Option<&[i32]>` found enum `Option<&Vec>` +help: try using `.map(|v| &**v)` to convert `Option<&Vec>` to `Option<&[i32]>` + | +LL | arg.map(|v| &**v) + | ++++++++++++++ error: aborting due to 1 previous error From a776e5f922d3b39d74d4b4d3acb752ce3585a2fb Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 11 Jul 2024 05:10:20 +0000 Subject: [PATCH 14/14] Add doc for deconstruct_option_or_result --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 50c4e9d5d6076..0817ad3aed2c2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -521,6 +521,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + /// If `ty` is `Option`, returns `T, T, None`. + /// If `ty` is `Result`, returns `T, T, Some(E, E)`. + /// Otherwise, returns `None`. fn deconstruct_option_or_result( &self, found_ty: Ty<'tcx>,