about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-12 03:40:38 +0000
committerbors <bors@rust-lang.org>2024-07-12 03:40:38 +0000
commitb286722878e18db29a7fbe672be7c4d3b02e8e4d (patch)
treecebcce1687ff40e7478d1f013b0d1b70b94c2cda
parent4a31a6c32a9a0e726516b1086f33e3d4a37dc94c (diff)
parentc2b7842555b89d6c254abf51857f7364fa9cc0c4 (diff)
downloadrust-b286722878e18db29a7fbe672be7c4d3b02e8e4d.tar.gz
rust-b286722878e18db29a7fbe672be7c4d3b02e8e4d.zip
Auto merge of #127635 - matthiaskrgr:rollup-foopajr, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #127164 (match lowering: Clarify the main loop of the algorithm)
 - #127422 (as_simd: fix doc comment to be in line with align_to)
 - #127596 (More suggestion for converting `Option<&Vec<T>>` to `Option<&[T]>`)
 - #127607 (compiletest: Better error message for bad `normalize-*` headers)
 - #127622 (Mark `builtin_syntax` as internal)
 - #127625 (Revert accidental comment deletion)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs52
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs345
-rw-r--r--library/core/src/slice/mod.rs26
-rw-r--r--src/tools/compiletest/src/header.rs18
-rw-r--r--tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir8
-rw-r--r--tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir8
-rw-r--r--tests/mir-opt/building/match/match_false_edges.main.built.after.mir86
-rw-r--r--tests/mir-opt/building/match/simple_match.match_bool.built.after.mir20
-rw-r--r--tests/mir-opt/building/match/simple_match.match_enum.built.after.mir26
-rw-r--r--tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir28
-rw-r--r--tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir34
-rw-r--r--tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir34
-rw-r--r--tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff48
-rw-r--r--tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff48
-rw-r--r--tests/mir-opt/issue_72181.bar.built.after.mir4
-rw-r--r--tests/mir-opt/issue_72181.main.built.after.mir16
-rw-r--r--tests/mir-opt/issue_72181_1.f.built.after.mir6
-rw-r--r--tests/mir-opt/issue_91633.bar.built.after.mir14
-rw-r--r--tests/mir-opt/issue_91633.hey.built.after.mir8
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.32bit.mir82
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.64bit.mir82
-rw-r--r--tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff26
-rw-r--r--tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff26
-rw-r--r--tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir16
-rw-r--r--tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs6
-rw-r--r--tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr18
28 files changed, 506 insertions, 585 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index d258c68b959..9ad941dabbe 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();
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d7d994d95c5..948499fb38f 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.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 5f897c74482..5975c52ca46 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,12 +483,47 @@ 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;
+                    }
+                }
             }
         }
 
         false
     }
 
+    /// If `ty` is `Option<T>`, returns `T, T, None`.
+    /// If `ty` is `Result<T, E>`, returns `T, T, Some(E, E)`.
+    /// Otherwise, returns `None`.
     fn deconstruct_option_or_result(
         &self,
         found_ty: Ty<'tcx>,
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 5695c881ecc..841ef2719c9 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)) {
@@ -1308,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;
@@ -1363,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 {
@@ -1408,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
@@ -1425,161 +1427,61 @@ 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<'pat>(
+    fn match_candidates(
         &mut self,
         span: Span,
         scrutinee_span: Span,
         start_block: BasicBlock,
-        otherwise_block: BasicBlock,
-        candidates: &mut [&mut Candidate<'pat, '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!(
-                &*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);
-
+        candidates: &mut [&mut Candidate<'_, 'tcx>],
+    ) -> BasicBlock {
         ensure_sufficient_stack(|| {
-            if candidates_to_expand.is_empty() {
-                // No candidates start with an or-pattern, we can continue.
-                self.match_expanded_candidates(
-                    span,
-                    scrutinee_span,
-                    start_block,
-                    otherwise_block,
-                    remaining_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(
-                    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,
-                );
-            }
-        });
+            self.match_candidates_inner(span, scrutinee_span, start_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_inner(
         &mut self,
         span: Span,
         scrutinee_span: Span,
         mut 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);
             }
         }
 
-        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.
-                let source_info = self.source_info(span);
-                self.cfg.goto(start_block, source_info, otherwise_block);
+                // If there are no candidates that still need testing, we're done.
+                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
                 // with the remaining candidates.
-                start_block = self.select_matched_candidate(first, start_block);
-                self.match_expanded_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, 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 remaining_candidates = unpack!(start_block = rest);
+        self.match_candidates(span, scrutinee_span, start_block, remaining_candidates)
     }
 
     /// Link up matched candidates.
@@ -1624,6 +1526,102 @@ 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. 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,
+        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
+        // 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 && 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;
+            }
+        }
+        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 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);
+                // 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.match_candidates(
+            span,
+            scrutinee_span,
+            start_block,
+            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);
+            }
+        }
+
+        remainder_start.and(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.
+    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`.
     ///
@@ -1690,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
@@ -1703,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,
@@ -1713,36 +1715,11 @@ 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);
             });
         }
     }
 
-    /// 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`.
@@ -1992,14 +1969,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);
 
@@ -2010,33 +1988,18 @@ 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
             .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();
 
@@ -2050,6 +2013,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             &test,
             target_blocks,
         );
+
+        remainder_start.and(remaining_candidates)
     }
 }
 
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 521c3248204..68508e85f8e 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3959,17 +3959,8 @@ impl<T> [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> [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.
     ///
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 7479be90797..7f5d4f4b416 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 {
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 bade0fa4b45..9ebfff18f48 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
@@ -62,7 +62,7 @@ fn full_tested_match() -> () {
         _6 = &((_2 as Some).0: i32);
         _3 = &fake shallow _2;
         StorageLive(_7);
-        _7 = guard() -> [return: bb8, unwind: bb16];
+        _7 = guard() -> [return: bb8, unwind: bb15];
     }
 
     bb8: {
@@ -118,11 +118,7 @@ fn full_tested_match() -> () {
         unreachable;
     }
 
-    bb15: {
-        goto -> bb14;
-    }
-
-    bb16 (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 0d78bb8b235..4d2989ea93e 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
@@ -68,7 +68,7 @@ fn full_tested_match2() -> () {
         _6 = &((_2 as Some).0: i32);
         _3 = &fake shallow _2;
         StorageLive(_7);
-        _7 = guard() -> [return: bb8, unwind: bb16];
+        _7 = guard() -> [return: bb8, unwind: bb15];
     }
 
     bb8: {
@@ -118,11 +118,7 @@ fn full_tested_match2() -> () {
         unreachable;
     }
 
-    bb15: {
-        goto -> bb14;
-    }
-
-    bb16 (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 ebb75ae141a..4ed93610706 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,65 +38,61 @@ fn main() -> () {
         StorageLive(_2);
         _2 = Option::<i32>::Some(const 1_i32);
         PlaceMention(_2);
-        _5 = discriminant(_2);
-        switchInt(move _5) -> [1: bb8, otherwise: bb2];
+        _4 = discriminant(_2);
+        switchInt(move _4) -> [1: bb2, otherwise: bb1];
     }
 
     bb1: {
-        FakeRead(ForMatchedPlace(None), _2);
-        unreachable;
+        falseEdge -> [real: bb14, imaginary: bb4];
     }
 
     bb2: {
-        falseEdge -> [real: bb15, imaginary: bb3];
+        falseEdge -> [real: bb9, imaginary: bb1];
     }
 
     bb3: {
-        _4 = discriminant(_2);
-        switchInt(move _4) -> [1: bb6, otherwise: bb4];
+        goto -> bb1;
     }
 
     bb4: {
+        _5 = discriminant(_2);
+        switchInt(move _5) -> [1: bb6, otherwise: bb5];
+    }
+
+    bb5: {
         StorageLive(_14);
         _14 = _2;
         _1 = const 4_i32;
         StorageDead(_14);
-        goto -> bb21;
-    }
-
-    bb5: {
-        goto -> bb1;
+        goto -> bb20;
     }
 
     bb6: {
-        falseEdge -> [real: bb16, imaginary: bb4];
+        falseEdge -> [real: bb15, imaginary: bb5];
     }
 
     bb7: {
-        goto -> bb4;
+        goto -> bb5;
     }
 
     bb8: {
-        falseEdge -> [real: bb10, imaginary: bb2];
+        FakeRead(ForMatchedPlace(None), _2);
+        unreachable;
     }
 
     bb9: {
-        goto -> bb2;
-    }
-
-    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: bb9, 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: bb7, imaginary: bb4];
+        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 faa2456fd10..b0ebdc37b06 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,17 +6,16 @@ fn match_bool(_1: bool) -> usize {
 
     bb0: {
         PlaceMention(_1);
-        switchInt(_1) -> [0: bb2, otherwise: bb4];
+        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: {
@@ -24,19 +23,16 @@ fn match_bool(_1: bool) -> usize {
     }
 
     bb4: {
-        falseEdge -> [real: bb6, imaginary: bb2];
+        FakeRead(ForMatchedPlace(None), _1);
+        unreachable;
     }
 
     bb5: {
-        goto -> bb2;
-    }
-
-    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 905aa19da70..5e685f43cd6 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: bb2, 1: bb4, 2: bb6, otherwise: bb1];
     }
 
     bb1: {
@@ -17,44 +17,40 @@ fn match_enum(_1: E1) -> bool {
     }
 
     bb2: {
-        goto -> bb1;
+        goto -> bb8;
     }
 
     bb3: {
-        goto -> bb9;
+        goto -> bb1;
     }
 
     bb4: {
-        goto -> bb2;
+        goto -> bb8;
     }
 
     bb5: {
-        goto -> bb9;
+        goto -> bb1;
     }
 
     bb6: {
-        goto -> bb2;
+        _0 = const false;
+        goto -> bb10;
     }
 
     bb7: {
-        _0 = const false;
-        goto -> bb11;
+        goto -> bb1;
     }
 
     bb8: {
-        goto -> bb2;
+        falseEdge -> [real: bb9, imaginary: bb6];
     }
 
     bb9: {
-        falseEdge -> [real: bb10, imaginary: bb7];
-    }
-
-    bb10: {
         _0 = const true;
-        goto -> bb11;
+        goto -> bb10;
     }
 
-    bb11: {
+    bb10: {
         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 060cd6132e3..2b5dbacc2d9 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 = <str as PartialEq>::eq((_3.0: &str), const "a") -> [return: bb11, unwind: bb19];
+        _9 = <str as PartialEq>::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 = <str as PartialEq>::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 = <str as PartialEq>::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/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 db758368a13..6d3b2cf2910 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 84cd557715c..003b90a912d 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/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 938b9bb14ad..3a5762e4f3d 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 ce89694076b..21b197d2f27 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/issue_72181.bar.built.after.mir b/tests/mir-opt/issue_72181.bar.built.after.mir
index 3ab9152f8bb..b6cc7d22195 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 fa101512d72..89d351d5172 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::<Foo>() -> [return: bb1, unwind: bb7];
+        _1 = std::mem::size_of::<Foo>() -> [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 674a4013fe7..89da9a80113 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 3dcdcab9dea..53829588a1b 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<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb5];
+        _2 = <[T] as Index<usize>>::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 e782f4d1a23..a537e509996 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<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb4];
+        _3 = <[T] as Index<usize>>::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 b7a054b5d54..72e7f4794f9 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::<Arguments<'_>>::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::<Arguments<'_>>::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 b7a054b5d54..72e7f4794f9 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::<Arguments<'_>>::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::<Arguments<'_>>::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/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 209f0d09c29..4f29e5244d7 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 209f0d09c29..4f29e5244d7 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 56edd38a6da..e357e785e33 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: bb4, 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: bb3, otherwise: bb1];
+        switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb3];
     }
 
     bb3: {
-        switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb1];
+        _0 = const ();
+        goto -> bb14;
     }
 
     bb4: {
-        switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, 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: {
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 00000000000..5ba58e74275
--- /dev/null
+++ b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs
@@ -0,0 +1,6 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/127545>.
+#![crate_type = "lib"]
+
+pub fn foo(arg: Option<&Vec<i32>>) -> 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 00000000000..b7c7202113a
--- /dev/null
+++ b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/transforming-option-ref-issue-127545.rs:5:5
+   |
+LL | pub fn foo(arg: Option<&Vec<i32>>) -> Option<&[i32]> {
+   |                                       -------------- expected `Option<&[i32]>` because of return type
+LL |     arg
+   |     ^^^ expected `Option<&[i32]>`, found `Option<&Vec<i32>>`
+   |
+   = note: expected enum `Option<&[i32]>`
+              found enum `Option<&Vec<i32>>`
+help: try using `.map(|v| &**v)` to convert `Option<&Vec<i32>>` to `Option<&[i32]>`
+   |
+LL |     arg.map(|v| &**v)
+   |        ++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.