diff --git a/Cargo.lock b/Cargo.lock
index e0c72d6899e98..bb37fee98e4f8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -741,7 +741,7 @@ dependencies = [
  "tracing-subscriber",
  "unified-diff",
  "walkdir",
- "windows 0.46.0",
+ "windows",
 ]
 
 [[package]]
@@ -1647,7 +1647,7 @@ dependencies = [
  "iana-time-zone-haiku",
  "js-sys",
  "wasm-bindgen",
- "windows 0.48.0",
+ "windows",
 ]
 
 [[package]]
@@ -3259,7 +3259,7 @@ dependencies = [
  "tempfile",
  "thorin-dwp",
  "tracing",
- "windows 0.46.0",
+ "windows",
 ]
 
 [[package]]
@@ -3315,7 +3315,7 @@ dependencies = [
  "tempfile",
  "thin-vec",
  "tracing",
- "windows 0.46.0",
+ "windows",
 ]
 
 [[package]]
@@ -3376,7 +3376,7 @@ dependencies = [
  "rustc_ty_utils",
  "serde_json",
  "tracing",
- "windows 0.46.0",
+ "windows",
 ]
 
 [[package]]
@@ -3426,7 +3426,7 @@ dependencies = [
  "termize",
  "tracing",
  "unicode-width",
- "windows 0.46.0",
+ "windows",
 ]
 
 [[package]]
@@ -4096,7 +4096,7 @@ dependencies = [
  "smallvec",
  "termize",
  "tracing",
- "windows 0.46.0",
+ "windows",
 ]
 
 [[package]]
@@ -5498,15 +5498,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "windows"
-version = "0.46.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
-dependencies = [
- "windows-targets 0.42.2",
-]
-
 [[package]]
 name = "windows"
 version = "0.48.0"
diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs
index 8c737f043237e..ee56d45c9c826 100644
--- a/compiler/rustc_builtin_macros/src/concat_idents.rs
+++ b/compiler/rustc_builtin_macros/src/concat_idents.rs
@@ -19,7 +19,7 @@ pub fn expand_concat_idents<'cx>(
     }
 
     let mut res_str = String::new();
-    for (i, e) in tts.into_trees().enumerate() {
+    for (i, e) in tts.trees().enumerate() {
         if i & 1 == 1 {
             match e {
                 TokenTree::Token(Token { kind: token::Comma, .. }, _) => {}
diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs
index cc5ae6894e6fe..9c98723e1f43f 100644
--- a/compiler/rustc_builtin_macros/src/trace_macros.rs
+++ b/compiler/rustc_builtin_macros/src/trace_macros.rs
@@ -8,7 +8,7 @@ pub fn expand_trace_macros(
     sp: Span,
     tt: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let mut cursor = tt.into_trees();
+    let mut cursor = tt.trees();
     let mut err = false;
     let value = match &cursor.next() {
         Some(TokenTree::Token(token, _)) if token.is_keyword(kw::True) => true,
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 4f73b731f5a2a..02be88df103a5 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -51,5 +51,5 @@ default-features = false
 features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.46.0"
+version = "0.48.0"
 features = ["Win32_Globalization"]
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 5e05fe463ed2b..c815bb2d19749 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -37,7 +37,7 @@ itertools = "0.10.1"
 version = "0.11"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.46.0"
+version = "0.48.0"
 features = [
     "Win32_Foundation",
     "Win32_Storage_FileSystem",
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 5e13e7c8aafc8..3c76c2b79911a 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -865,14 +865,16 @@ cfg_if! {
             use std::mem;
 
             use windows::{
-                Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
+                // FIXME: change back to K32GetProcessMemoryInfo when windows crate
+                // updated to 0.49.0+ to drop dependency on psapi.dll
+                Win32::System::ProcessStatus::{GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
                 Win32::System::Threading::GetCurrentProcess,
             };
 
             let mut pmc = PROCESS_MEMORY_COUNTERS::default();
             let pmc_size = mem::size_of_val(&pmc);
             unsafe {
-                K32GetProcessMemoryInfo(
+                GetProcessMemoryInfo(
                     GetCurrentProcess(),
                     &mut pmc,
                     pmc_size as u32,
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index d7d97fcc3e7b7..67352c55c9019 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -57,7 +57,7 @@ rustc_mir_transform = { path = "../rustc_mir_transform" }
 libc = "0.2"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.46.0"
+version = "0.48.0"
 features = [
     "Win32_System_Diagnostics_Debug",
 ]
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 46ace8eb2dd8d..bd3033fcb3e86 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -27,12 +27,11 @@ serde = { version = "1.0.125", features = [ "derive" ] }
 serde_json = "1.0.59"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.46.0"
+version = "0.48.0"
 features = [
     "Win32_Foundation",
     "Win32_Security",
     "Win32_System_Threading",
-    "Win32_System_WindowsProgramming",
 ]
 
 [features]
diff --git a/compiler/rustc_errors/src/lock.rs b/compiler/rustc_errors/src/lock.rs
index 7db262abfde26..bd5cf49b56bd7 100644
--- a/compiler/rustc_errors/src/lock.rs
+++ b/compiler/rustc_errors/src/lock.rs
@@ -19,8 +19,7 @@ pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
     use windows::{
         core::PCSTR,
         Win32::Foundation::{CloseHandle, HANDLE, WAIT_ABANDONED, WAIT_OBJECT_0},
-        Win32::System::Threading::{CreateMutexA, ReleaseMutex, WaitForSingleObject},
-        Win32::System::WindowsProgramming::INFINITE,
+        Win32::System::Threading::{CreateMutexA, ReleaseMutex, WaitForSingleObject, INFINITE},
     };
 
     struct Handle(HANDLE);
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 3025cce7ba7e5..b1c45eaf601e5 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1882,8 +1882,8 @@ declare_lint_pass!(
 struct UnderMacro(bool);
 
 impl KeywordIdents {
-    fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: TokenStream) {
-        for tt in tokens.into_trees() {
+    fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) {
+        for tt in tokens.trees() {
             match tt {
                 // Only report non-raw idents.
                 TokenTree::Token(token, _) => {
@@ -1944,10 +1944,10 @@ impl KeywordIdents {
 
 impl EarlyLintPass for KeywordIdents {
     fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef) {
-        self.check_tokens(cx, mac_def.body.tokens.clone());
+        self.check_tokens(cx, &mac_def.body.tokens);
     }
     fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
-        self.check_tokens(cx, mac.args.tokens.clone());
+        self.check_tokens(cx, &mac.args.tokens);
     }
     fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
         self.check_ident_token(cx, UnderMacro(false), ident);
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 8d0737e1eeeeb..488d83b5f671b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2366,13 +2366,11 @@ impl<'tcx> Ty<'tcx> {
 
             ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
 
-            ty::Alias(..) | ty::Param(_) => false,
+            ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
 
             ty::Infer(ty::TyVar(_)) => false,
 
-            ty::Bound(..)
-            | ty::Placeholder(..)
-            | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+            ty::Bound(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("`is_trivially_sized` applied to unexpected type: {:?}", self)
             }
         }
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index dafd2ae23a635..d1bc9ee91538e 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -85,7 +85,9 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let ssa = SsaLocals::new(body);
 
     let mut replacer = compute_replacement(tcx, body, &ssa);
-    debug!(?replacer.targets, ?replacer.allowed_replacements, ?replacer.storage_to_remove);
+    debug!(?replacer.targets);
+    debug!(?replacer.allowed_replacements);
+    debug!(?replacer.storage_to_remove);
 
     replacer.visit_body_preserves_cfg(body);
 
@@ -190,8 +192,11 @@ fn compute_replacement<'tcx>(
             continue;
         }
 
+        // Whether the current local is subject to the uniqueness rule.
+        let needs_unique = ty.is_mutable_ptr();
+
         // If this a mutable reference that we cannot fully replace, mark it as unknown.
-        if ty.is_mutable_ptr() && !fully_replacable_locals.contains(local) {
+        if needs_unique && !fully_replacable_locals.contains(local) {
             debug!("not fully replaceable");
             continue;
         }
@@ -203,13 +208,14 @@ fn compute_replacement<'tcx>(
             // have been visited before.
             Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
             | Rvalue::CopyForDeref(place) => {
-                if let Some(rhs) = place.as_local() {
+                if let Some(rhs) = place.as_local() && ssa.is_ssa(rhs) {
                     let target = targets[rhs];
-                    if matches!(target, Value::Pointer(..)) {
+                    // Only see through immutable reference and pointers, as we do not know yet if
+                    // mutable references are fully replaced.
+                    if !needs_unique && matches!(target, Value::Pointer(..)) {
                         targets[local] = target;
-                    } else if ssa.is_ssa(rhs) {
-                        let refmut = body.local_decls[rhs].ty.is_mutable_ptr();
-                        targets[local] = Value::Pointer(tcx.mk_place_deref(rhs.into()), refmut);
+                    } else {
+                        targets[local] = Value::Pointer(tcx.mk_place_deref(rhs.into()), needs_unique);
                     }
                 }
             }
@@ -217,10 +223,10 @@ fn compute_replacement<'tcx>(
                 let mut place = *place;
                 // Try to see through `place` in order to collapse reborrow chains.
                 if place.projection.first() == Some(&PlaceElem::Deref)
-                    && let Value::Pointer(target, refmut) = targets[place.local]
+                    && let Value::Pointer(target, inner_needs_unique) = targets[place.local]
                     // Only see through immutable reference and pointers, as we do not know yet if
                     // mutable references are fully replaced.
-                    && !refmut
+                    && !inner_needs_unique
                     // Only collapse chain if the pointee is definitely live.
                     && can_perform_opt(target, location)
                 {
@@ -228,7 +234,7 @@ fn compute_replacement<'tcx>(
                 }
                 assert_ne!(place.local, local);
                 if is_constant_place(place) {
-                    targets[local] = Value::Pointer(place, ty.is_mutable_ptr());
+                    targets[local] = Value::Pointer(place, needs_unique);
                 }
             }
             // We do not know what to do, so keep as not-a-pointer.
@@ -276,16 +282,35 @@ fn compute_replacement<'tcx>(
                 return;
             }
 
-            if let Value::Pointer(target, refmut) = self.targets[place.local]
-                && place.projection.first() == Some(&PlaceElem::Deref)
-            {
-                let perform_opt = (self.can_perform_opt)(target, loc);
-                if perform_opt {
-                    self.allowed_replacements.insert((target.local, loc));
-                } else if refmut {
-                    // This mutable reference is not fully replacable, so drop it.
-                    self.targets[place.local] = Value::Unknown;
+            if place.projection.first() != Some(&PlaceElem::Deref) {
+                // This is not a dereference, nothing to do.
+                return;
+            }
+
+            let mut place = place.as_ref();
+            loop {
+                if let Value::Pointer(target, needs_unique) = self.targets[place.local] {
+                    let perform_opt = (self.can_perform_opt)(target, loc);
+                    debug!(?place, ?target, ?needs_unique, ?perform_opt);
+
+                    // This a reborrow chain, recursively allow the replacement.
+                    //
+                    // This also allows to detect cases where `target.local` is not replacable,
+                    // and mark it as such.
+                    if let &[PlaceElem::Deref] = &target.projection[..] {
+                        assert!(perform_opt);
+                        self.allowed_replacements.insert((target.local, loc));
+                        place.local = target.local;
+                        continue;
+                    } else if perform_opt {
+                        self.allowed_replacements.insert((target.local, loc));
+                    } else if needs_unique {
+                        // This mutable reference is not fully replacable, so drop it.
+                        self.targets[place.local] = Value::Unknown;
+                    }
                 }
+
+                break;
             }
         }
     }
@@ -326,18 +351,23 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
-        if let Value::Pointer(target, _) = self.targets[place.local]
-            && place.projection.first() == Some(&PlaceElem::Deref)
-        {
-            let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
-                || self.allowed_replacements.contains(&(target.local, loc));
-
-            if perform_opt {
-                *place = target.project_deeper(&place.projection[1..], self.tcx);
-                self.any_replacement = true;
+        if place.projection.first() != Some(&PlaceElem::Deref) {
+            return;
+        }
+
+        loop {
+            if let Value::Pointer(target, _) = self.targets[place.local] {
+                let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
+                    || self.allowed_replacements.contains(&(target.local, loc));
+
+                if perform_opt {
+                    *place = target.project_deeper(&place.projection[1..], self.tcx);
+                    self.any_replacement = true;
+                    continue;
+                }
             }
-        } else {
-            self.super_place(place, ctxt, loc);
+
+            break;
         }
     }
 
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 3477b97438c37..3af83aaaaa8a2 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -25,7 +25,7 @@ termize = "0.1.1"
 libc = "0.2"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.46.0"
+version = "0.48.0"
 features = [
     "Win32_Foundation",
     "Win32_System_LibraryLoader",
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 7fdbd48d56334..3988416d0c795 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -135,13 +135,13 @@ fn current_dll_path() -> Result<PathBuf, String> {
 
     use windows::{
         core::PCWSTR,
-        Win32::Foundation::HINSTANCE,
+        Win32::Foundation::HMODULE,
         Win32::System::LibraryLoader::{
             GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
         },
     };
 
-    let mut module = HINSTANCE::default();
+    let mut module = HMODULE::default();
     unsafe {
         GetModuleHandleExW(
             GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
diff --git a/src/tools/cargo b/src/tools/cargo
index 26b73d15a68fb..13413c64ff88d 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 26b73d15a68fb94579f6d3590585ec0e9d81d3d5
+Subproject commit 13413c64ff88dd6c2824e9eb9374fc5f10895d28
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 85fd6523c82b1..0d42504c7f4ca 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -28,7 +28,7 @@ libc = "0.2"
 miow = "0.5"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.46.0"
+version = "0.48.0"
 features = [
     "Win32_Foundation",
     "Win32_System_Diagnostics_Debug",
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index baef4bb0140fb..afa6bce943f34 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -6,47 +6,53 @@ use std::path::Path;
 
 /// These are licenses that are allowed for all crates, including the runtime,
 /// rustc, tools, etc.
+#[rustfmt::skip]
 const LICENSES: &[&str] = &[
-    "MIT/Apache-2.0",
-    "MIT / Apache-2.0",
-    "Apache-2.0/MIT",
+    // tidy-alphabetical-start
+    "(MIT OR Apache-2.0) AND Unicode-DFS-2016",            // unicode_ident
+    "0BSD OR MIT OR Apache-2.0",                           // adler license
+    "0BSD",
     "Apache-2.0 / MIT",
-    "MIT OR Apache-2.0",
     "Apache-2.0 OR MIT",
     "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license
-    "MIT",
+    "Apache-2.0/MIT",
     "ISC",
-    "Unlicense/MIT",
+    "MIT / Apache-2.0",
+    "MIT OR Apache-2.0 OR Zlib",                           // tinyvec_macros
+    "MIT OR Apache-2.0",
+    "MIT OR Zlib OR Apache-2.0",                           // miniz_oxide
+    "MIT",
+    "MIT/Apache-2.0",
+    "Unicode-DFS-2016",                                    // tinystr and icu4x
     "Unlicense OR MIT",
-    "0BSD",
-    "0BSD OR MIT OR Apache-2.0",                // adler license
-    "Zlib OR Apache-2.0 OR MIT",                // tinyvec
-    "MIT OR Apache-2.0 OR Zlib",                // tinyvec_macros
-    "MIT OR Zlib OR Apache-2.0",                // miniz_oxide
-    "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident
-    "Unicode-DFS-2016",                         // tinystr and icu4x
+    "Unlicense/MIT",
+    "Zlib OR Apache-2.0 OR MIT",                           // tinyvec
+    // tidy-alphabetical-end
 ];
 
 /// These are exceptions to Rust's permissive licensing policy, and
 /// should be considered bugs. Exceptions are only allowed in Rust
 /// tooling. It is _crucial_ that no exception crates be dependencies
 /// of the Rust runtime (std/test).
+#[rustfmt::skip]
 const EXCEPTIONS: &[(&str, &str)] = &[
+    // tidy-alphabetical-start
     ("ar_archive_writer", "Apache-2.0 WITH LLVM-exception"), // rustc
-    ("mdbook", "MPL-2.0"),                                   // mdbook
+    ("codespan-reporting", "Apache-2.0"),                    // cxx via iana-time-zone-haiku via time, only on haiku
     ("colored", "MPL-2.0"),                                  // rustfmt
+    ("dissimilar", "Apache-2.0"),                            // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
+    ("fluent-langneg", "Apache-2.0"),                        // rustc (fluent translations)
+    ("fortanix-sgx-abi", "MPL-2.0"),                         // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above.
+    ("instant", "BSD-3-Clause"),                             // rustc_driver/tracing-subscriber/parking_lot
+    ("mdbook", "MPL-2.0"),                                   // mdbook
     ("ryu", "Apache-2.0 OR BSL-1.0"),                        // cargo/... (because of serde)
-    ("codespan-reporting", "Apache-2.0"), // cxx via iana-time-zone-haiku via time, only on haiku
-    ("instant", "BSD-3-Clause"),          // rustc_driver/tracing-subscriber/parking_lot
-    ("snap", "BSD-3-Clause"),             // rustc
-    ("fluent-langneg", "Apache-2.0"),     // rustc (fluent translations)
-    ("self_cell", "Apache-2.0"),          // rustc (fluent translations)
-    // FIXME: this dependency violates the documentation comment above:
-    ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
-    ("dissimilar", "Apache-2.0"),    // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
+    ("self_cell", "Apache-2.0"),                             // rustc (fluent translations)
+    ("snap", "BSD-3-Clause"),                                // rustc
+    // tidy-alphabetical-end
 ];
 
 const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
+    // tidy-alphabetical-start
     ("bitmaps", "MPL-2.0+"),
     ("bytesize", "Apache-2.0"),
     ("dunce", "CC0-1.0 OR MIT-0"),
@@ -62,9 +68,11 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
     ("sized-chunks", "MPL-2.0+"),
     ("subtle", "BSD-3-Clause"),
     ("unicode-bom", "Apache-2.0"),
+    // tidy-alphabetical-end
 ];
 
 const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
+    // tidy-alphabetical-start
     ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
@@ -80,6 +88,7 @@ const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
     ("regalloc2", "Apache-2.0 WITH LLVM-exception"),
     ("target-lexicon", "Apache-2.0 WITH LLVM-exception"),
     ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"),
+    // tidy-alphabetical-end
 ];
 
 const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
@@ -95,6 +104,7 @@ const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort",
 /// This list is here to provide a speed-bump to adding a new dependency to
 /// rustc. Please check with the compiler team before adding an entry.
 const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
+    // tidy-alphabetical-start
     "addr2line",
     "adler",
     "ahash",
@@ -113,8 +123,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "chalk-engine",
     "chalk-ir",
     "chalk-solve",
-    "convert_case", // dependency of derive_more
     "compiler_builtins",
+    "convert_case", // dependency of derive_more
     "cpufeatures",
     "crc32fast",
     "crossbeam-channel",
@@ -187,8 +197,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "ppv-lite86",
     "proc-macro-hack",
     "proc-macro2",
-    "pulldown-cmark",
     "psm",
+    "pulldown-cmark",
     "punycode",
     "quote",
     "rand",
@@ -227,6 +237,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "tempfile",
     "termcolor",
     "termize",
+    "thin-vec",
     "thiserror",
     "thiserror-impl",
     "thorin-dwp",
@@ -234,7 +245,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "tinystr",
     "tinyvec",
     "tinyvec_macros",
-    "thin-vec",
     "tracing",
     "tracing-attributes",
     "tracing-core",
@@ -263,29 +273,37 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "valuable",
     "version_check",
     "wasi",
-    "windows",
     "winapi",
     "winapi-i686-pc-windows-gnu",
     "winapi-util",
     "winapi-x86_64-pc-windows-gnu",
+    "windows",
+    "windows-targets",
+    "windows_aarch64_gnullvm",
+    "windows_aarch64_msvc",
+    "windows_i686_gnu",
+    "windows_i686_msvc",
+    "windows_x86_64_gnu",
+    "windows_x86_64_gnullvm",
+    "windows_x86_64_msvc",
     "writeable",
-    // this is a false-positive: it's only used by rustfmt, but because it's enabled through a
-    // feature, tidy thinks it's used by rustc as well.
-    "yansi-term",
+    "yansi-term", // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well.
     "yoke",
     "yoke-derive",
     "zerofrom",
     "zerofrom-derive",
     "zerovec",
     "zerovec-derive",
+    // tidy-alphabetical-end
 ];
 
 const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
+    // tidy-alphabetical-start
     "ahash",
     "anyhow",
     "autocfg",
-    "bumpalo",
     "bitflags",
+    "bumpalo",
     "byteorder",
     "cfg-if",
     "cranelift-bforest",
@@ -324,6 +342,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "winapi-i686-pc-windows-gnu",
     "winapi-x86_64-pc-windows-gnu",
     "windows-sys",
+    // tidy-alphabetical-end
 ];
 
 /// Dependency checks.
diff --git a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
new file mode 100644
index 0000000000000..af8ee2411d36d
--- /dev/null
+++ b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
@@ -0,0 +1,74 @@
+- // MIR for `mut_raw_then_mut_shr` before ReferencePropagation
++ // MIR for `mut_raw_then_mut_shr` after ReferencePropagation
+  
+  fn mut_raw_then_mut_shr() -> (i32, i32) {
+      let mut _0: (i32, i32);              // return place in scope 0 at $DIR/reference_prop.rs:+0:30: +0:40
+      let mut _1: i32;                     // in scope 0 at $DIR/reference_prop.rs:+1:9: +1:14
+      let mut _4: *mut i32;                // in scope 0 at $DIR/reference_prop.rs:+3:16: +3:36
+      let mut _5: &mut i32;                // in scope 0 at $DIR/reference_prop.rs:+3:16: +3:26
+      let _8: ();                          // in scope 0 at $DIR/reference_prop.rs:+7:5: +7:26
+      let mut _9: i32;                     // in scope 0 at $DIR/reference_prop.rs:+8:6: +8:7
+      let mut _10: i32;                    // in scope 0 at $DIR/reference_prop.rs:+8:9: +8:10
+      scope 1 {
+          debug x => _1;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:14
+          let _2: &mut i32;                // in scope 1 at $DIR/reference_prop.rs:+2:9: +2:13
+          scope 2 {
+              debug xref => _2;            // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
+              let _3: *mut i32;            // in scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
+              scope 3 {
+                  debug xraw => _3;        // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
+                  let _6: &i32;            // in scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
+                  scope 4 {
+                      debug xshr => _6;    // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
+                      let _7: i32;         // in scope 4 at $DIR/reference_prop.rs:+6:9: +6:10
+                      scope 5 {
+                          debug a => _7;   // in scope 5 at $DIR/reference_prop.rs:+6:9: +6:10
+                          scope 6 {
+                          }
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+1:9: +1:14
+          _1 = const 2_i32;                // scope 0 at $DIR/reference_prop.rs:+1:17: +1:18
+-         StorageLive(_2);                 // scope 1 at $DIR/reference_prop.rs:+2:9: +2:13
+          _2 = &mut _1;                    // scope 1 at $DIR/reference_prop.rs:+2:16: +2:22
+          StorageLive(_3);                 // scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
+-         StorageLive(_4);                 // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
+-         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
+-         _5 = &mut (*_2);                 // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
+-         _4 = &raw mut (*_5);             // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
++         _4 = &raw mut _1;                // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
+          _3 = _4;                         // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
+-         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
+-         StorageDead(_4);                 // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
+          StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
+-         _6 = &(*_2);                     // scope 3 at $DIR/reference_prop.rs:+4:16: +4:22
++         _6 = &_1;                        // scope 3 at $DIR/reference_prop.rs:+4:16: +4:22
+          StorageLive(_7);                 // scope 4 at $DIR/reference_prop.rs:+6:9: +6:10
+-         _7 = (*_6);                      // scope 4 at $DIR/reference_prop.rs:+6:13: +6:18
+-         StorageLive(_8);                 // scope 5 at $DIR/reference_prop.rs:+7:5: +7:26
+-         (*_3) = const 4_i32;             // scope 6 at $DIR/reference_prop.rs:+7:14: +7:23
+-         _8 = const ();                   // scope 6 at $DIR/reference_prop.rs:+7:5: +7:26
+-         StorageDead(_8);                 // scope 5 at $DIR/reference_prop.rs:+7:25: +7:26
++         _7 = _1;                         // scope 4 at $DIR/reference_prop.rs:+6:13: +6:18
++         _1 = const 4_i32;                // scope 6 at $DIR/reference_prop.rs:+7:14: +7:23
+          StorageLive(_9);                 // scope 5 at $DIR/reference_prop.rs:+8:6: +8:7
+          _9 = _7;                         // scope 5 at $DIR/reference_prop.rs:+8:6: +8:7
+          StorageLive(_10);                // scope 5 at $DIR/reference_prop.rs:+8:9: +8:10
+          _10 = _1;                        // scope 5 at $DIR/reference_prop.rs:+8:9: +8:10
+          _0 = (move _9, move _10);        // scope 5 at $DIR/reference_prop.rs:+8:5: +8:11
+          StorageDead(_10);                // scope 5 at $DIR/reference_prop.rs:+8:10: +8:11
+          StorageDead(_9);                 // scope 5 at $DIR/reference_prop.rs:+8:10: +8:11
+          StorageDead(_7);                 // scope 4 at $DIR/reference_prop.rs:+9:1: +9:2
+          StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+9:1: +9:2
+          StorageDead(_3);                 // scope 2 at $DIR/reference_prop.rs:+9:1: +9:2
+-         StorageDead(_2);                 // scope 1 at $DIR/reference_prop.rs:+9:1: +9:2
+          StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+9:1: +9:2
+          return;                          // scope 0 at $DIR/reference_prop.rs:+9:2: +9:2
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff b/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff
index a7d505c69066b..75c1f8f57ccae 100644
--- a/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff
@@ -9,15 +9,14 @@
       let mut _5: *mut usize;              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
   
       bb0: {
-          _2 = &mut (*_1);                 // scope 0 at $DIR/reference_prop.rs:+10:13: +10:25
+-         _2 = &mut (*_1);                 // scope 0 at $DIR/reference_prop.rs:+10:13: +10:25
 -         _3 = &mut (*_2);                 // scope 0 at $DIR/reference_prop.rs:+11:13: +11:26
 -         _4 = &raw mut (*_2);             // scope 0 at $DIR/reference_prop.rs:+12:13: +12:30
 -         _5 = &raw mut (*_3);             // scope 0 at $DIR/reference_prop.rs:+13:13: +13:30
 -         _0 = (*_4);                      // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
 -         _0 = (*_5);                      // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
-+         _3 = &mut (*_1);                 // scope 0 at $DIR/reference_prop.rs:+11:13: +11:26
-+         _0 = (*_2);                      // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
-+         _0 = (*_3);                      // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
++         _0 = (*_1);                      // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
++         _0 = (*_1);                      // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
           return;                          // scope 0 at $DIR/reference_prop.rs:+17:13: +17:21
       }
   }
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
index e3e5d791464eb..93f8d1df8e85a 100644
--- a/tests/mir-opt/reference_prop.rs
+++ b/tests/mir-opt/reference_prop.rs
@@ -433,6 +433,29 @@ fn maybe_dead(m: bool) {
     )
 }
 
+fn mut_raw_then_mut_shr() -> (i32, i32) {
+    let mut x = 2;
+    let xref = &mut x;
+    let xraw = &mut *xref as *mut _;
+    let xshr = &*xref;
+    // Verify that we completely replace with `x` in both cases.
+    let a = *xshr;
+    unsafe { *xraw = 4; }
+    (a, x)
+}
+
+fn unique_with_copies() {
+    let y = {
+        let mut a = 0;
+        let x = &raw mut a;
+        // `*y` is not replacable below, so we must not replace `*x`.
+        unsafe { opaque(*x) };
+        x
+    };
+    // But rewriting as `*x` is ok.
+    unsafe { opaque(*y) };
+}
+
 fn main() {
     let mut x = 5_usize;
     let mut y = 7_usize;
@@ -444,6 +467,8 @@ fn main() {
     multiple_storage();
     dominate_storage();
     maybe_dead(true);
+    mut_raw_then_mut_shr();
+    unique_with_copies();
 }
 
 // EMIT_MIR reference_prop.reference_propagation.ReferencePropagation.diff
@@ -454,3 +479,5 @@ fn main() {
 // EMIT_MIR reference_prop.multiple_storage.ReferencePropagation.diff
 // EMIT_MIR reference_prop.dominate_storage.ReferencePropagation.diff
 // EMIT_MIR reference_prop.maybe_dead.ReferencePropagation.diff
+// EMIT_MIR reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
+// EMIT_MIR reference_prop.unique_with_copies.ReferencePropagation.diff
diff --git a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff
new file mode 100644
index 0000000000000..2cda2409e8093
--- /dev/null
+++ b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff
@@ -0,0 +1,66 @@
+- // MIR for `unique_with_copies` before ReferencePropagation
++ // MIR for `unique_with_copies` after ReferencePropagation
+  
+  fn unique_with_copies() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:25: +0:25
+      let _1: *mut i32;                    // in scope 0 at $DIR/reference_prop.rs:+1:9: +1:10
+      let mut _2: i32;                     // in scope 0 at $DIR/reference_prop.rs:+2:13: +2:18
+      let _4: ();                          // in scope 0 at $DIR/reference_prop.rs:+5:18: +5:28
+      let mut _5: i32;                     // in scope 0 at $DIR/reference_prop.rs:+5:25: +5:27
+      let _6: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:14: +9:24
+      let mut _7: i32;                     // in scope 0 at $DIR/reference_prop.rs:+9:21: +9:23
+      scope 1 {
+          debug y => _1;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:10
+          scope 5 {
+          }
+      }
+      scope 2 {
+          debug a => _2;                   // in scope 2 at $DIR/reference_prop.rs:+2:13: +2:18
+          let _3: *mut i32;                // in scope 2 at $DIR/reference_prop.rs:+3:13: +3:14
+          scope 3 {
+              debug x => _3;               // in scope 3 at $DIR/reference_prop.rs:+3:13: +3:14
+              scope 4 {
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 0 at $DIR/reference_prop.rs:+2:13: +2:18
+          _2 = const 0_i32;                // scope 0 at $DIR/reference_prop.rs:+2:21: +2:22
+-         StorageLive(_3);                 // scope 2 at $DIR/reference_prop.rs:+3:13: +3:14
+          _3 = &raw mut _2;                // scope 2 at $DIR/reference_prop.rs:+3:17: +3:27
+          StorageLive(_4);                 // scope 3 at $DIR/reference_prop.rs:+5:9: +5:30
+          StorageLive(_5);                 // scope 4 at $DIR/reference_prop.rs:+5:25: +5:27
+          _5 = (*_3);                      // scope 4 at $DIR/reference_prop.rs:+5:25: +5:27
+          _4 = opaque::<i32>(move _5) -> bb1; // scope 4 at $DIR/reference_prop.rs:+5:18: +5:28
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:452:18: 452:24
+                                           // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_5);                 // scope 4 at $DIR/reference_prop.rs:+5:27: +5:28
+          StorageDead(_4);                 // scope 3 at $DIR/reference_prop.rs:+5:30: +5:31
+          _1 = _3;                         // scope 3 at $DIR/reference_prop.rs:+6:9: +6:10
+-         StorageDead(_3);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
+          StorageDead(_2);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
+          StorageLive(_6);                 // scope 1 at $DIR/reference_prop.rs:+9:5: +9:26
+          StorageLive(_7);                 // scope 5 at $DIR/reference_prop.rs:+9:21: +9:23
+-         _7 = (*_1);                      // scope 5 at $DIR/reference_prop.rs:+9:21: +9:23
++         _7 = (*_3);                      // scope 5 at $DIR/reference_prop.rs:+9:21: +9:23
+          _6 = opaque::<i32>(move _7) -> bb2; // scope 5 at $DIR/reference_prop.rs:+9:14: +9:24
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:456:14: 456:20
+                                           // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
+      }
+  
+      bb2: {
+          StorageDead(_7);                 // scope 5 at $DIR/reference_prop.rs:+9:23: +9:24
+          StorageDead(_6);                 // scope 1 at $DIR/reference_prop.rs:+9:26: +9:27
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+0:25: +10:2
+          StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+10:1: +10:2
+          return;                          // scope 0 at $DIR/reference_prop.rs:+10:2: +10:2
+      }
+  }
+  
diff --git a/tests/run-make/coverage-reports/Makefile b/tests/run-make/coverage-reports/Makefile
index d4ae03e590a30..0ae409c4119e8 100644
--- a/tests/run-make/coverage-reports/Makefile
+++ b/tests/run-make/coverage-reports/Makefile
@@ -138,6 +138,7 @@ endif
 			) \
 		2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
 		| "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
+		| "$(PYTHON)" $(BASEDIR)/sort_subviews.py \
 		> "$(TMPDIR)"/actual_show_coverage.$@.txt || \
 	( status=$$? ; \
 		>&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
@@ -158,23 +159,15 @@ ifdef RUSTC_BLESS_TEST
 else
 	# Compare the show coverage output (`--bless` refreshes `typical` files).
 	#
-	# FIXME(richkadel): None of the Rust test source samples have the
-	# `// ignore-llvm-cov-show-diffs` anymore. This directive exists to work around a limitation
-	# with `llvm-cov show`. When reporting coverage for multiple instantiations of a generic function,
-	# with different type substitutions, `llvm-cov show` prints these in a non-deterministic order,
-	# breaking the `diff` comparison.
+	# `llvm-cov show` normally prints instantiation groups in an unpredictable
+	# order, but we have used `sort_subviews.py` to sort them, so we can still
+	# check the output directly with `diff`.
 	#
-	# A partial workaround is implemented below, with `diff --ignore-matching-lines=RE`
-	# to ignore each line prefixing each generic instantiation coverage code region.
-	#
-	# This workaround only works if the coverage counts are identical across all reported
-	# instantiations. If there is no way to ensure this, you may need to apply the
-	# `// ignore-llvm-cov-show-diffs` directive, and check for differences using the
-	# `.json` files to validate that results have not changed. (Until then, the JSON
-	# files are redundant, so there is no need to generate `expected_*.json` files or
-	# compare actual JSON results.)
-
-	$(DIFF) --ignore-matching-lines='^  \| .*::<.*>.*:$$' --ignore-matching-lines='^  \| <.*>::.*:$$' \
+	# Some of the test cases are currently not working (since #110393) and have
+	# been marked with `// ignore-llvm-cov-show-diffs` so that they don't fail
+	# the build.
+
+	$(DIFF) \
 		expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
 		( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
 			>&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async.txt b/tests/run-make/coverage-reports/expected_show_coverage.async.txt
index 87ccb6c43eab3..93c1535b06b50 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.async.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.async.txt
@@ -41,9 +41,9 @@
    41|      1|                    // executed asynchronously.
    42|      1|    match x {
    43|      1|        y if c(x).await == y + 1 => { d().await; }
-                      ^0       ^0                   ^0 ^0
+                      ^0        ^0                  ^0  ^0
    44|      1|        y if f().await == y + 1 => (),
-                      ^0      ^0                 ^0
+                      ^0       ^0                ^0
    45|      1|        _ => (),
    46|       |    }
    47|      1|}
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt b/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt
new file mode 100644
index 0000000000000..81468cb35dac3
--- /dev/null
+++ b/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt
@@ -0,0 +1,49 @@
+    1|       |// compile-flags: --edition=2021
+    2|       |
+    3|       |// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
+    4|       |// predictable order, while preserving their heterogeneous contents.
+    5|       |
+    6|      1|fn main() {
+    7|      1|    let cond = std::env::args().len() > 1;
+    8|      1|    generic_fn::<()>(cond);
+    9|      1|    generic_fn::<&'static str>(!cond);
+   10|      1|    if false {
+   11|      0|        generic_fn::<char>(cond);
+   12|      1|    }
+   13|      1|    generic_fn::<i32>(cond);
+   14|      1|    other_fn();
+   15|      1|}
+   16|       |
+   17|      3|fn generic_fn<T>(cond: bool) {
+   18|      3|    if cond {
+   19|      1|        println!("{}", std::any::type_name::<T>());
+   20|      2|    }
+   21|      3|}
+  ------------------
+  | Unexecuted instantiation: sort_groups::generic_fn::<char>
+  ------------------
+  | sort_groups::generic_fn::<&str>:
+  |   17|      1|fn generic_fn<T>(cond: bool) {
+  |   18|      1|    if cond {
+  |   19|      1|        println!("{}", std::any::type_name::<T>());
+  |   20|      1|    }
+  |                   ^0
+  |   21|      1|}
+  ------------------
+  | sort_groups::generic_fn::<()>:
+  |   17|      1|fn generic_fn<T>(cond: bool) {
+  |   18|      1|    if cond {
+  |   19|      0|        println!("{}", std::any::type_name::<T>());
+  |   20|      1|    }
+  |   21|      1|}
+  ------------------
+  | sort_groups::generic_fn::<i32>:
+  |   17|      1|fn generic_fn<T>(cond: bool) {
+  |   18|      1|    if cond {
+  |   19|      0|        println!("{}", std::any::type_name::<T>());
+  |   20|      1|    }
+  |   21|      1|}
+  ------------------
+   22|       |
+   23|      1|fn other_fn() {}
+
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt b/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
index 65eb1008dd83b..412f4a93b9c99 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
@@ -19,29 +19,29 @@
    18|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
    19|      2|}
   ------------------
-  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
+  | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
+  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
   |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   19|      1|}
   ------------------
-  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
   |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   19|      1|}
-  ------------------
-  | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
   ------------------
    20|       |// Expect for above function: `Unexecuted instantiation` (see below)
    21|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
    22|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
    23|      2|}
   ------------------
-  | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
   |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
   |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
   |   23|      1|}
   ------------------
-  | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+  | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
   |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
   |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
   |   23|      1|}
@@ -51,12 +51,12 @@
    26|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
    27|      2|}
   ------------------
-  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
   |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
   |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
   |   27|      1|}
   ------------------
-  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
+  | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
   |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
   |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
   |   27|      1|}
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
index 748343885de1d..66ca9e80a3278 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
@@ -42,6 +42,8 @@
    40|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
    41|      2|}
   ------------------
+  | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
+  ------------------
   | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
   |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
@@ -51,8 +53,6 @@
   |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   41|      1|}
-  ------------------
-  | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
   ------------------
    42|       |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
    43|       |
@@ -77,15 +77,15 @@
    51|      3|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
    52|      3|}
   ------------------
-  | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
-  |   50|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   51|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   52|      1|}
-  ------------------
   | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
   |   50|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
   |   51|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
   |   52|      2|}
+  ------------------
+  | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  |   50|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   51|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   52|      1|}
   ------------------
    53|       |
    54|       |#[inline(always)]
diff --git a/tests/run-make/coverage-reports/sort_subviews.py b/tests/run-make/coverage-reports/sort_subviews.py
new file mode 100644
index 0000000000000..10cfc51d44771
--- /dev/null
+++ b/tests/run-make/coverage-reports/sort_subviews.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+
+# `llvm-cov show` prints grouped subviews (e.g. for generic functions) in an
+# unstable order, which is inconvenient when checking output snapshots with
+# `diff`. To work around that, this script detects consecutive subviews in its
+# piped input, and sorts them while preserving their contents.
+
+from __future__ import print_function
+
+import sys
+
+
+def main():
+    subviews = []
+
+    def flush_subviews():
+        if not subviews:
+            return
+
+        # The last "subview" should be just a boundary line on its own, so
+        # temporarily remove it before sorting the accumulated subviews.
+        terminator = subviews.pop()
+        subviews.sort()
+        subviews.append(terminator)
+
+        for view in subviews:
+            for line in view:
+                print(line, end="")
+
+        subviews.clear()
+
+    for line in sys.stdin:
+        if line.startswith("  ------------------"):
+            # This is a subview boundary line, so start a new subview.
+            subviews.append([line])
+        elif line.startswith("  |"):
+            # Add this line to the current subview.
+            subviews[-1].append(line)
+        else:
+            # This line is not part of a subview, so sort and print any
+            # accumulated subviews, and then print the line as-is.
+            flush_subviews()
+            print(line, end="")
+
+    flush_subviews()
+    assert not subviews
+
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/run-make/coverage/sort_groups.rs b/tests/run-make/coverage/sort_groups.rs
new file mode 100644
index 0000000000000..f89f9f3ec61fa
--- /dev/null
+++ b/tests/run-make/coverage/sort_groups.rs
@@ -0,0 +1,23 @@
+// compile-flags: --edition=2021
+
+// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
+// predictable order, while preserving their heterogeneous contents.
+
+fn main() {
+    let cond = std::env::args().len() > 1;
+    generic_fn::<()>(cond);
+    generic_fn::<&'static str>(!cond);
+    if false {
+        generic_fn::<char>(cond);
+    }
+    generic_fn::<i32>(cond);
+    other_fn();
+}
+
+fn generic_fn<T>(cond: bool) {
+    if cond {
+        println!("{}", std::any::type_name::<T>());
+    }
+}
+
+fn other_fn() {}
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr
similarity index 91%
rename from tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr
rename to tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr
index 8726fae79a006..ba42f619a5461 100644
--- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `&T` needs to have the same ABI as a pointer
-  --> $DIR/check-size-at-cast-polymorphic-bad.rs:11:15
+  --> $DIR/check-size-at-cast-polymorphic-bad.rs:14:15
    |
 LL |     dyn_debug(t);
    |               ^ `&T` needs to be a pointer-like type
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr
new file mode 100644
index 0000000000000..ba42f619a5461
--- /dev/null
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: `&T` needs to have the same ABI as a pointer
+  --> $DIR/check-size-at-cast-polymorphic-bad.rs:14:15
+   |
+LL |     dyn_debug(t);
+   |               ^ `&T` needs to be a pointer-like type
+   |
+   = help: the trait `PointerLike` is not implemented for `&T`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerLike {
+   |                                          +++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
index 913c2faacbd61..9846f87142457 100644
--- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
@@ -1,3 +1,6 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
 #![feature(dyn_star)]
 #![allow(incomplete_features)]