Auto merge of #111562 - clubby789:speedup-bootstrap-py, r=jyn514

Improve startup time of bootstrap

~~If the user has a `build/host` symlink set up, we can determine the target triple by reading it rather than invoking rustc. This significantly reduces startup time of bootstrap once any kind of build has been done~~
New approach explained below
```
➜  hyperfine -p 'git checkout -q master' -N './x.py -h' -r 50
Benchmark 1: ./x.py -h
  Time (mean ± σ):     140.7 ms ±   2.6 ms    [User: 99.9 ms, System: 39.3 ms]
  Range (min … max):   136.8 ms … 149.6 ms    50 runs

➜  rust git:(master) hyperfine -p 'git checkout -q speedup-bootstrap-py' -N './x.py -h' -r 50
Benchmark 1: ./x.py -h
  Time (mean ± σ):      95.2 ms ±   1.5 ms    [User: 67.7 ms, System: 26.7 ms]
  Range (min … max):    92.9 ms …  99.6 ms    50 runs
```

Also a small microoptimisation in using string splitting rather than regex when reading toml, which saves a few more milliseconds (2-5 testing locally), but less important.

Profiling shows the remaining runtime is around half setting up the Python runtime, and the vast majority of the remaining time is spent in subprocess building and running bootstrap itself, so probably can't be improved much further.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2d8980f..b12a0b8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -201,6 +201,9 @@
           - name: dist-i686-linux
             os: ubuntu-20.04-8core-32gb
             env: {}
+          - name: dist-loongarch64-linux
+            os: ubuntu-20.04-8core-32gb
+            env: {}
           - name: dist-mips-linux
             os: ubuntu-20.04-8core-32gb
             env: {}
diff --git a/Cargo.lock b/Cargo.lock
index bb37fee..0369442 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -154,11 +154,11 @@
 
 [[package]]
 name = "ar_archive_writer"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0639441fd17a3197d1cbca8dc8768cc172a63b64b4bb6c372e8f41ed0acc9bb"
+checksum = "74cfb39880a59e122232cb5fb06b20b4382d58c12fa9747d16f846d38a7b094c"
 dependencies = [
- "object",
+ "object 0.31.1",
 ]
 
 [[package]]
@@ -233,7 +233,7 @@
  "cfg-if",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.30.1",
  "rustc-demangle",
 ]
 
@@ -247,6 +247,15 @@
 ]
 
 [[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
 name = "bitflags"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -332,6 +341,12 @@
 ]
 
 [[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
 name = "bytes"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -629,7 +644,7 @@
  "itertools",
  "pulldown-cmark",
  "quine-mc_cluskey",
- "regex-syntax",
+ "regex-syntax 0.7.1",
  "rustc-semver",
  "semver",
  "serde",
@@ -711,9 +726,9 @@
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.91"
+version = "0.1.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a"
+checksum = "64518f1ae689f74db058bbfb3238dfe6eb53f59f4ae712f1ff4348628522e190"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -723,6 +738,7 @@
 name = "compiletest"
 version = "0.0.0"
 dependencies = [
+ "anyhow",
  "build_helper",
  "colored",
  "diff",
@@ -854,7 +870,7 @@
  "autocfg",
  "cfg-if",
  "crossbeam-utils",
- "memoffset",
+ "memoffset 0.7.1",
  "scopeguard",
 ]
 
@@ -888,6 +904,16 @@
 ]
 
 [[package]]
+name = "ctrlc"
+version = "3.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7394a21d012ce5c850497fb774b167d81b99f060025fbf06ee92b9848bd97eb2"
+dependencies = [
+ "nix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "curl"
 version = "0.4.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1242,6 +1268,16 @@
 ]
 
 [[package]]
+name = "field-offset"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535"
+dependencies = [
+ "memoffset 0.8.0",
+ "rustc_version",
+]
+
+[[package]]
 name = "filetime"
 version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2190,6 +2226,15 @@
 
 [[package]]
 name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memoffset"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
@@ -2198,6 +2243,15 @@
 ]
 
 [[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
 name = "mime"
 version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2260,6 +2314,7 @@
 version = "0.1.0"
 dependencies = [
  "colored",
+ "ctrlc",
  "env_logger 0.9.0",
  "getrandom",
  "lazy_static",
@@ -2290,6 +2345,18 @@
 checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
 
 [[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
+[[package]]
 name = "nom"
 version = "7.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2336,13 +2403,23 @@
 checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a"
 dependencies = [
  "compiler_builtins",
+ "memchr",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
+name = "object"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
+dependencies = [
  "crc32fast",
  "flate2",
  "hashbrown 0.13.1",
  "indexmap",
  "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
+ "ruzstd",
 ]
 
 [[package]]
@@ -2667,9 +2744,9 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.53"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
 dependencies = [
  "unicode-ident",
 ]
@@ -2702,9 +2779,9 @@
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.9.2"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
+checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
 dependencies = [
  "bitflags",
  "memchr",
@@ -2837,7 +2914,7 @@
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax",
+ "regex-syntax 0.6.26",
 ]
 
 [[package]]
@@ -2846,7 +2923,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 dependencies = [
- "regex-syntax",
+ "regex-syntax 0.6.26",
 ]
 
 [[package]]
@@ -2865,6 +2942,12 @@
 checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
 
 [[package]]
+name = "regex-syntax"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+
+[[package]]
 name = "remote-test-client"
 version = "0.1.0"
 
@@ -3194,7 +3277,7 @@
  "cstr",
  "libc",
  "measureme",
- "object",
+ "object 0.31.1",
  "rustc-demangle",
  "rustc_ast",
  "rustc_attr",
@@ -3230,7 +3313,7 @@
  "itertools",
  "jobserver",
  "libc",
- "object",
+ "object 0.31.1",
  "pathdiff",
  "regex",
  "rustc_arena",
@@ -3306,6 +3389,7 @@
  "rustc-hash",
  "rustc-rayon",
  "rustc-rayon-core",
+ "rustc_arena",
  "rustc_graphviz",
  "rustc_index",
  "rustc_macros",
@@ -3781,6 +3865,7 @@
  "chalk-ir",
  "derive_more",
  "either",
+ "field-offset",
  "gsgdt",
  "measureme",
  "polonius-engine",
@@ -3995,7 +4080,9 @@
 name = "rustc_query_impl"
 version = "0.0.0"
 dependencies = [
+ "field-offset",
  "measureme",
+ "memoffset 0.6.5",
  "rustc-rayon-core",
  "rustc_ast",
  "rustc_data_structures",
@@ -4296,6 +4383,7 @@
 name = "rustdoc-json-types"
 version = "0.1.0"
 dependencies = [
+ "bincode",
  "rustc-hash",
  "serde",
  "serde_json",
@@ -4386,6 +4474,17 @@
 checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
 
 [[package]]
+name = "ruzstd"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a15e661f0f9dac21f3494fe5d23a6338c0ac116a2d22c2b63010acd89467ffe"
+dependencies = [
+ "byteorder",
+ "thiserror",
+ "twox-hash",
+]
+
+[[package]]
 name = "ryu"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4445,18 +4544,18 @@
 
 [[package]]
 name = "serde"
-version = "1.0.159"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.159"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4621,7 +4720,7 @@
  "hermit-abi 0.3.0",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.30.1",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -4893,13 +4992,13 @@
 
 [[package]]
 name = "thorin-dwp"
-version = "0.4.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da8fbf660a019b6bf11ea95762041464aa9099cc293b6a66d77cea5107619671"
+checksum = "98c040e1340b889d4180c64e1d787efa9c32cb1617757e101480b61238b0d927"
 dependencies = [
  "gimli 0.26.2",
  "hashbrown 0.12.3",
- "object",
+ "object 0.31.1",
  "tracing",
 ]
 
@@ -5122,9 +5221,9 @@
 
 [[package]]
 name = "ui_test"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
+checksum = "191a442639ea102fa62671026047e51d574bfda44b7fdf32151d7314624c1cd2"
 dependencies = [
  "bstr 1.3.0",
  "cargo-platform",
diff --git a/RELEASES.md b/RELEASES.md
index e72905c..85266a1 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1481,7 +1481,7 @@
 [is_power_of_two_usize]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroUsize.html#method.is_power_of_two
 [stdarch/1266]: https://github.com/rust-lang/stdarch/pull/1266
 
-Version 1.58.1 (2022-01-19)
+Version 1.58.1 (2022-01-20)
 ===========================
 
 * Fix race condition in `std::fs::remove_dir_all` ([CVE-2022-21658])
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 3d97d9b..f11c1c7 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -12,7 +12,7 @@
 pub trait LayoutCalculator {
     type TargetDataLayoutRef: Borrow<TargetDataLayout>;
 
-    fn delay_bug(&self, txt: &str);
+    fn delay_bug(&self, txt: String);
     fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
 
     fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS {
@@ -969,7 +969,7 @@
     for &i in &inverse_memory_index {
         let field = &fields[i];
         if !sized {
-            this.delay_bug(&format!(
+            this.delay_bug(format!(
                 "univariant: field #{} comes after unsized field",
                 offsets.len(),
             ));
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 43b429f..4360fbe 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2391,10 +2391,10 @@
 
 impl FnDecl {
     pub fn has_self(&self) -> bool {
-        self.inputs.get(0).map_or(false, Param::is_self)
+        self.inputs.get(0).is_some_and(Param::is_self)
     }
     pub fn c_variadic(&self) -> bool {
-        self.inputs.last().map_or(false, |arg| matches!(arg.ty.kind, TyKind::CVarArgs))
+        self.inputs.last().is_some_and(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
     }
 }
 
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index e6c4db9..15fe295 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -149,7 +149,7 @@
     }
 
     pub fn may_have_doc_links(&self) -> bool {
-        self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
+        self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
     }
 
     pub fn is_proc_macro_attr(&self) -> bool {
@@ -441,12 +441,12 @@
 
     /// Returns `true` if this list item is a MetaItem with a name of `name`.
     pub fn has_name(&self, name: Symbol) -> bool {
-        self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
+        self.meta_item().is_some_and(|meta_item| meta_item.has_name(name))
     }
 
     /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
     pub fn is_word(&self) -> bool {
-        self.meta_item().map_or(false, |meta_item| meta_item.is_word())
+        self.meta_item().is_some_and(|meta_item| meta_item.is_word())
     }
 
     /// Gets a list of inner meta items from a list `MetaItem` type.
diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs
index 3593949..e87f6e8 100644
--- a/compiler/rustc_ast/src/expand/allocator.rs
+++ b/compiler/rustc_ast/src/expand/allocator.rs
@@ -1,20 +1,28 @@
 use rustc_span::symbol::{sym, Symbol};
 
-#[derive(Clone, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, Debug, Copy, Eq, PartialEq, HashStable_Generic)]
 pub enum AllocatorKind {
     Global,
     Default,
 }
 
-impl AllocatorKind {
-    pub fn fn_name(&self, base: Symbol) -> String {
-        match *self {
-            AllocatorKind::Global => format!("__rg_{base}"),
-            AllocatorKind::Default => format!("__rdl_{base}"),
-        }
+pub fn global_fn_name(base: Symbol) -> String {
+    format!("__rust_{base}")
+}
+
+pub fn default_fn_name(base: Symbol) -> String {
+    format!("__rdl_{base}")
+}
+
+pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str {
+    match alloc_error_handler_kind {
+        AllocatorKind::Global => "__rg_oom",
+        AllocatorKind::Default => "__rdl_oom",
     }
 }
 
+pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable";
+
 pub enum AllocatorTy {
     Layout,
     Ptr,
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 42b8434..7ef39f8 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -607,7 +607,7 @@
     /// Returns `true` if the token is an identifier whose name is the given
     /// string slice.
     pub fn is_ident_named(&self, name: Symbol) -> bool {
-        self.ident().map_or(false, |(ident, _)| ident.name == name)
+        self.ident().is_some_and(|(ident, _)| ident.name == name)
     }
 
     /// Returns `true` if the token is an interpolated path.
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index f0a6a5e..db296aa 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -48,14 +48,15 @@
     Delimited(DelimSpan, Delimiter, TokenStream),
 }
 
-// Ensure all fields of `TokenTree` is `Send` and `Sync`.
+// Ensure all fields of `TokenTree` are `DynSend` and `DynSync`.
 #[cfg(parallel_compiler)]
 fn _dummy()
 where
-    Token: Send + Sync,
-    DelimSpan: Send + Sync,
-    Delimiter: Send + Sync,
-    TokenStream: Send + Sync,
+    Token: sync::DynSend + sync::DynSync,
+    Spacing: sync::DynSend + sync::DynSync,
+    DelimSpan: sync::DynSend + sync::DynSync,
+    Delimiter: sync::DynSend + sync::DynSync,
+    TokenStream: sync::DynSend + sync::DynSync,
 {
 }
 
@@ -118,7 +119,7 @@
     }
 }
 
-pub trait ToAttrTokenStream: sync::Send + sync::Sync {
+pub trait ToAttrTokenStream: sync::DynSend + sync::DynSync {
     fn to_attr_token_stream(&self) -> AttrTokenStream;
 }
 
@@ -550,6 +551,10 @@
             vec_mut.extend(stream_iter);
         }
     }
+
+    pub fn chunks(&self, chunk_size: usize) -> core::slice::Chunks<'_, TokenTree> {
+        self.0.chunks(chunk_size)
+    }
 }
 
 /// By-reference iterator over a [`TokenStream`], that produces `&TokenTree`
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 15a54fe..50eb921 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -392,8 +392,7 @@
         // Small bases are lexed as if they were base 10, e.g, the string
         // might be `0b10201`. This will cause the conversion above to fail,
         // but these kinds of errors are already reported by the lexer.
-        let from_lexer =
-            base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
+        let from_lexer = base < 10 && s.chars().any(|c| c.to_digit(10).is_some_and(|d| d >= base));
         if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) }
     })
 }
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 21b2a3c..f63a9bf 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -1,144 +1,29 @@
-ast_lowering_generic_type_with_parentheses =
-    parenthesized type parameters may only be used with a `Fn` trait
-    .label = only `Fn` traits may use parentheses
-
-ast_lowering_use_angle_brackets = use angle brackets instead
-
-ast_lowering_invalid_abi =
-    invalid ABI: found `{$abi}`
-    .label = invalid ABI
-    .note = invoke `{$command}` for a full list of supported calling conventions.
-
-ast_lowering_invalid_abi_suggestion = did you mean
-
-ast_lowering_assoc_ty_parentheses =
-    parenthesized generic arguments cannot be used in associated type constraints
-
-ast_lowering_remove_parentheses = remove these parentheses
-
-ast_lowering_misplaced_impl_trait =
-    `impl Trait` only allowed in function and inherent method return types, not in {$position}
-
-ast_lowering_misplaced_assoc_ty_binding =
-    associated type bounds are only allowed in where clauses and function signatures, not in {$position}
-
-ast_lowering_underscore_expr_lhs_assign =
-    in expressions, `_` can only be used on the left-hand side of an assignment
-    .label = `_` not allowed here
-
-ast_lowering_base_expression_double_dot =
-    base expression required after `..`
-    .label = add a base expression here
-
-ast_lowering_await_only_in_async_fn_and_blocks =
-    `await` is only allowed inside `async` functions and blocks
-    .label = only allowed inside `async` functions and blocks
-
-ast_lowering_this_not_async = this is not `async`
-
-ast_lowering_generator_too_many_parameters =
-    too many parameters for a generator (expected 0 or 1 parameters)
-
-ast_lowering_closure_cannot_be_static = closures cannot be static
-
-ast_lowering_async_non_move_closure_not_supported =
-    `async` non-`move` closures with parameters are not currently supported
-    .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
-
-ast_lowering_functional_record_update_destructuring_assignment =
-    functional record updates are not allowed in destructuring assignments
-    .suggestion = consider removing the trailing pattern
-
-ast_lowering_async_generators_not_supported =
-    `async` generators are not yet supported
-
-ast_lowering_inline_asm_unsupported_target =
-    inline assembly is unsupported on this target
-
-ast_lowering_att_syntax_only_x86 =
-    the `att_syntax` option is only supported on x86
-
 ast_lowering_abi_specified_multiple_times =
     `{$prev_name}` ABI specified multiple times
     .label = previously specified here
     .note = these ABIs are equivalent on the current target
 
-ast_lowering_clobber_abi_not_supported =
-    `clobber_abi` is not supported on this target
-
-ast_lowering_invalid_abi_clobber_abi =
-    invalid ABI for `clobber_abi`
-    .note = the following ABIs are supported on this target: {$supported_abis}
-
-ast_lowering_invalid_register =
-    invalid register `{$reg}`: {$error}
-
-ast_lowering_invalid_register_class =
-    invalid register class `{$reg_class}`: {$error}
-
-ast_lowering_invalid_asm_template_modifier_reg_class =
-    invalid asm template modifier for this register class
-
-ast_lowering_argument = argument
-
-ast_lowering_template_modifier = template modifier
-
-ast_lowering_support_modifiers =
-    the `{$class_name}` register class supports the following template modifiers: {$modifiers}
-
-ast_lowering_does_not_support_modifiers =
-    the `{$class_name}` register class does not support template modifiers
-
-ast_lowering_invalid_asm_template_modifier_const =
-    asm template modifiers are not allowed for `const` arguments
-
-ast_lowering_invalid_asm_template_modifier_sym =
-    asm template modifiers are not allowed for `sym` arguments
-
-ast_lowering_register_class_only_clobber =
-    register class `{$reg_class_name}` can only be used as a clobber, not as an input or output
-
-ast_lowering_register_conflict =
-    register `{$reg1_name}` conflicts with register `{$reg2_name}`
-    .help = use `lateout` instead of `out` to avoid conflict
-
-ast_lowering_register1 = register `{$reg1_name}`
-
-ast_lowering_register2 = register `{$reg2_name}`
-
-ast_lowering_sub_tuple_binding =
-    `{$ident_name} @` is not allowed in a {$ctx}
-    .label = this is only allowed in slice patterns
-    .help = remove this and bind each tuple field independently
-
-ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields
-
-ast_lowering_extra_double_dot =
-    `..` can only be used once per {$ctx} pattern
-    .label = can only be used once per {$ctx} pattern
-
-ast_lowering_previously_used_here = previously used here
-
-ast_lowering_misplaced_double_dot =
-    `..` patterns are not allowed here
-    .note = only allowed in tuple, tuple struct, and slice patterns
-
-ast_lowering_misplaced_relax_trait_bound =
-    `?Trait` bounds are only permitted at the point where a type parameter is declared
-
-ast_lowering_not_supported_for_lifetime_binder_async_closure =
-    `for<...>` binders on `async` closures are not currently supported
-
 ast_lowering_arbitrary_expression_in_pattern =
     arbitrary expressions aren't allowed in patterns
 
-ast_lowering_inclusive_range_with_no_end = inclusive range with no end
+ast_lowering_argument = argument
 
-ast_lowering_trait_fn_async =
-    functions in traits cannot be declared `async`
-    .label = `async` because of this
-    .note = `async` trait functions are not currently supported
-    .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
+ast_lowering_assoc_ty_parentheses =
+    parenthesized generic arguments cannot be used in associated type constraints
+
+ast_lowering_async_generators_not_supported =
+    `async` generators are not yet supported
+
+ast_lowering_async_non_move_closure_not_supported =
+    `async` non-`move` closures with parameters are not currently supported
+    .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
+
+ast_lowering_att_syntax_only_x86 =
+    the `att_syntax` option is only supported on x86
+
+ast_lowering_await_only_in_async_fn_and_blocks =
+    `await` is only allowed inside `async` functions and blocks
+    .label = only allowed inside `async` functions and blocks
 
 ast_lowering_bad_return_type_notation_inputs =
     argument types not allowed with return type notation
@@ -151,3 +36,118 @@
 ast_lowering_bad_return_type_notation_output =
     return type not allowed with return type notation
     .suggestion = remove the return type
+
+ast_lowering_base_expression_double_dot =
+    base expression required after `..`
+    .label = add a base expression here
+
+ast_lowering_clobber_abi_not_supported =
+    `clobber_abi` is not supported on this target
+
+ast_lowering_closure_cannot_be_static = closures cannot be static
+
+ast_lowering_does_not_support_modifiers =
+    the `{$class_name}` register class does not support template modifiers
+
+ast_lowering_extra_double_dot =
+    `..` can only be used once per {$ctx} pattern
+    .label = can only be used once per {$ctx} pattern
+
+ast_lowering_functional_record_update_destructuring_assignment =
+    functional record updates are not allowed in destructuring assignments
+    .suggestion = consider removing the trailing pattern
+
+ast_lowering_generator_too_many_parameters =
+    too many parameters for a generator (expected 0 or 1 parameters)
+
+ast_lowering_generic_type_with_parentheses =
+    parenthesized type parameters may only be used with a `Fn` trait
+    .label = only `Fn` traits may use parentheses
+
+ast_lowering_inclusive_range_with_no_end = inclusive range with no end
+
+ast_lowering_inline_asm_unsupported_target =
+    inline assembly is unsupported on this target
+
+ast_lowering_invalid_abi =
+    invalid ABI: found `{$abi}`
+    .label = invalid ABI
+    .note = invoke `{$command}` for a full list of supported calling conventions.
+
+ast_lowering_invalid_abi_clobber_abi =
+    invalid ABI for `clobber_abi`
+    .note = the following ABIs are supported on this target: {$supported_abis}
+
+ast_lowering_invalid_abi_suggestion = did you mean
+
+ast_lowering_invalid_asm_template_modifier_const =
+    asm template modifiers are not allowed for `const` arguments
+
+ast_lowering_invalid_asm_template_modifier_reg_class =
+    invalid asm template modifier for this register class
+
+ast_lowering_invalid_asm_template_modifier_sym =
+    asm template modifiers are not allowed for `sym` arguments
+
+ast_lowering_invalid_register =
+    invalid register `{$reg}`: {$error}
+
+ast_lowering_invalid_register_class =
+    invalid register class `{$reg_class}`: {$error}
+
+ast_lowering_misplaced_assoc_ty_binding =
+    associated type bounds are only allowed in where clauses and function signatures, not in {$position}
+
+ast_lowering_misplaced_double_dot =
+    `..` patterns are not allowed here
+    .note = only allowed in tuple, tuple struct, and slice patterns
+
+ast_lowering_misplaced_impl_trait =
+    `impl Trait` only allowed in function and inherent method return types, not in {$position}
+
+ast_lowering_misplaced_relax_trait_bound =
+    `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+ast_lowering_not_supported_for_lifetime_binder_async_closure =
+    `for<...>` binders on `async` closures are not currently supported
+
+ast_lowering_previously_used_here = previously used here
+
+ast_lowering_register1 = register `{$reg1_name}`
+
+ast_lowering_register2 = register `{$reg2_name}`
+
+ast_lowering_register_class_only_clobber =
+    register class `{$reg_class_name}` can only be used as a clobber, not as an input or output
+
+ast_lowering_register_conflict =
+    register `{$reg1_name}` conflicts with register `{$reg2_name}`
+    .help = use `lateout` instead of `out` to avoid conflict
+
+ast_lowering_remove_parentheses = remove these parentheses
+
+ast_lowering_sub_tuple_binding =
+    `{$ident_name} @` is not allowed in a {$ctx}
+    .label = this is only allowed in slice patterns
+    .help = remove this and bind each tuple field independently
+
+ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields
+
+ast_lowering_support_modifiers =
+    the `{$class_name}` register class supports the following template modifiers: {$modifiers}
+
+ast_lowering_template_modifier = template modifier
+
+ast_lowering_this_not_async = this is not `async`
+
+ast_lowering_trait_fn_async =
+    functions in traits cannot be declared `async`
+    .label = `async` because of this
+    .note = `async` trait functions are not currently supported
+    .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+ast_lowering_underscore_expr_lhs_assign =
+    in expressions, `_` can only be used on the left-hand side of an assignment
+    .label = `_` not allowed here
+
+ast_lowering_use_angle_brackets = use angle brackets instead
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index cd6614a..8d4f966 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -58,7 +58,7 @@
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
@@ -435,6 +435,7 @@
     // Queries that borrow `resolver_for_lowering`.
     tcx.ensure_with_value().output_filenames(());
     tcx.ensure_with_value().early_lint_checks(());
+    tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE);
     let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
 
     let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
@@ -1424,7 +1425,16 @@
                             DefPathData::ImplTrait,
                             span,
                         );
-                        let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
+
+                        // HACK: pprust breaks strings with newlines when the type
+                        // gets too long. We don't want these to show up in compiler
+                        // output or built artifacts, so replace them here...
+                        // Perhaps we should instead format APITs more robustly.
+                        let ident = Ident::from_str_and_span(
+                            &pprust::ty_to_string(t).replace('\n', " "),
+                            span,
+                        );
+
                         let (param, bounds, path) = self.lower_universal_param_and_bounds(
                             *def_node_id,
                             span,
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 2f41378..2f0ac0c 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -1,48 +1,95 @@
-ast_passes_forbidden_let =
-    `let` expressions are not supported here
-    .note = only supported directly in conditions of `if` and `while` expressions
-    .not_supported_or = `||` operators are not supported in let chain expressions
-    .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
+ast_passes_assoc_const_without_body =
+    associated constant in `impl` without body
+    .suggestion = provide a definition for the constant
 
-ast_passes_forbidden_let_stable =
-    expected expression, found statement (`let`)
-    .note = variable declaration using `let` is a statement
+ast_passes_assoc_fn_without_body =
+    associated function in `impl` without body
+    .suggestion = provide a definition for the function
+
+ast_passes_assoc_type_without_body =
+    associated type in `impl` without body
+    .suggestion = provide a definition for the type
+
+ast_passes_at_least_one_trait = at least one trait must be specified
+
+ast_passes_auto_generic = auto traits cannot have generic parameters
+    .label = auto trait cannot have generic parameters
+    .suggestion = remove the parameters
+
+ast_passes_auto_items = auto traits cannot have associated items
+    .label = {ast_passes_auto_items}
+    .suggestion = remove these associated items
+
+ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds
+    .label = {ast_passes_auto_super_lifetime}
+    .suggestion = remove the super traits or lifetime bounds
+
+ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
+
+ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
+    .cannot_have = cannot have a body
+    .invalid = the invalid body
+    .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body
+
+ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
+
+ast_passes_const_and_async = functions cannot be both `const` and `async`
+    .const = `const` because of this
+    .async = `async` because of this
+    .label = {""}
+
+ast_passes_const_without_body =
+    free constant item without body
+    .suggestion = provide a definition for the constant
+
+ast_passes_constraint_on_negative_bound =
+    associated type constraints not allowed on negative bounds
 
 ast_passes_deprecated_where_clause_location =
     where clause not allowed here
 
-ast_passes_keyword_lifetime =
-    lifetimes cannot use keyword names
+ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
+    .label = not supported
+    .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
+    .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax
+    .note = see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
 
-ast_passes_invalid_label =
-    invalid label name `{$name}`
+ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
 
-ast_passes_visibility_not_permitted =
-    visibility qualifiers are not permitted here
-    .enum_variant = enum variants and their fields always share the visibility of the enum they are in
-    .trait_impl = trait items always share the visibility of their trait
-    .individual_impl_items = place qualifiers on individual impl items instead
-    .individual_foreign_items = place qualifiers on individual foreign items instead
+ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
+    .label = in this `extern` block
+    .suggestion = remove the qualifiers
 
-ast_passes_trait_fn_const =
-    functions in traits cannot be declared const
-    .label = functions in traits cannot be const
+ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
+    .label = in this `extern` block
+    .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
 
-ast_passes_forbidden_lifetime_bound =
-    lifetime bounds cannot be used in this context
+ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
-ast_passes_forbidden_non_lifetime_param =
-    only lifetime parameters can be used in this context
+ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr}
+    .suggestion = remove the {$remove_descr}
+    .label = `extern` block begins here
 
-ast_passes_fn_param_too_many =
-    function can not have more than {$max_num_args} arguments
+ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
 
-ast_passes_fn_param_c_var_args_only =
-    C-variadic function must be declared with at least one named argument
+ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
+    .suggestion = remove the attribute
+    .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
+
+ast_passes_fieldless_union = unions cannot have zero fields
+
+ast_passes_fn_body_extern = incorrect function inside `extern` block
+    .cannot_have = cannot have a body
+    .suggestion = remove the invalid body
+    .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+    .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body
 
 ast_passes_fn_param_c_var_args_not_last =
     `...` must be the last argument of a C-variadic function
 
+ast_passes_fn_param_c_var_args_only =
+    C-variadic function must be declared with at least one named argument
+
 ast_passes_fn_param_doc_comment =
     documentation comments cannot be applied to function parameters
     .label = doc comments are not allowed here
@@ -55,88 +102,32 @@
     .label = not semantically valid as function parameter
     .note = associated functions are those in `impl` or `trait` definitions
 
-ast_passes_forbidden_default =
-    `default` is only allowed on items in trait impls
-    .label = `default` because of this
-
-ast_passes_assoc_const_without_body =
-    associated constant in `impl` without body
-    .suggestion = provide a definition for the constant
-
-ast_passes_assoc_fn_without_body =
-    associated function in `impl` without body
-    .suggestion = provide a definition for the function
-
-ast_passes_assoc_type_without_body =
-    associated type in `impl` without body
-    .suggestion = provide a definition for the type
-
-ast_passes_const_without_body =
-    free constant item without body
-    .suggestion = provide a definition for the constant
-
-ast_passes_static_without_body =
-    free static item without body
-    .suggestion = provide a definition for the static
-
-ast_passes_ty_alias_without_body =
-    free type alias without body
-    .suggestion = provide a definition for the type
+ast_passes_fn_param_too_many =
+    function can not have more than {$max_num_args} arguments
 
 ast_passes_fn_without_body =
     free function without a body
     .suggestion = provide a definition for the function
 
-ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
+ast_passes_forbidden_default =
+    `default` is only allowed on items in trait impls
+    .label = `default` because of this
 
-ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
+ast_passes_forbidden_let =
+    `let` expressions are not supported here
+    .note = only supported directly in conditions of `if` and `while` expressions
+    .not_supported_or = `||` operators are not supported in let chain expressions
+    .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
 
-ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr}
-    .suggestion = remove the {$remove_descr}
-    .label = `extern` block begins here
+ast_passes_forbidden_let_stable =
+    expected expression, found statement (`let`)
+    .note = variable declaration using `let` is a statement
 
-ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+ast_passes_forbidden_lifetime_bound =
+    lifetime bounds cannot be used in this context
 
-ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
-    .cannot_have = cannot have a body
-    .invalid = the invalid body
-    .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body
-
-ast_passes_fn_body_extern = incorrect function inside `extern` block
-    .cannot_have = cannot have a body
-    .suggestion = remove the invalid body
-    .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
-    .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body
-
-ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
-    .label = in this `extern` block
-    .suggestion = remove the qualifiers
-
-ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
-    .label = in this `extern` block
-    .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
-
-ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
-
-ast_passes_item_underscore = `{$kind}` items in this context need a name
-    .label = `_` is not a valid name for this `{$kind}` item
-
-ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
-
-ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
-    .help = consider using the `#[path]` attribute to specify filesystem path
-
-ast_passes_auto_generic = auto traits cannot have generic parameters
-    .label = auto trait cannot have generic parameters
-    .suggestion = remove the parameters
-
-ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds
-    .label = {ast_passes_auto_super_lifetime}
-    .suggestion = remove the super traits or lifetime bounds
-
-ast_passes_auto_items = auto traits cannot have associated items
-    .label = {ast_passes_auto_items}
-    .suggestion = remove these associated items
+ast_passes_forbidden_non_lifetime_param =
+    only lifetime parameters can be used in this context
 
 ast_passes_generic_before_constraints = generic arguments must come before the first constraint
     .constraints = {$constraint_len ->
@@ -156,88 +147,97 @@
     *[other] arguments
     }
 
-ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types
-
-ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
+ast_passes_generic_default_trailing = generic parameters with a default must be trailing
 
 ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
 
-ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
-    .outer = outer `impl Trait`
-    .inner = nested `impl Trait` here
-
-ast_passes_at_least_one_trait = at least one trait must be specified
-
-ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
-
-ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
-    .suggestion = reorder the parameters: lifetimes, then consts and types
-
-ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
-    .help = use `auto trait Trait {"{}"}` instead
-
-ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
-    .negative = negative because of this
-    .unsafe = unsafe because of this
+ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
+    .help = remove one of these features
 
 ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
     .because = {$annotation} because of this
     .type = inherent impl for this type
     .only_trait = only trait implementations may be annotated with {$annotation}
 
-ast_passes_unsafe_item = {$kind} cannot be declared unsafe
+ast_passes_invalid_label =
+    invalid label name `{$name}`
 
-ast_passes_fieldless_union = unions cannot have zero fields
+ast_passes_item_underscore = `{$kind}` items in this context need a name
+    .label = `_` is not a valid name for this `{$kind}` item
 
-ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
-    .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+ast_passes_keyword_lifetime =
+    lifetimes cannot use keyword names
 
-ast_passes_generic_default_trailing = generic parameters with a default must be trailing
+ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
+    .help = consider using the `#[path]` attribute to specify filesystem path
+
+ast_passes_negative_bound_not_supported =
+    negative bounds are not supported
+
+ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
+    .outer = outer `impl Trait`
+    .inner = nested `impl Trait` here
 
 ast_passes_nested_lifetimes = nested quantification of lifetimes
 
+ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
+
+ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
+    .help = use `auto trait Trait {"{}"}` instead
+
+ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
+
+ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
+
 ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
     .note = traits are `?{$path_str}` by default
 
-ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
+ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
+    .suggestion = reorder the parameters: lifetimes, then consts and types
+
+ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies
+    .label = pattern not allowed in function without body
+
+ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types
+
+ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
+    .label = pattern not allowed in foreign function
+
+ast_passes_show_span = {$msg}
+
+ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
+
+ast_passes_static_without_body =
+    free static item without body
+    .suggestion = provide a definition for the static
 
 ast_passes_tilde_const_disallowed = `~const` is not allowed here
     .trait = trait objects cannot have `~const` trait bounds
     .closure = closures cannot have `~const` trait bounds
     .function = this function is not `const`, so it cannot have `~const` trait bounds
 
-ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
+ast_passes_trait_fn_const =
+    functions in traits cannot be declared const
+    .label = functions in traits cannot be const
 
-ast_passes_const_and_async = functions cannot be both `const` and `async`
-    .const = `const` because of this
-    .async = `async` because of this
-    .label = {""}
+ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
 
-ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
-    .label = pattern not allowed in foreign function
+ast_passes_ty_alias_without_body =
+    free type alias without body
+    .suggestion = provide a definition for the type
 
-ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies
-    .label = pattern not allowed in function without body
+ast_passes_unsafe_item = {$kind} cannot be declared unsafe
 
-ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
-    .label = not supported
-    .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
-    .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax
-    .note = see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
+    .negative = negative because of this
+    .unsafe = unsafe because of this
 
-ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
+ast_passes_visibility_not_permitted =
+    visibility qualifiers are not permitted here
+    .enum_variant = enum variants and their fields always share the visibility of the enum they are in
+    .trait_impl = trait items always share the visibility of their trait
+    .individual_impl_items = place qualifiers on individual impl items instead
+    .individual_foreign_items = place qualifiers on individual foreign items instead
 
-ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
-    .suggestion = remove the attribute
-    .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
-
-ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
-    .help = remove one of these features
-
-ast_passes_show_span = {$msg}
-
-ast_passes_negative_bound_not_supported =
-    negative bounds are not supported
-
-ast_passes_constraint_on_negative_bound =
-    associated type constraints not allowed on negative bounds
+ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
+    .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index bf43bbd..04ed276 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -348,7 +348,7 @@
         let source_map = self.session.source_map();
         let end = source_map.end_point(sp);
 
-        if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) {
+        if source_map.span_to_snippet(end).is_ok_and(|s| s == ";") {
             end
         } else {
             sp.shrink_to_hi()
@@ -736,11 +736,10 @@
                         this.visit_expr(&arm.body);
                         this.visit_pat(&arm.pat);
                         walk_list!(this, visit_attribute, &arm.attrs);
-                        if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind {
+                        if let Some(guard) = &arm.guard {
                             this.with_let_management(None, |this, _| {
-                                this.visit_expr(guard_expr)
+                                this.visit_expr(guard)
                             });
-                            return;
                         }
                     }
                 }
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 3d5056d..274f931 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -317,8 +317,7 @@
         match i.kind {
             ast::ForeignItemKind::Fn(..) | ast::ForeignItemKind::Static(..) => {
                 let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name);
-                let links_to_llvm =
-                    link_name.map_or(false, |val| val.as_str().starts_with("llvm."));
+                let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
                 if links_to_llvm {
                     gate_feature_post!(
                         &self,
diff --git a/compiler/rustc_attr/messages.ftl b/compiler/rustc_attr/messages.ftl
index a7f8c99..e6cbbaf 100644
--- a/compiler/rustc_attr/messages.ftl
+++ b/compiler/rustc_attr/messages.ftl
@@ -1,85 +1,3 @@
-attr_expected_one_cfg_pattern =
-    expected 1 cfg-pattern
-
-attr_invalid_predicate =
-    invalid predicate `{$predicate}`
-
-attr_multiple_item =
-    multiple '{$item}' items
-
-attr_incorrect_meta_item =
-    incorrect meta item
-
-attr_unknown_meta_item =
-    unknown meta item '{$item}'
-    .label = expected one of {$expected}
-
-attr_missing_since =
-    missing 'since'
-
-attr_missing_note =
-    missing 'note'
-
-attr_multiple_stability_levels =
-    multiple stability levels
-
-attr_invalid_issue_string =
-    `issue` must be a non-zero numeric string or "none"
-    .must_not_be_zero = `issue` must not be "0", use "none" instead
-    .empty = cannot parse integer from empty string
-    .invalid_digit = invalid digit found in string
-    .pos_overflow = number too large to fit in target type
-    .neg_overflow = number too small to fit in target type
-
-attr_missing_feature =
-    missing 'feature'
-
-attr_non_ident_feature =
-    'feature' is not an identifier
-
-attr_missing_issue =
-    missing 'issue'
-
-attr_incorrect_repr_format_packed_one_or_zero_arg =
-    incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
-
-attr_invalid_repr_hint_no_paren =
-    invalid representation hint: `{$name}` does not take a parenthesized argument list
-
-attr_invalid_repr_hint_no_value =
-    invalid representation hint: `{$name}` does not take a value
-
-attr_unsupported_literal_generic =
-    unsupported literal
-attr_unsupported_literal_cfg_string =
-    literal in `cfg` predicate value must be a string
-attr_unsupported_literal_deprecated_string =
-    literal in `deprecated` value must be a string
-attr_unsupported_literal_deprecated_kv_pair =
-    item in `deprecated` must be a key/value pair
-attr_unsupported_literal_suggestion =
-    consider removing the prefix
-
-attr_invalid_repr_align_need_arg =
-    invalid `repr(align)` attribute: `align` needs an argument
-    .suggestion = supply an argument here
-
-attr_invalid_repr_generic =
-    invalid `repr({$repr_arg})` attribute: {$error_part}
-
-attr_incorrect_repr_format_align_one_arg =
-    incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
-
-attr_incorrect_repr_format_generic =
-    incorrect `repr({$repr_arg})` attribute format
-    .suggestion = use parentheses instead
-
-attr_rustc_promotable_pairing =
-    `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
-
-attr_rustc_allowed_unstable_pairing =
-    `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
-
 attr_cfg_predicate_identifier =
     `cfg` predicate key must be an identifier
 
@@ -88,6 +6,9 @@
     .help = add `#![feature(deprecated_suggestion)]` to the crate root
     .note = see #94785 for more details
 
+attr_expected_one_cfg_pattern =
+    expected 1 cfg-pattern
+
 attr_expected_single_version_literal =
     expected single version literal
 
@@ -100,8 +21,87 @@
 attr_expects_features =
     `{$name}` expects feature names
 
+attr_incorrect_meta_item =
+    incorrect meta item
+
+attr_incorrect_repr_format_align_one_arg =
+    incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+
+attr_incorrect_repr_format_generic =
+    incorrect `repr({$repr_arg})` attribute format
+    .suggestion = use parentheses instead
+
+attr_incorrect_repr_format_packed_one_or_zero_arg =
+    incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+
+attr_invalid_issue_string =
+    `issue` must be a non-zero numeric string or "none"
+    .must_not_be_zero = `issue` must not be "0", use "none" instead
+    .empty = cannot parse integer from empty string
+    .invalid_digit = invalid digit found in string
+    .pos_overflow = number too large to fit in target type
+    .neg_overflow = number too small to fit in target type
+
+attr_invalid_predicate =
+    invalid predicate `{$predicate}`
+
+attr_invalid_repr_align_need_arg =
+    invalid `repr(align)` attribute: `align` needs an argument
+    .suggestion = supply an argument here
+
+attr_invalid_repr_generic =
+    invalid `repr({$repr_arg})` attribute: {$error_part}
+
+attr_invalid_repr_hint_no_paren =
+    invalid representation hint: `{$name}` does not take a parenthesized argument list
+
+attr_invalid_repr_hint_no_value =
+    invalid representation hint: `{$name}` does not take a value
+
+attr_missing_feature =
+    missing 'feature'
+
+attr_missing_issue =
+    missing 'issue'
+
+attr_missing_note =
+    missing 'note'
+
+attr_missing_since =
+    missing 'since'
+
+attr_multiple_item =
+    multiple '{$item}' items
+
+attr_multiple_stability_levels =
+    multiple stability levels
+
+attr_non_ident_feature =
+    'feature' is not an identifier
+
+attr_rustc_allowed_unstable_pairing =
+    `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
+
+attr_rustc_promotable_pairing =
+    `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
+
 attr_soft_no_args =
     `soft` should not have any arguments
 
+attr_unknown_meta_item =
+    unknown meta item '{$item}'
+    .label = expected one of {$expected}
+
 attr_unknown_version_literal =
     unknown version literal format, assuming it refers to a future version
+
+attr_unsupported_literal_cfg_string =
+    literal in `cfg` predicate value must be a string
+attr_unsupported_literal_deprecated_kv_pair =
+    item in `deprecated` must be a key/value pair
+attr_unsupported_literal_deprecated_string =
+    literal in `deprecated` value must be a string
+attr_unsupported_literal_generic =
+    unsupported literal
+attr_unsupported_literal_suggestion =
+    consider removing the prefix
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 2a3092d..372a588 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -23,8 +23,7 @@
 pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
 
 pub fn rust_version_symbol() -> Symbol {
-    let version = option_env!("CFG_VERSION").unwrap_or("<current>");
-    let version = version.split(' ').next().unwrap();
+    let version = option_env!("CFG_RELEASE").unwrap_or("<current>");
     Symbol::intern(&version)
 }
 
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index 4a616dc..67fdb67 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -1,150 +1,23 @@
-borrowck_move_unsized =
-    cannot move a value of type `{$ty}`
-    .label = the size of `{$ty}` cannot be statically determined
-
-borrowck_higher_ranked_lifetime_error =
-    higher-ranked lifetime error
-
-borrowck_could_not_prove =
-    could not prove `{$predicate}`
-
-borrowck_could_not_normalize =
-    could not normalize `{$value}`
-
-borrowck_higher_ranked_subtype_error =
-    higher-ranked subtype error
-
-borrowck_generic_does_not_live_long_enough =
-    `{$kind}` does not live long enough
-
-borrowck_move_borrowed =
-    cannot move out of `{$desc}` because it is borrowed
-
-borrowck_var_does_not_need_mut =
-    variable does not need to be mutable
-    .suggestion = remove this `mut`
-
-borrowck_var_cannot_escape_closure =
-    captured variable cannot escape `FnMut` closure body
-    .note = `FnMut` closures only have access to their captured variables while they are executing...
-    .cannot_escape = ...therefore, they cannot allow references to captured variables to escape
-
-borrowck_var_here_defined = variable defined here
-
-borrowck_var_here_captured = variable captured here
-
-borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
-
-borrowck_returned_closure_escaped =
-    returns a closure that contains a reference to a captured variable, which then escapes the closure body
-
-borrowck_returned_async_block_escaped =
-    returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
-
-borrowck_returned_ref_escaped =
-    returns a reference to a captured variable which escapes the closure body
-
-borrowck_lifetime_constraints_error =
-    lifetime may not live long enough
-
-borrowck_returned_lifetime_wrong =
-    {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
-
-borrowck_returned_lifetime_short =
-    {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
-
-borrowck_used_impl_require_static =
-    the used `impl` has a `'static` requirement
-
-borrowck_borrow_due_to_use_generator =
-    borrow occurs due to use in generator
-
-borrowck_use_due_to_use_generator =
-    use occurs due to use in generator
+borrowck_assign_due_to_use_closure =
+    assignment occurs due to use in closure
 
 borrowck_assign_due_to_use_generator =
     assign occurs due to use in generator
 
+borrowck_assign_part_due_to_use_closure =
+    assignment to part occurs due to use in closure
+
 borrowck_assign_part_due_to_use_generator =
     assign to part occurs due to use in generator
 
 borrowck_borrow_due_to_use_closure =
     borrow occurs due to use in closure
 
-borrowck_use_due_to_use_closure =
-    use occurs due to use in closure
-
-borrowck_assign_due_to_use_closure =
-    assignment occurs due to use in closure
-
-borrowck_assign_part_due_to_use_closure =
-    assignment to part occurs due to use in closure
-
-borrowck_capture_immute =
-    capture is immutable because of use here
-
-borrowck_capture_mut =
-    capture is mutable because of use here
-
-borrowck_capture_move =
-    capture is moved because of use here
-
-borrowck_var_borrow_by_use_place_in_generator =
-    {$is_single_var ->
-        *[true] borrow occurs
-        [false] borrows occur
-    } due to use of {$place} in generator
-
-borrowck_var_borrow_by_use_place_in_closure =
-    {$is_single_var ->
-        *[true] borrow occurs
-        [false] borrows occur
-    } due to use of {$place} in closure
-
-borrowck_var_borrow_by_use_in_generator =
+borrowck_borrow_due_to_use_generator =
     borrow occurs due to use in generator
 
-borrowck_var_borrow_by_use_in_closure =
-    borrow occurs due to use in closure
-
-borrowck_var_move_by_use_place_in_generator =
-    move occurs due to use of {$place} in generator
-
-borrowck_var_move_by_use_place_in_closure =
-    move occurs due to use of {$place} in closure
-
-borrowck_var_move_by_use_in_generator =
-    move occurs due to use in generator
-
-borrowck_var_move_by_use_in_closure =
-    move occurs due to use in closure
-
-borrowck_partial_var_move_by_use_in_generator =
-    variable {$is_partial ->
-        [true] partially moved
-        *[false] moved
-    } due to use in generator
-
-borrowck_partial_var_move_by_use_in_closure =
-    variable {$is_partial ->
-        [true] partially moved
-        *[false] moved
-    } due to use in closure
-
-borrowck_var_first_borrow_by_use_place_in_generator =
-    first borrow occurs due to use of {$place} in generator
-
-borrowck_var_first_borrow_by_use_place_in_closure =
-    first borrow occurs due to use of {$place} in closure
-
-borrowck_var_second_borrow_by_use_place_in_generator =
-    second borrow occurs due to use of {$place} in generator
-
-borrowck_var_second_borrow_by_use_place_in_closure =
-    second borrow occurs due to use of {$place} in closure
-
-borrowck_var_mutable_borrow_by_use_place_in_closure =
-    mutable borrow occurs due to use of {$place} in closure
+borrowck_calling_operator_moves_lhs =
+    calling this operator moves the left-hand side
 
 borrowck_cannot_move_when_borrowed =
     cannot move out of {$place ->
@@ -160,11 +33,67 @@
         *[other] {$value_place}
     } occurs here
 
-borrowck_opaque_type_non_generic_param =
-    expected generic {$kind} parameter, found `{$ty}`
-    .label = {STREQ($ty, "'static") ->
-        [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
-        *[other] this generic parameter must be used with a generic {$kind} parameter
+borrowck_capture_immute =
+    capture is immutable because of use here
+
+borrowck_capture_move =
+    capture is moved because of use here
+
+borrowck_capture_mut =
+    capture is mutable because of use here
+
+borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
+
+borrowck_closure_invoked_twice =
+    closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
+
+borrowck_closure_moved_twice =
+    closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
+
+borrowck_consider_borrow_type_contents =
+    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+
+borrowck_could_not_normalize =
+    could not normalize `{$value}`
+
+borrowck_could_not_prove =
+    could not prove `{$predicate}`
+
+borrowck_func_take_self_moved_place =
+    `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
+
+borrowck_generic_does_not_live_long_enough =
+    `{$kind}` does not live long enough
+
+borrowck_higher_ranked_lifetime_error =
+    higher-ranked lifetime error
+
+borrowck_higher_ranked_subtype_error =
+    higher-ranked subtype error
+
+borrowck_lifetime_constraints_error =
+    lifetime may not live long enough
+
+borrowck_move_borrowed =
+    cannot move out of `{$desc}` because it is borrowed
+
+borrowck_move_out_place_here =
+    {$place} is moved here
+
+borrowck_move_unsized =
+    cannot move a value of type `{$ty}`
+    .label = the size of `{$ty}` cannot be statically determined
+
+borrowck_moved_a_fn_once_in_call =
+    this value implements `FnOnce`, which causes it to be moved when called
+
+borrowck_moved_due_to_await =
+    {$place_name} {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to this {$is_loop_message ->
+        [true] await, in previous iteration of loop
+        *[false] await
     }
 
 borrowck_moved_due_to_call =
@@ -176,15 +105,6 @@
         *[false] call
     }
 
-borrowck_moved_due_to_usage_in_operator =
-    {$place_name} {$is_partial ->
-        [true] partially moved
-        *[false] moved
-    } due to usage in {$is_loop_message ->
-        [true] operator, in previous iteration of loop
-        *[false] operator
-    }
-
 borrowck_moved_due_to_implicit_into_iter_call =
     {$place_name} {$is_partial ->
         [true] partially moved
@@ -203,13 +123,74 @@
         *[false] call
     }
 
-borrowck_moved_due_to_await =
+borrowck_moved_due_to_usage_in_operator =
     {$place_name} {$is_partial ->
         [true] partially moved
         *[false] moved
-    } due to this {$is_loop_message ->
-        [true] await, in previous iteration of loop
-        *[false] await
+    } due to usage in {$is_loop_message ->
+        [true] operator, in previous iteration of loop
+        *[false] operator
+    }
+
+borrowck_opaque_type_non_generic_param =
+    expected generic {$kind} parameter, found `{$ty}`
+    .label = {STREQ($ty, "'static") ->
+        [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+        *[other] this generic parameter must be used with a generic {$kind} parameter
+    }
+
+borrowck_partial_var_move_by_use_in_closure =
+    variable {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to use in closure
+
+borrowck_partial_var_move_by_use_in_generator =
+    variable {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to use in generator
+
+borrowck_returned_async_block_escaped =
+    returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
+
+borrowck_returned_closure_escaped =
+    returns a closure that contains a reference to a captured variable, which then escapes the closure body
+
+borrowck_returned_lifetime_short =
+    {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
+
+borrowck_returned_lifetime_wrong =
+    {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
+
+borrowck_returned_ref_escaped =
+    returns a reference to a captured variable which escapes the closure body
+
+borrowck_suggest_create_freash_reborrow =
+    consider reborrowing the `Pin` instead of moving it
+
+borrowck_suggest_iterate_over_slice =
+    consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+
+borrowck_ty_no_impl_copy =
+    {$is_partial_move ->
+        [true] partial move
+        *[false] move
+    } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
+
+borrowck_use_due_to_use_closure =
+    use occurs due to use in closure
+
+borrowck_use_due_to_use_generator =
+    use occurs due to use in generator
+
+borrowck_used_impl_require_static =
+    the used `impl` has a `'static` requirement
+
+borrowck_value_capture_here =
+    value captured {$is_within ->
+        [true] here by generator
+        *[false] here
     }
 
 borrowck_value_moved_here =
@@ -224,41 +205,60 @@
         *[false] {""}
     }
 
-borrowck_consider_borrow_type_contents =
-    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+borrowck_var_borrow_by_use_in_closure =
+    borrow occurs due to use in closure
 
-borrowck_moved_a_fn_once_in_call =
-    this value implements `FnOnce`, which causes it to be moved when called
+borrowck_var_borrow_by_use_in_generator =
+    borrow occurs due to use in generator
 
-borrowck_calling_operator_moves_lhs =
-    calling this operator moves the left-hand side
+borrowck_var_borrow_by_use_place_in_closure =
+    {$is_single_var ->
+        *[true] borrow occurs
+        [false] borrows occur
+    } due to use of {$place} in closure
 
-borrowck_func_take_self_moved_place =
-    `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
+borrowck_var_borrow_by_use_place_in_generator =
+    {$is_single_var ->
+        *[true] borrow occurs
+        [false] borrows occur
+    } due to use of {$place} in generator
 
-borrowck_suggest_iterate_over_slice =
-    consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+borrowck_var_cannot_escape_closure =
+    captured variable cannot escape `FnMut` closure body
+    .note = `FnMut` closures only have access to their captured variables while they are executing...
+    .cannot_escape = ...therefore, they cannot allow references to captured variables to escape
 
-borrowck_suggest_create_freash_reborrow =
-    consider reborrowing the `Pin` instead of moving it
+borrowck_var_does_not_need_mut =
+    variable does not need to be mutable
+    .suggestion = remove this `mut`
 
-borrowck_value_capture_here =
-    value captured {$is_within ->
-        [true] here by generator
-        *[false] here
-    }
+borrowck_var_first_borrow_by_use_place_in_closure =
+    first borrow occurs due to use of {$place} in closure
 
-borrowck_move_out_place_here =
-    {$place} is moved here
+borrowck_var_first_borrow_by_use_place_in_generator =
+    first borrow occurs due to use of {$place} in generator
 
-borrowck_closure_invoked_twice =
-    closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
+borrowck_var_here_captured = variable captured here
 
-borrowck_closure_moved_twice =
-    closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
+borrowck_var_here_defined = variable defined here
 
-borrowck_ty_no_impl_copy =
-    {$is_partial_move ->
-        [true] partial move
-        *[false] move
-    } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
+borrowck_var_move_by_use_in_closure =
+    move occurs due to use in closure
+
+borrowck_var_move_by_use_in_generator =
+    move occurs due to use in generator
+
+borrowck_var_move_by_use_place_in_closure =
+    move occurs due to use of {$place} in closure
+
+borrowck_var_move_by_use_place_in_generator =
+    move occurs due to use of {$place} in generator
+
+borrowck_var_mutable_borrow_by_use_place_in_closure =
+    mutable borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_closure =
+    second borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_generator =
+    second borrow occurs due to use of {$place} in generator
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 4824f63..6be20b0 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -30,7 +30,7 @@
     /// Map from local to all the borrows on that local.
     pub local_map: FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>>,
 
-    pub(crate) locals_state_at_exit: LocalsStateAtExit,
+    pub locals_state_at_exit: LocalsStateAtExit,
 }
 
 impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
@@ -153,7 +153,7 @@
         self.activation_map.get(&location).map_or(&[], |activations| &activations[..])
     }
 
-    pub(crate) fn len(&self) -> usize {
+    pub fn len(&self) -> usize {
         self.location_map.len()
     }
 
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 3451b7d..d257145 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -3,22 +3,96 @@
 //! This file provides API for compiler consumers.
 
 use rustc_hir::def_id::LocalDefId;
-use rustc_index::IndexSlice;
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_middle::mir::Body;
+use rustc_index::{IndexSlice, IndexVec};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::mir::{Body, Promoted};
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::TyCtxt;
+use std::rc::Rc;
+
+use crate::borrow_set::BorrowSet;
 
 pub use super::{
+    constraints::OutlivesConstraint,
+    dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows},
     facts::{AllFacts as PoloniusInput, RustcFacts},
     location::{LocationTable, RichLocation},
     nll::PoloniusOutput,
-    BodyWithBorrowckFacts,
+    place_ext::PlaceExt,
+    places_conflict::{places_conflict, PlaceConflictBias},
+    region_infer::RegionInferenceContext,
 };
 
-/// This function computes Polonius facts for the given body. It makes a copy of
-/// the body because it needs to regenerate the region identifiers. This function
-/// should never be invoked during a typical compilation session due to performance
-/// issues with Polonius.
+/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
+///
+/// If executing under `-Z polonius` the choice here has no effect, and everything as if
+/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
+/// will be retrieved.
+#[derive(Debug, Copy, Clone)]
+pub enum ConsumerOptions {
+    /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
+    /// and [`RegionInferenceContext`]. If you would like the body only, use
+    /// [`TyCtxt::mir_promoted`].
+    ///
+    /// These can be used in conjunction with [`calculate_borrows_out_of_scope_at_location`].
+    RegionInferenceContext,
+    /// The recommended option. Retrieves the maximal amount of information
+    /// without significant slowdowns.
+    ///
+    /// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext),
+    /// and additionally retrieve the [`LocationTable`] and [`PoloniusInput`] that
+    /// would be given to Polonius. Critically, this does not run Polonius, which
+    /// one may want to avoid due to performance issues on large bodies.
+    PoloniusInputFacts,
+    /// Implies [`PoloniusInputFacts`](ConsumerOptions::PoloniusInputFacts),
+    /// and additionally runs Polonius to calculate the [`PoloniusOutput`].
+    PoloniusOutputFacts,
+}
+
+impl ConsumerOptions {
+    /// Should the Polonius input facts be computed?
+    pub(crate) fn polonius_input(&self) -> bool {
+        matches!(self, Self::PoloniusInputFacts | Self::PoloniusOutputFacts)
+    }
+    /// Should we run Polonius and collect the output facts?
+    pub(crate) fn polonius_output(&self) -> bool {
+        matches!(self, Self::PoloniusOutputFacts)
+    }
+}
+
+/// A `Body` with information computed by the borrow checker. This struct is
+/// intended to be consumed by compiler consumers.
+///
+/// We need to include the MIR body here because the region identifiers must
+/// match the ones in the Polonius facts.
+pub struct BodyWithBorrowckFacts<'tcx> {
+    /// A mir body that contains region identifiers.
+    pub body: Body<'tcx>,
+    /// The mir bodies of promoteds.
+    pub promoted: IndexVec<Promoted, Body<'tcx>>,
+    /// The set of borrows occurring in `body` with data about them.
+    pub borrow_set: Rc<BorrowSet<'tcx>>,
+    /// Context generated during borrowck, intended to be passed to
+    /// [`calculate_borrows_out_of_scope_at_location`].
+    pub region_inference_context: Rc<RegionInferenceContext<'tcx>>,
+    /// The table that maps Polonius points to locations in the table.
+    /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
+    /// or [`ConsumerOptions::PoloniusOutputFacts`].
+    pub location_table: Option<LocationTable>,
+    /// Polonius input facts.
+    /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
+    /// or [`ConsumerOptions::PoloniusOutputFacts`].
+    pub input_facts: Option<Box<PoloniusInput>>,
+    /// Polonius output facts. Populated when using
+    /// [`ConsumerOptions::PoloniusOutputFacts`].
+    pub output_facts: Option<Rc<PoloniusOutput>>,
+}
+
+/// This function computes borrowck facts for the given body. The [`ConsumerOptions`]
+/// determine which facts are returned. This function makes a copy of the body because
+/// it needs to regenerate the region identifiers. It should never be invoked during a
+/// typical compilation session due to the unnecessary overhead of returning
+/// [`BodyWithBorrowckFacts`].
 ///
 /// Note:
 /// *   This function will panic if the required body was already stolen. This
@@ -28,10 +102,14 @@
 ///     that shows how to do this at `tests/run-make/obtain-borrowck/`.
 ///
 /// *   Polonius is highly unstable, so expect regular changes in its signature or other details.
-pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> {
+pub fn get_body_with_borrowck_facts(
+    tcx: TyCtxt<'_>,
+    def: LocalDefId,
+    options: ConsumerOptions,
+) -> BodyWithBorrowckFacts<'_> {
     let (input_body, promoted) = tcx.mir_promoted(def);
     let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
     let input_body: &Body<'_> = &input_body.borrow();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
-    *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
+    *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()
 }
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 167f245..2daa82a 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -156,10 +156,10 @@
         &mut self,
         borrow_index: BorrowIndex,
         borrow_region: RegionVid,
-        location: Location,
+        first_location: Location,
     ) {
         // We visit one BB at a time. The complication is that we may start in the
-        // middle of the first BB visited (the one containing `location`), in which
+        // middle of the first BB visited (the one containing `first_location`), in which
         // case we may have to later on process the first part of that BB if there
         // is a path back to its start.
 
@@ -168,61 +168,58 @@
         // `visited` once they are added to `stack`, before they are actually
         // processed, because this avoids the need to look them up again on
         // completion.
-        self.visited.insert(location.block);
+        self.visited.insert(first_location.block);
 
-        let mut first_lo = location.statement_index;
-        let first_hi = self.body[location.block].statements.len();
+        let first_block = first_location.block;
+        let mut first_lo = first_location.statement_index;
+        let first_hi = self.body[first_block].statements.len();
 
-        self.visit_stack.push(StackEntry { bb: location.block, lo: first_lo, hi: first_hi });
+        self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi });
 
-        while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
-            // If we process the first part of the first basic block (i.e. we encounter that block
-            // for the second time), we no longer have to visit its successors again.
-            let mut finished_early = bb == location.block && hi != first_hi;
-            for i in lo..=hi {
-                let location = Location { block: bb, statement_index: i };
+        'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
+            if let Some(kill_stmt) =
+                self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi)
+            {
+                let kill_location = Location { block: bb, statement_index: kill_stmt };
                 // If region does not contain a point at the location, then add to list and skip
                 // successor locations.
-                if !self.regioncx.region_contains(borrow_region, location) {
-                    debug!("borrow {:?} gets killed at {:?}", borrow_index, location);
-                    self.borrows_out_of_scope_at_location
-                        .entry(location)
-                        .or_default()
-                        .push(borrow_index);
-                    finished_early = true;
-                    break;
-                }
+                debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
+                self.borrows_out_of_scope_at_location
+                    .entry(kill_location)
+                    .or_default()
+                    .push(borrow_index);
+                continue 'preorder;
             }
 
-            if !finished_early {
-                // Add successor BBs to the work list, if necessary.
-                let bb_data = &self.body[bb];
-                debug_assert!(hi == bb_data.statements.len());
-                for succ_bb in bb_data.terminator().successors() {
-                    if !self.visited.insert(succ_bb) {
-                        if succ_bb == location.block && first_lo > 0 {
-                            // `succ_bb` has been seen before. If it wasn't
-                            // fully processed, add its first part to `stack`
-                            // for processing.
-                            self.visit_stack.push(StackEntry {
-                                bb: succ_bb,
-                                lo: 0,
-                                hi: first_lo - 1,
-                            });
+            // If we process the first part of the first basic block (i.e. we encounter that block
+            // for the second time), we no longer have to visit its successors again.
+            if bb == first_block && hi != first_hi {
+                continue;
+            }
 
-                            // And update this entry with 0, to represent the
-                            // whole BB being processed.
-                            first_lo = 0;
-                        }
-                    } else {
-                        // succ_bb hasn't been seen before. Add it to
-                        // `stack` for processing.
-                        self.visit_stack.push(StackEntry {
-                            bb: succ_bb,
-                            lo: 0,
-                            hi: self.body[succ_bb].statements.len(),
-                        });
+            // Add successor BBs to the work list, if necessary.
+            let bb_data = &self.body[bb];
+            debug_assert!(hi == bb_data.statements.len());
+            for succ_bb in bb_data.terminator().successors() {
+                if !self.visited.insert(succ_bb) {
+                    if succ_bb == first_block && first_lo > 0 {
+                        // `succ_bb` has been seen before. If it wasn't
+                        // fully processed, add its first part to `stack`
+                        // for processing.
+                        self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
+
+                        // And update this entry with 0, to represent the
+                        // whole BB being processed.
+                        first_lo = 0;
                     }
+                } else {
+                    // succ_bb hasn't been seen before. Add it to
+                    // `stack` for processing.
+                    self.visit_stack.push(StackEntry {
+                        bb: succ_bb,
+                        lo: 0,
+                        hi: self.body[succ_bb].statements.len(),
+                    });
                 }
             }
         }
@@ -231,27 +228,32 @@
     }
 }
 
+pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
+    body: &Body<'tcx>,
+    regioncx: &RegionInferenceContext<'tcx>,
+    borrow_set: &BorrowSet<'tcx>,
+) -> FxIndexMap<Location, Vec<BorrowIndex>> {
+    let mut prec = OutOfScopePrecomputer::new(body, regioncx);
+    for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
+        let borrow_region = borrow_data.region;
+        let location = borrow_data.reserve_location;
+
+        prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
+    }
+
+    prec.borrows_out_of_scope_at_location
+}
+
 impl<'a, 'tcx> Borrows<'a, 'tcx> {
-    pub(crate) fn new(
+    pub fn new(
         tcx: TyCtxt<'tcx>,
         body: &'a Body<'tcx>,
         nonlexical_regioncx: &'a RegionInferenceContext<'tcx>,
         borrow_set: &'a BorrowSet<'tcx>,
     ) -> Self {
-        let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx);
-        for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
-            let borrow_region = borrow_data.region;
-            let location = borrow_data.reserve_location;
-
-            prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
-        }
-
-        Borrows {
-            tcx,
-            body,
-            borrow_set,
-            borrows_out_of_scope_at_location: prec.borrows_out_of_scope_at_location,
-        }
+        let borrows_out_of_scope_at_location =
+            calculate_borrows_out_of_scope_at_location(body, nonlexical_regioncx, borrow_set);
+        Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
     }
 
     pub fn location(&self, idx: BorrowIndex) -> &Location {
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 84f75ca..f41795d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -128,7 +128,7 @@
     }
 }
 
-impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
+impl<'tcx, F> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F>> {
     fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
         // We can't rerun custom type ops.
         UniverseInfo::other()
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index d0cb112..1d430a9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -118,7 +118,7 @@
                     let path_span = path_span.unwrap();
                     // path_span is only present in the case of closure capture
                     assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture));
-                    if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) {
+                    if !borrow_span.is_some_and(|sp| sp.overlaps(var_or_use_span)) {
                         let path_label = "used here by closure";
                         let capture_kind_label = message;
                         err.span_label(
@@ -224,12 +224,9 @@
                             if info.tail_result_is_ignored {
                                 // #85581: If the first mutable borrow's scope contains
                                 // the second borrow, this suggestion isn't helpful.
-                                if !multiple_borrow_span
-                                    .map(|(old, new)| {
-                                        old.to(info.span.shrink_to_hi()).contains(new)
-                                    })
-                                    .unwrap_or(false)
-                                {
+                                if !multiple_borrow_span.is_some_and(|(old, new)| {
+                                    old.to(info.span.shrink_to_hi()).contains(new)
+                                }) {
                                     err.span_suggestion_verbose(
                                         info.span.shrink_to_hi(),
                                         "consider adding semicolon after the expression so its \
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 7fc8eb1..20370e4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1156,7 +1156,7 @@
                                 ty::Adt(def, ..) => Some(def.did()),
                                 _ => None,
                             });
-                    let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
+                    let is_option_or_result = parent_self_ty.is_some_and(|def_id| {
                         matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
                     });
                     if is_option_or_result && maybe_reinitialized_locations_is_empty {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 6286033..4bde372 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -289,8 +289,7 @@
                     .body
                     .local_decls
                     .get(local)
-                    .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local]))
-                    .unwrap_or(false) =>
+                    .is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) =>
             {
                 let decl = &self.body.local_decls[local];
                 err.span_label(span, format!("cannot {act}"));
@@ -443,7 +442,7 @@
                     .sess
                     .source_map()
                     .span_to_snippet(span)
-                    .map_or(false, |snippet| snippet.starts_with("&mut ")) =>
+                    .is_ok_and(|snippet| snippet.starts_with("&mut ")) =>
             {
                 err.span_label(span, format!("cannot {act}"));
                 err.span_suggestion(
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index ffba605..b6eb9ae 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -125,8 +125,7 @@
                     |(r, _)| {
                         self.constraints_to_add
                             .get(r)
-                            .map(|r_outlived| r_outlived.as_slice().contains(fr))
-                            .unwrap_or(false)
+                            .is_some_and(|r_outlived| r_outlived.as_slice().contains(fr))
                     },
                 );
 
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 863c92a..036391d 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -46,7 +46,7 @@
     all_facts: &'cx mut AllFacts,
     location_table: &'cx LocationTable,
     body: &'cx Body<'tcx>,
-    dominators: Dominators<BasicBlock>,
+    dominators: &'cx Dominators<BasicBlock>,
     borrow_set: &'cx BorrowSet<'tcx>,
 }
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 315303b..9277a26 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -26,7 +26,7 @@
 use rustc_index::bit_set::ChunkedBitSet;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_infer::infer::{
-    DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
+    InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
 };
 use rustc_middle::mir::{
     traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
@@ -35,7 +35,8 @@
 use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
 use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
 use rustc_session::lint::builtin::UNUSED_MUT;
 use rustc_span::{Span, Symbol};
@@ -43,7 +44,6 @@
 
 use either::Either;
 use smallvec::SmallVec;
-use std::cell::OnceCell;
 use std::cell::RefCell;
 use std::collections::BTreeMap;
 use std::ops::Deref;
@@ -62,7 +62,7 @@
 use self::diagnostics::{AccessKind, RegionName};
 use self::location::LocationTable;
 use self::prefixes::PrefixSet;
-use facts::AllFacts;
+use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
 
 use self::path_utils::*;
 
@@ -144,7 +144,7 @@
         tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
     let input_body: &Body<'_> = &input_body.borrow();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
-    let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
+    let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
     debug!("mir_borrowck done");
 
     tcx.arena.alloc(opt_closure_req)
@@ -152,15 +152,15 @@
 
 /// Perform the actual borrow checking.
 ///
-/// If `return_body_with_facts` is true, then return the body with non-erased
-/// region ids on which the borrow checking was performed together with Polonius
-/// facts.
+/// Use `consumer_options: None` for the default behavior of returning
+/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
+/// to the given [`ConsumerOptions`].
 #[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
 fn do_mir_borrowck<'tcx>(
     infcx: &InferCtxt<'tcx>,
     input_body: &Body<'tcx>,
     input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
-    return_body_with_facts: bool,
+    consumer_options: Option<ConsumerOptions>,
 ) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
     let def = input_body.source.def_id().expect_local();
     debug!(?def);
@@ -241,8 +241,6 @@
     let borrow_set =
         Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
 
-    let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.unstable_opts.polonius;
-
     // Compute non-lexical lifetimes.
     let nll::NllOutput {
         regioncx,
@@ -262,7 +260,7 @@
         &mdpe.move_data,
         &borrow_set,
         &upvars,
-        use_polonius,
+        consumer_options,
     );
 
     // Dump MIR results into a file, if that is enabled. This let us
@@ -331,7 +329,6 @@
                 used_mut: Default::default(),
                 used_mut_upvars: SmallVec::new(),
                 borrow_set: Rc::clone(&borrow_set),
-                dominators: Default::default(),
                 upvars: Vec::new(),
                 local_names: IndexVec::from_elem(None, &promoted_body.local_decls),
                 region_names: RefCell::default(),
@@ -360,7 +357,6 @@
         used_mut: Default::default(),
         used_mut_upvars: SmallVec::new(),
         borrow_set: Rc::clone(&borrow_set),
-        dominators: Default::default(),
         upvars,
         local_names,
         region_names: RefCell::default(),
@@ -444,13 +440,16 @@
         tainted_by_errors,
     };
 
-    let body_with_facts = if return_body_with_facts {
-        let output_facts = mbcx.polonius_output.expect("Polonius output was not computed");
+    let body_with_facts = if consumer_options.is_some() {
+        let output_facts = mbcx.polonius_output;
         Some(Box::new(BodyWithBorrowckFacts {
             body: body_owned,
-            input_facts: *polonius_input.expect("Polonius input facts were not generated"),
+            promoted,
+            borrow_set,
+            region_inference_context: regioncx,
+            location_table: polonius_input.as_ref().map(|_| location_table_owned),
+            input_facts: polonius_input,
             output_facts,
-            location_table: location_table_owned,
         }))
     } else {
         None
@@ -461,22 +460,6 @@
     (result, body_with_facts)
 }
 
-/// A `Body` with information computed by the borrow checker. This struct is
-/// intended to be consumed by compiler consumers.
-///
-/// We need to include the MIR body here because the region identifiers must
-/// match the ones in the Polonius facts.
-pub struct BodyWithBorrowckFacts<'tcx> {
-    /// A mir body that contains region identifiers.
-    pub body: Body<'tcx>,
-    /// Polonius input facts.
-    pub input_facts: AllFacts,
-    /// Polonius output facts.
-    pub output_facts: Rc<self::nll::PoloniusOutput>,
-    /// The table that maps Polonius points to locations in the table.
-    pub location_table: LocationTable,
-}
-
 pub struct BorrowckInferCtxt<'cx, 'tcx> {
     pub(crate) infcx: &'cx InferCtxt<'tcx>,
     pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
@@ -591,9 +574,6 @@
     /// The set of borrows extracted from the MIR
     borrow_set: Rc<BorrowSet<'tcx>>,
 
-    /// Dominators for MIR
-    dominators: OnceCell<Dominators<BasicBlock>>,
-
     /// Information about upvars not necessarily preserved in types or MIR
     upvars: Vec<Upvar<'tcx>>,
 
@@ -2269,7 +2249,8 @@
     }
 
     fn dominators(&self) -> &Dominators<BasicBlock> {
-        self.dominators.get_or_init(|| self.body.basic_blocks.dominators())
+        // `BasicBlocks` computes dominators on-demand and caches them.
+        self.body.basic_blocks.dominators()
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index a4394dd..889acb3 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -27,6 +27,7 @@
 use crate::{
     borrow_set::BorrowSet,
     constraint_generation,
+    consumers::ConsumerOptions,
     diagnostics::RegionErrors,
     facts::{AllFacts, AllFactsExt, RustcFacts},
     invalidation,
@@ -165,10 +166,14 @@
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     upvars: &[Upvar<'tcx>],
-    use_polonius: bool,
+    consumer_options: Option<ConsumerOptions>,
 ) -> NllOutput<'tcx> {
+    let polonius_input = consumer_options.map(|c| c.polonius_input()).unwrap_or_default()
+        || infcx.tcx.sess.opts.unstable_opts.polonius;
+    let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default()
+        || infcx.tcx.sess.opts.unstable_opts.polonius;
     let mut all_facts =
-        (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
+        (polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
 
     let universal_regions = Rc::new(universal_regions);
 
@@ -189,7 +194,7 @@
             move_data,
             elements,
             upvars,
-            use_polonius,
+            polonius_input,
         );
 
     if let Some(all_facts) = &mut all_facts {
@@ -284,7 +289,7 @@
             all_facts.write_to_dir(dir_path, location_table).unwrap();
         }
 
-        if use_polonius {
+        if polonius_output {
             let algorithm =
                 env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
             let algorithm = Algorithm::from_str(&algorithm).unwrap();
@@ -430,7 +435,7 @@
 fn for_each_region_constraint<'tcx>(
     tcx: TyCtxt<'tcx>,
     closure_region_requirements: &ClosureRegionRequirements<'tcx>,
-    with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
+    with_msg: &mut dyn FnMut(String) -> io::Result<()>,
 ) -> io::Result<()> {
     for req in &closure_region_requirements.outlives_requirements {
         let subject = match req.subject {
@@ -439,7 +444,7 @@
                 format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
             }
         };
-        with_msg(&format!("where {}: {:?}", subject, req.outlived_free_region,))?;
+        with_msg(format!("where {}: {:?}", subject, req.outlived_free_region,))?;
     }
     Ok(())
 }
diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs
index 85d207b..d521d0d 100644
--- a/compiler/rustc_borrowck/src/place_ext.rs
+++ b/compiler/rustc_borrowck/src/place_ext.rs
@@ -7,7 +7,7 @@
 use rustc_middle::ty::{self, TyCtxt};
 
 /// Extension methods for the `Place` type.
-pub(crate) trait PlaceExt<'tcx> {
+pub trait PlaceExt<'tcx> {
     /// Returns `true` if we can safely ignore borrows of this place.
     /// This is true whenever there is no action that the user can do
     /// to the place `self` that would invalidate the borrow. This is true
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 918fb2d..25c485b 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -16,7 +16,7 @@
 /// being run in the calling context, the conservative choice is to assume the compared indices
 /// are disjoint (and therefore, do not overlap).
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub(crate) enum PlaceConflictBias {
+pub enum PlaceConflictBias {
     Overlap,
     NoOverlap,
 }
@@ -24,7 +24,7 @@
 /// Helper function for checking if places conflict with a mutable borrow and deep access depth.
 /// This is used to check for places conflicting outside of the borrow checking code (such as in
 /// dataflow).
-pub(crate) fn places_conflict<'tcx>(
+pub fn places_conflict<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     borrow_place: Place<'tcx>,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 8fbe814..50b246b 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -12,7 +12,7 @@
 use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
 use rustc_middle::mir::{
-    Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
+    BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
     ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
     TerminatorKind,
 };
@@ -585,6 +585,11 @@
         self.universal_regions.to_region_vid(r)
     }
 
+    /// Returns an iterator over all the outlives constraints.
+    pub fn outlives_constraints(&self) -> impl Iterator<Item = OutlivesConstraint<'tcx>> + '_ {
+        self.constraints.outlives().iter().copied()
+    }
+
     /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
     pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) {
         self.universal_regions.annotate(tcx, err)
@@ -598,6 +603,20 @@
         self.scc_values.contains(scc, p)
     }
 
+    /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
+    ///
+    /// Panics if called before `solve()` executes.
+    pub(crate) fn first_non_contained_inclusive(
+        &self,
+        r: RegionVid,
+        block: BasicBlock,
+        start: usize,
+        end: usize,
+    ) -> Option<usize> {
+        let scc = self.constraint_sccs.scc(r);
+        self.scc_values.first_non_contained_inclusive(scc, block, start, end)
+    }
+
     /// Returns access to the value of `r` for debugging purposes.
     pub(crate) fn region_value_str(&self, r: RegionVid) -> String {
         let scc = self.constraint_sccs.scc(r);
@@ -698,7 +717,7 @@
     #[instrument(skip(self, _body), level = "debug")]
     fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
         debug!("constraints={:#?}", {
-            let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
+            let mut constraints: Vec<_> = self.outlives_constraints().collect();
             constraints.sort_by_key(|c| (c.sup, c.sub));
             constraints
                 .into_iter()
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 309f23d9..7fc89e8 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -2,9 +2,10 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::OpaqueTyOrigin;
+use rustc_infer::infer::InferCtxt;
 use rustc_infer::infer::TyCtxtInferExt as _;
-use rustc_infer::infer::{DefiningAnchor, InferCtxt};
 use rustc_infer::traits::{Obligation, ObligationCause};
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
@@ -152,8 +153,10 @@
                     let guar = ty.error_reported().err().unwrap_or_else(|| {
                         prev.report_mismatch(
                             &OpaqueHiddenType { ty, span: concrete_type.span },
+                            opaque_type_key.def_id,
                             infcx.tcx,
                         )
+                        .emit()
                     });
                     prev.ty = infcx.tcx.ty_error(guar);
                 }
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 193e206..9290e74 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -159,7 +159,7 @@
     /// Returns `true` if the region `r` contains the given element.
     pub(crate) fn contains(&self, row: N, location: Location) -> bool {
         let index = self.elements.point_from_location(location);
-        self.points.row(row).map_or(false, |r| r.contains(index))
+        self.points.row(row).is_some_and(|r| r.contains(index))
     }
 
     /// Returns an iterator of all the elements contained by the region `r`
@@ -283,6 +283,22 @@
         elem.contained_in_row(self, r)
     }
 
+    /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
+    pub(crate) fn first_non_contained_inclusive(
+        &self,
+        r: N,
+        block: BasicBlock,
+        start: usize,
+        end: usize,
+    ) -> Option<usize> {
+        let row = self.points.row(r)?;
+        let block = self.elements.entry_point(block);
+        let start = block.plus(start);
+        let end = block.plus(end);
+        let first_unset = row.first_unset_in(start..=end)?;
+        Some(first_unset.index() - block.index())
+    }
+
     /// `self[to] |= values[from]`, essentially: that is, take all the
     /// elements for the region `from` from `values` and add them to
     /// the region `to` in `self`.
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index b27d5d2..f527eee 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -1,13 +1,13 @@
 use std::fmt;
 
-use rustc_infer::infer::{canonical::Canonical, InferOk};
+use rustc_errors::ErrorGuaranteed;
+use rustc_infer::infer::canonical::Canonical;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
-use rustc_trait_selection::traits::query::{Fallible, NoSolution};
-use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
+use rustc_trait_selection::traits::ObligationCause;
 
 use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
 
@@ -30,14 +30,15 @@
         locations: Locations,
         category: ConstraintCategory<'tcx>,
         op: Op,
-    ) -> Fallible<R>
+    ) -> Result<R, ErrorGuaranteed>
     where
         Op: type_op::TypeOp<'tcx, Output = R>,
         Op::ErrorInfo: ToUniverseInfo<'tcx>,
     {
         let old_universe = self.infcx.universe();
 
-        let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
+        let TypeOpOutput { output, constraints, error_info } =
+            op.fully_perform(self.infcx, locations.span(self.body))?;
 
         debug!(?output, ?constraints);
 
@@ -135,14 +136,11 @@
     ) {
         let param_env = self.param_env;
         let predicate = predicate.to_predicate(self.tcx());
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             locations,
             category,
             param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
-        )
-        .unwrap_or_else(|NoSolution| {
-            span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
-        })
+        );
     }
 
     pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
@@ -163,15 +161,12 @@
         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
     {
         let param_env = self.param_env;
-        self.fully_perform_op(
+        let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             location.to_locations(),
             category,
             param_env.and(type_op::normalize::Normalize::new(value)),
-        )
-        .unwrap_or_else(|NoSolution| {
-            span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
-            value
-        })
+        );
+        result.unwrap_or(value)
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -181,18 +176,11 @@
         user_ty: ty::UserType<'tcx>,
         span: Span,
     ) {
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
             self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
-        )
-        .unwrap_or_else(|err| {
-            span_mirbug!(
-                self,
-                span,
-                "ascribe_user_type `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
-            );
-        });
+        );
     }
 
     /// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`.
@@ -219,27 +207,17 @@
 
         let cause = ObligationCause::dummy_with_span(span);
         let param_env = self.param_env;
-        let op = |infcx: &'_ _| {
-            let ocx = ObligationCtxt::new_in_snapshot(infcx);
-            let user_ty = ocx.normalize(&cause, param_env, user_ty);
-            ocx.eq(&cause, param_env, user_ty, mir_ty)?;
-            if !ocx.select_all_or_error().is_empty() {
-                return Err(NoSolution);
-            }
-            Ok(InferOk { value: (), obligations: vec![] })
-        };
-
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
-            type_op::custom::CustomTypeOp::new(op, || "ascribe_user_type_skip_wf".to_string()),
-        )
-        .unwrap_or_else(|err| {
-            span_mirbug!(
-                self,
-                span,
-                "ascribe_user_type_skip_wf `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
-            );
-        });
+            type_op::custom::CustomTypeOp::new(
+                |ocx| {
+                    let user_ty = ocx.normalize(&cause, param_env, user_ty);
+                    ocx.eq(&cause, param_env, user_ty, mir_ty)?;
+                    Ok(())
+                },
+                "ascribe_user_type_skip_wf",
+            ),
+        );
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index bd01c0b..c8ec125 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,7 +8,7 @@
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use std::rc::Rc;
 use type_op::TypeOpOutput;
@@ -243,18 +243,11 @@
             let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
                 .param_env
                 .and(type_op::normalize::Normalize::new(ty))
-                .fully_perform(self.infcx)
-                .unwrap_or_else(|_| {
-                    let guar = self
-                        .infcx
-                        .tcx
-                        .sess
-                        .delay_span_bug(span, format!("failed to normalize {:?}", ty));
-                    TypeOpOutput {
-                        output: self.infcx.tcx.ty_error(guar),
-                        constraints: None,
-                        error_info: None,
-                    }
+                .fully_perform(self.infcx, span)
+                .unwrap_or_else(|guar| TypeOpOutput {
+                    output: self.infcx.tcx.ty_error(guar),
+                    constraints: None,
+                    error_info: None,
                 });
             if let Some(c) = constraints_normalize {
                 constraints.push(c)
@@ -324,7 +317,7 @@
         let TypeOpOutput { output: bounds, constraints, .. } = self
             .param_env
             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
-            .fully_perform(self.infcx)
+            .fully_perform(self.infcx, DUMMY_SP)
             .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
         debug!(?bounds, ?constraints);
         self.add_outlives_bounds(bounds);
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 9731b10..fd94ac8 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -4,6 +4,7 @@
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
 use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
+use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
 use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -568,10 +569,15 @@
     ) -> DropData<'tcx> {
         debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
 
-        let param_env = typeck.param_env;
-        let TypeOpOutput { output, constraints, .. } =
-            param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap();
-
-        DropData { dropck_result: output, region_constraint_data: constraints }
+        match typeck
+            .param_env
+            .and(DropckOutlives::new(dropped_ty))
+            .fully_perform(typeck.infcx, DUMMY_SP)
+        {
+            Ok(TypeOpOutput { output, constraints, .. }) => {
+                DropData { dropck_result: output, region_constraint_data: constraints }
+            }
+            Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
+        }
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 33b24b6..51a84ce 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -10,6 +10,7 @@
 use hir::OpaqueTyOrigin;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
@@ -20,12 +21,13 @@
 use rustc_infer::infer::region_constraints::RegionConstraintData;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{
-    InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
+    InferCtxt, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
 };
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::*;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
@@ -41,13 +43,14 @@
 use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
-use rustc_trait_selection::traits::query::Fallible;
+
 use rustc_trait_selection::traits::PredicateObligation;
 
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
 use rustc_mir_dataflow::ResultsCursor;
 
+use crate::renumber::RegionCtxt;
 use crate::session_diagnostics::MoveUnsized;
 use crate::{
     borrow_set::BorrowSet,
@@ -71,7 +74,7 @@
         $crate::type_check::mirbug(
             $context.tcx(),
             $context.last_span,
-            &format!(
+            format!(
                 "broken MIR in {:?} ({:?}): {}",
                 $context.body().source.def_id(),
                 $elem,
@@ -183,17 +186,19 @@
         &mut borrowck_context,
     );
 
-    let errors_reported = {
-        let mut verifier = TypeVerifier::new(&mut checker, promoted);
-        verifier.visit_body(&body);
-        verifier.errors_reported
-    };
-
-    if !errors_reported {
-        // if verifier failed, don't do further checks to avoid ICEs
-        checker.typeck_mir(body);
+    // FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
+    // predefined opaques in the typeck root.
+    // FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
+    // the HIR typeck map defining usages back to their definition params,
+    // they won't actually match up with the usages in this body...
+    if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
+        checker.register_predefined_opaques_in_new_solver();
     }
 
+    let mut verifier = TypeVerifier::new(&mut checker, promoted);
+    verifier.visit_body(&body);
+
+    checker.typeck_mir(body);
     checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
     checker.check_signature_annotation(&body);
 
@@ -213,24 +218,22 @@
     let opaque_type_values = opaque_type_values
         .into_iter()
         .map(|(opaque_type_key, decl)| {
-            checker
-                .fully_perform_op(
-                    Locations::All(body.span),
-                    ConstraintCategory::OpaqueType,
-                    CustomTypeOp::new(
-                        |infcx| {
-                            infcx.register_member_constraints(
-                                param_env,
-                                opaque_type_key,
-                                decl.hidden_type.ty,
-                                decl.hidden_type.span,
-                            );
-                            Ok(InferOk { value: (), obligations: vec![] })
-                        },
-                        || "opaque_type_map".to_string(),
-                    ),
-                )
-                .unwrap();
+            let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
+                Locations::All(body.span),
+                ConstraintCategory::OpaqueType,
+                CustomTypeOp::new(
+                    |ocx| {
+                        ocx.infcx.register_member_constraints(
+                            param_env,
+                            opaque_type_key,
+                            decl.hidden_type.ty,
+                            decl.hidden_type.span,
+                        );
+                        Ok(())
+                    },
+                    "opaque_type_map",
+                ),
+            );
             let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
             trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
             if hidden_type.has_non_region_infer() {
@@ -274,7 +277,7 @@
 }
 
 #[track_caller]
-fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: &str) {
+fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
     // We sometimes see MIR failures (notably predicate failures) due to
     // the fact that we check rvalue sized predicates here. So use `delay_span_bug`
     // to avoid reporting bugs in those cases.
@@ -294,7 +297,6 @@
     cx: &'a mut TypeChecker<'b, 'tcx>,
     promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
     last_span: Span,
-    errors_reported: bool,
 }
 
 impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
@@ -383,13 +385,11 @@
                         };
                     };
 
-                    if !self.errors_reported {
-                        let promoted_body = &self.promoted[promoted];
-                        self.sanitize_promoted(promoted_body, location);
+                    let promoted_body = &self.promoted[promoted];
+                    self.sanitize_promoted(promoted_body, location);
 
-                        let promoted_ty = promoted_body.return_ty();
-                        check_err(self, promoted_body, ty, promoted_ty);
-                    }
+                    let promoted_ty = promoted_body.return_ty();
+                    check_err(self, promoted_body, ty, promoted_ty);
                 } else {
                     self.cx.ascribe_user_type(
                         constant.literal.ty(),
@@ -483,9 +483,6 @@
         for local_decl in &body.local_decls {
             self.sanitize_type(local_decl, local_decl.ty);
         }
-        if self.errors_reported {
-            return;
-        }
         self.super_body(body);
     }
 }
@@ -495,7 +492,7 @@
         cx: &'a mut TypeChecker<'b, 'tcx>,
         promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
     ) -> Self {
-        TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
+        TypeVerifier { promoted, last_span: cx.body.span, cx }
     }
 
     fn body(&self) -> &Body<'tcx> {
@@ -529,7 +526,6 @@
         for elem in place.projection.iter() {
             if place_ty.variant_index.is_none() {
                 if let Err(guar) = place_ty.ty.error_reported() {
-                    assert!(self.errors_reported);
                     return PlaceTy::from_ty(self.tcx().ty_error(guar));
                 }
             }
@@ -593,10 +589,7 @@
 
         self.visit_body(&promoted_body);
 
-        if !self.errors_reported {
-            // if verifier failed, don't do further checks to avoid ICEs
-            self.cx.typeck_mir(promoted_body);
-        }
+        self.cx.typeck_mir(promoted_body);
 
         self.cx.body = parent_body;
         // Merge the outlives constraints back in, at the given location.
@@ -762,7 +755,6 @@
     }
 
     fn error(&mut self) -> Ty<'tcx> {
-        self.errors_reported = true;
         self.tcx().ty_error_misc()
     }
 
@@ -1041,6 +1033,57 @@
         checker
     }
 
+    pub(super) fn register_predefined_opaques_in_new_solver(&mut self) {
+        // OK to use the identity substitutions for each opaque type key, since
+        // we remap opaques from HIR typeck back to their definition params.
+        let opaques: Vec<_> = self
+            .infcx
+            .tcx
+            .typeck(self.body.source.def_id().expect_local())
+            .concrete_opaque_types
+            .iter()
+            .map(|(&def_id, &hidden_ty)| {
+                let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
+                (ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
+            })
+            .collect();
+
+        let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
+            self.infcx.next_nll_region_var(
+                NllRegionVariableOrigin::Existential { from_forall: false },
+                || RegionCtxt::Unknown,
+            )
+        });
+
+        let param_env = self.param_env;
+        let result = self.fully_perform_op(
+            Locations::All(self.body.span),
+            ConstraintCategory::OpaqueType,
+            CustomTypeOp::new(
+                |ocx| {
+                    for (key, hidden_ty) in renumbered_opaques {
+                        ocx.register_infer_ok_obligations(
+                            ocx.infcx.register_hidden_type_in_new_solver(
+                                key,
+                                param_env,
+                                hidden_ty.ty,
+                            )?,
+                        );
+                    }
+                    Ok(())
+                },
+                "register pre-defined opaques",
+            ),
+        );
+
+        if result.is_err() {
+            self.infcx.tcx.sess.delay_span_bug(
+                self.body.span,
+                "failed re-defining predefined opaques in mir typeck",
+            );
+        }
+    }
+
     fn body(&self) -> &Body<'tcx> {
         self.body
     }
@@ -1091,7 +1134,7 @@
         sup: Ty<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         // Use this order of parameters because the sup type is usually the
         // "expected" type in diagnostics.
         self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
@@ -1104,7 +1147,7 @@
         found: Ty<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
     }
 
@@ -1116,7 +1159,7 @@
         user_ty: &UserTypeProjection,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
         trace!(?annotated_type);
         let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
@@ -2712,10 +2755,20 @@
     /// constraints in our `InferCtxt`
     type ErrorInfo = InstantiateOpaqueType<'tcx>;
 
-    fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
-        let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
-            Ok(InferOk { value: (), obligations: self.obligations.clone() })
-        })?;
+    fn fully_perform(
+        mut self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
+        let (mut output, region_constraints) = scrape_region_constraints(
+            infcx,
+            |ocx| {
+                ocx.register_obligations(self.obligations.clone());
+                Ok(())
+            },
+            "InstantiateOpaqueType",
+            span,
+        )?;
         self.region_constraints = Some(region_constraints);
         output.error_info = Some(self);
         Ok(output)
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 7158c62..8c4bfb2 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,12 +1,13 @@
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_infer::traits::PredicateObligations;
 use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
-use rustc_trait_selection::traits::query::Fallible;
 
 use crate::constraints::OutlivesConstraint;
 use crate::diagnostics::UniverseInfo;
@@ -30,7 +31,7 @@
         b: Ty<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         TypeRelating::new(
             self.infcx,
             NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)),
@@ -47,7 +48,7 @@
         b: ty::SubstsRef<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
-    ) -> Fallible<()> {
+    ) -> Result<(), NoSolution> {
         TypeRelating::new(
             self.infcx,
             NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
@@ -185,17 +186,15 @@
     }
 
     fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
-        self.type_checker
-            .fully_perform_op(
-                self.locations,
-                self.category,
-                InstantiateOpaqueType {
-                    obligations,
-                    // These fields are filled in during execution of the operation
-                    base_universe: None,
-                    region_constraints: None,
-                },
-            )
-            .unwrap();
+        let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op(
+            self.locations,
+            self.category,
+            InstantiateOpaqueType {
+                obligations,
+                // These fields are filled in during execution of the operation
+                base_universe: None,
+                region_constraints: None,
+            },
+        );
     }
 }
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 3b458b1..f00cd39 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -1,62 +1,101 @@
-builtin_macros_requires_cfg_pattern =
-    macro requires a cfg-pattern as an argument
-    .label = cfg-pattern required
-
-builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
-
 builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
 
+builtin_macros_asm_clobber_abi = clobber_abi
+builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
+builtin_macros_asm_clobber_outputs = generic outputs
+
+builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
+    .label = previously here
+    .arg = duplicate argument
+
+builtin_macros_asm_expected_comma = expected token: `,`
+    .label = expected `,`
+
+builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
+    [true] options
+    *[false] clobber_abi, options
+    }, or additional template string
+
+builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
+
+builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
+
+builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
+
+builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
+
+builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
+    .label = this option was already provided
+    .suggestion = remove this option
+
+builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments
+    .pos = positional argument
+    .named = named argument
+    .explicit = explicit register argument
+
+builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
+
+builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
+
+builtin_macros_asm_requires_template = requires at least a template string argument
+
+builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
+
+builtin_macros_asm_underscore_input = _ cannot be used for input operands
+
+builtin_macros_assert_missing_comma = unexpected string literal
+    .suggestion = try adding a comma
+
 builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
     .label = boolean expression required
 
 builtin_macros_assert_requires_expression = macro requires an expression as an argument
     .suggestion = try removing semicolon
 
-builtin_macros_assert_missing_comma = unexpected string literal
-    .suggestion = try adding a comma
+builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
+    .label = not applicable here
+    .label2 = not a `struct`, `enum` or `union`
 
-builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
-builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
-builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
+builtin_macros_cannot_derive_union = this trait cannot be derived for unions
+
 builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments
 
 builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not
 
-builtin_macros_concat_bytestr = cannot concatenate a byte string literal
-
-builtin_macros_concat_missing_literal = expected a literal
-    .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
-
-builtin_macros_concat_bytes_missing_literal = expected a byte literal
-    .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
-
-builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
-    .byte_char = try using a byte character
-    .byte_str = try using a byte string
-    .number_array = try wrapping the number in an array
-
-builtin_macros_concat_bytes_oob = numeric literal is out of bounds
-
-builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
-
+builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
+builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
+builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
 builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
     .note = byte strings are treated as arrays of bytes
     .help = try flattening the array
 
 builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number
 
-builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
-builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
+builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
+    .byte_char = try using a byte character
+    .byte_str = try using a byte string
+    .number_array = try wrapping the number in an array
+
+builtin_macros_concat_bytes_missing_literal = expected a byte literal
+    .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+
+builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
+
+builtin_macros_concat_bytes_oob = numeric literal is out of bounds
+
+builtin_macros_concat_bytestr = cannot concatenate a byte string literal
+
 builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
 
-builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
-    .label = not applicable here
-    .label2 = not a `struct`, `enum` or `union`
+builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
+builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
+builtin_macros_concat_missing_literal = expected a literal
+    .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
 
-builtin_macros_unexpected_lit = expected path to a trait, found literal
-    .label = not a trait
-    .str_lit = try using `#[derive({$sym})]`
-    .other = for example, write `#[derive(Debug)]` for `Debug`
+builtin_macros_default_arg = `#[default]` attribute does not accept a value
+    .suggestion = try using `#[default]`
+
+builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
 
 builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments
     .suggestion = remove the arguments
@@ -64,66 +103,38 @@
 builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
     .suggestion = remove the value
 
-builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
-
-builtin_macros_cannot_derive_union = this trait cannot be derived for unions
-
-builtin_macros_no_default_variant = no default declared
-    .help = make a unit variant default by placing `#[default]` above it
-    .suggestion = make `{$ident}` default
-
-builtin_macros_multiple_defaults = multiple declared defaults
-    .label = first default
-    .additional = additional default
-    .note = only one variant can be default
-    .suggestion = make `{$ident}` default
-
-builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
-    .help = consider a manual implementation of `Default`
-
-builtin_macros_non_exhaustive_default = default variant must be exhaustive
-    .label = declared `#[non_exhaustive]` here
-    .help = consider a manual implementation of `Default`
-
-builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
-    .note = only one `#[default]` attribute is needed
-    .label = `#[default]` used here
-    .label_again = `#[default]` used again here
-    .help = try removing {$only_one ->
-    [true] this
-    *[false] these
-    }
-
-builtin_macros_default_arg = `#[default]` attribute does not accept a value
-    .suggestion = try using `#[default]`
-
-builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
-
 builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
     .cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
     .other = use `std::env::var("{$var}")` to read the variable at run time
 
-builtin_macros_format_requires_string = requires at least a format string argument
+builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
+
+builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
 
 builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
     .label1 = previously here
     .label2 = duplicate argument
 
+builtin_macros_format_no_arg_named = there is no argument named `{$name}`
+    .note = did you intend to capture a variable `{$name}` from the surrounding scope?
+    .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+
+builtin_macros_format_pos_mismatch = {$n} positional {$n ->
+    [one] argument
+    *[more] arguments
+    } in format string, but {$desc}
+
 builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments
     .label = positional arguments must be before named arguments
     .named_args = named argument
 
+builtin_macros_format_requires_string = requires at least a format string argument
+
 builtin_macros_format_string_invalid = invalid format string: {$desc}
     .label = {$label1} in format string
     .note = {$note}
     .second_label = {$label}
 
-builtin_macros_sugg = consider using a positional formatting argument instead
-
-builtin_macros_format_no_arg_named = there is no argument named `{$name}`
-    .note = did you intend to capture a variable `{$name}` from the surrounding scope?
-    .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
-
 builtin_macros_format_unknown_trait = unknown format trait `{$ty}`
     .note = the only appropriate formatting traits are:
                                             - ``, which uses the `Display` trait
@@ -145,60 +156,49 @@
 builtin_macros_format_unused_args = multiple unused formatting arguments
     .label = multiple missing formatting specifiers
 
-builtin_macros_format_pos_mismatch = {$n} positional {$n ->
-    [one] argument
-    *[more] arguments
-    } in format string, but {$desc}
+builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
 
-builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
+builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
+    .note = only one `#[default]` attribute is needed
+    .label = `#[default]` used here
+    .label_again = `#[default]` used again here
+    .help = try removing {$only_one ->
+    [true] this
+    *[false] these
+    }
+
+builtin_macros_multiple_defaults = multiple declared defaults
+    .label = first default
+    .additional = additional default
+    .note = only one variant can be default
+    .suggestion = make `{$ident}` default
+
+builtin_macros_no_default_variant = no default declared
+    .help = make a unit variant default by placing `#[default]` above it
+    .suggestion = make `{$ident}` default
+
+builtin_macros_non_exhaustive_default = default variant must be exhaustive
+    .label = declared `#[non_exhaustive]` here
+    .help = consider a manual implementation of `Default`
+
+builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
+    .help = consider a manual implementation of `Default`
+
+builtin_macros_requires_cfg_pattern =
+    macro requires a cfg-pattern as an argument
+    .label = cfg-pattern required
+
+builtin_macros_sugg = consider using a positional formatting argument instead
 
 builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
     .label = `{$kind}` because of this
 
-builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
-
-builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
-
-builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
-
-builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
-
-builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
-
-builtin_macros_asm_requires_template = requires at least a template string argument
-
-builtin_macros_asm_expected_comma = expected token: `,`
-    .label = expected `,`
-
-builtin_macros_asm_underscore_input = _ cannot be used for input operands
-
-builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
-
-builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
-    [true] options
-    *[false] clobber_abi, options
-    }, or additional template string
-
-builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
-    .label = previously here
-    .arg = duplicate argument
-
-builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments
-    .pos = positional argument
-    .named = named argument
-    .explicit = explicit register argument
-
-builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
-
-builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
-
-builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
-builtin_macros_asm_clobber_abi = clobber_abi
-builtin_macros_asm_clobber_outputs = generic outputs
-
-builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
-    .label = this option was already provided
-    .suggestion = remove this option
+builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
 
 builtin_macros_test_runner_invalid = `test_runner` argument must be a path
 builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument
+
+builtin_macros_unexpected_lit = expected path to a trait, found literal
+    .label = not a trait
+    .str_lit = try using `#[derive({$sym})]`
+    .other = for example, write `#[derive(Debug)]` for `Debug`
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index bb059a1..5217e31 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -550,7 +550,7 @@
         if !parser.errors.is_empty() {
             let err = parser.errors.remove(0);
             let err_sp = template_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
-            let msg = &format!("invalid asm template string: {}", err.description);
+            let msg = format!("invalid asm template string: {}", err.description);
             let mut e = ecx.struct_span_err(err_sp, msg);
             e.span_label(err_sp, err.label + " in asm template string");
             if let Some(note) = err.note {
@@ -585,7 +585,7 @@
                                 || args.reg_args.contains(idx)
                             {
                                 let msg = format!("invalid reference to argument at index {}", idx);
-                                let mut err = ecx.struct_span_err(span, &msg);
+                                let mut err = ecx.struct_span_err(span, msg);
                                 err.span_label(span, "from here");
 
                                 let positional_args = args.operands.len()
@@ -638,7 +638,7 @@
                                     ecx.struct_span_err(
                                         template_span
                                             .from_inner(InnerSpan::new(span.start, span.end)),
-                                        &msg,
+                                        msg,
                                     )
                                     .emit();
                                     None
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 750f1fe..49401e9 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -119,7 +119,7 @@
         self.has_cfg_or_cfg_attr = self.has_cfg_or_cfg_attr
             || attr
                 .ident()
-                .map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr);
+                .is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr);
     }
 }
 
@@ -166,7 +166,9 @@
                     ))
                 },
                 Annotatable::Stmt(_) => |parser| {
-                    Ok(Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes)?.unwrap())))
+                    Ok(Annotatable::Stmt(P(parser
+                        .parse_stmt_without_recovery(false, ForceCollect::Yes)?
+                        .unwrap())))
                 },
                 Annotatable::Expr(_) => {
                     |parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?))
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 0481a11..2c8e6f9 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -27,3 +27,26 @@
 
     trait_def.expand(cx, mitem, item, push);
 }
+
+pub fn expand_deriving_const_param_ty(
+    cx: &mut ExtCtxt<'_>,
+    span: Span,
+    mitem: &MetaItem,
+    item: &Annotatable,
+    push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
+) {
+    let trait_def = TraitDef {
+        span,
+        path: path_std!(marker::ConstParamTy),
+        skip_path_as_bound: false,
+        needs_copy_as_bound_if_packed: false,
+        additional_bounds: Vec::new(),
+        supports_unions: false,
+        methods: Vec::new(),
+        associated_types: Vec::new(),
+        is_const,
+    };
+
+    trait_def.expand(cx, mitem, item, push);
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index dfee2d3..9883563 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -145,7 +145,7 @@
             }
             _ => cx.span_bug(
                 trait_span,
-                &format!("unexpected substructure in simple `derive({})`", name),
+                format!("unexpected substructure in simple `derive({})`", name),
             ),
         }
     }
@@ -179,10 +179,10 @@
             vdata = &variant.data;
         }
         EnumTag(..) | AllFieldlessEnum(..) => {
-            cx.span_bug(trait_span, &format!("enum tags in `derive({})`", name,))
+            cx.span_bug(trait_span, format!("enum tags in `derive({})`", name,))
         }
         StaticEnum(..) | StaticStruct(..) => {
-            cx.span_bug(trait_span, &format!("associated function in `derive({})`", name))
+            cx.span_bug(trait_span, format!("associated function in `derive({})`", name))
         }
     }
 
@@ -194,7 +194,7 @@
                     let Some(ident) = field.name else {
                         cx.span_bug(
                             trait_span,
-                            &format!("unnamed field in normal struct in `derive({})`", name,),
+                            format!("unnamed field in normal struct in `derive({})`", name,),
                         );
                     };
                     let call = subcall(cx, field);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index caced3d..4ba0933 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1591,7 +1591,7 @@
                                 BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
                                 sp,
                                 ast::CRATE_NODE_ID,
-                                &format!(
+                                format!(
                                     "{} slice in a packed struct that derives a built-in trait",
                                     ty
                                 ),
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 58c9727..8f64e33 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -63,7 +63,8 @@
         Some(exprs) => exprs.into_iter(),
     };
 
-    let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else {
+    let var_expr = exprs.next().unwrap();
+    let Some((var, _)) = expr_to_string(cx, var_expr.clone(), "expected string literal") else {
         return DummyResult::any(sp);
     };
 
@@ -71,7 +72,7 @@
         None => None,
         Some(second) => match expr_to_string(cx, second, "expected string literal") {
             None => return DummyResult::any(sp),
-            Some((s, _style)) => Some(s),
+            Some((s, _)) => Some(s),
         },
     };
 
@@ -80,10 +81,15 @@
     cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
+            // Use the string literal in the code in the diagnostic to avoid confusing diagnostics,
+            // e.g. when the literal contains escape sequences.
+            let ast::ExprKind::Lit(ast::token::Lit { kind: ast::token::LitKind::Str, symbol: original_var, ..}) = &var_expr.kind else {
+                unreachable!("`expr_to_string` ensures this is a string lit")
+            };
             cx.emit_err(errors::EnvNotDefined {
                 span: sp,
                 msg: custom_msg,
-                var,
+                var: *original_var,
                 help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())),
             });
             return DummyResult::any(sp);
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index adc12ec..c59a733 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -814,7 +814,7 @@
         };
         e = ecx.struct_span_err(
             span,
-            &format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
+            format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
         );
         e.note("positional arguments are zero-based");
     }
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 866cc5a..f0d378d 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -1,7 +1,7 @@
 use crate::util::check_builtin_macro_attribute;
 
 use rustc_ast::expand::allocator::{
-    AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
+    global_fn_name, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
 };
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
@@ -40,8 +40,7 @@
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
-    let f =
-        AllocFnFactory { span, ty_span, kind: AllocatorKind::Global, global: item.ident, cx: ecx };
+    let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx };
 
     // Generate item statements for the allocator methods.
     let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
@@ -63,7 +62,6 @@
 struct AllocFnFactory<'a, 'b> {
     span: Span,
     ty_span: Span,
-    kind: AllocatorKind,
     global: Ident,
     cx: &'b ExtCtxt<'a>,
 }
@@ -92,7 +90,7 @@
         }));
         let item = self.cx.item(
             self.span,
-            Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span),
+            Ident::from_str_and_span(&global_fn_name(method.name), self.span),
             self.attrs(),
             kind,
         );
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 4e5edb4..ebf1448 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -115,6 +115,7 @@
     register_derive! {
         Clone: clone::expand_deriving_clone,
         Copy: bounds::expand_deriving_copy,
+        ConstParamTy: bounds::expand_deriving_const_param_ty,
         Debug: debug::expand_deriving_debug,
         Default: default::expand_deriving_default,
         Eq: eq::expand_deriving_eq,
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index b8a24f1..e613b90 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -188,12 +188,12 @@
                 base::MacEager::expr(cx.expr_str(sp, interned_src))
             }
             Err(_) => {
-                cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
+                cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
                 DummyResult::any(sp)
             }
         },
         Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
             DummyResult::any(sp)
         }
     }
@@ -221,7 +221,7 @@
             base::MacEager::expr(expr)
         }
         Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
             DummyResult::any(sp)
         }
     }
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 73a3e33..84e09cf 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -432,11 +432,9 @@
     let is_cold = if fn_sig.abi() == Abi::RustCold {
         true
     } else {
-        instance
-            .map(|inst| {
-                fx.tcx.codegen_fn_attrs(inst.def_id()).flags.contains(CodegenFnAttrFlags::COLD)
-            })
-            .unwrap_or(false)
+        instance.is_some_and(|inst| {
+            fx.tcx.codegen_fn_attrs(inst.def_id()).flags.contains(CodegenFnAttrFlags::COLD)
+        })
     };
     if is_cold {
         fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
@@ -470,7 +468,7 @@
     };
 
     // Pass the caller location for `#[track_caller]`.
-    if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) {
+    if instance.is_some_and(|inst| inst.def.requires_caller_location(fx.tcx)) {
         let caller_location = fx.get_caller_location(source_info);
         args.push(CallArgument { value: caller_location, is_owned: false });
     }
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 2c246ce..d4b1ae2 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -3,10 +3,12 @@
 
 use crate::prelude::*;
 
-use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
+use rustc_ast::expand::allocator::{
+    alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
+    ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
+};
 use rustc_codegen_ssa::base::allocator_kind_for_codegen;
 use rustc_session::config::OomStrategy;
-use rustc_span::symbol::sym;
 
 /// Returns whether an allocator shim was created
 pub(crate) fn codegen(
@@ -34,41 +36,43 @@
 ) {
     let usize_ty = module.target_config().pointer_type();
 
-    for method in ALLOCATOR_METHODS {
-        let mut arg_tys = Vec::with_capacity(method.inputs.len());
-        for ty in method.inputs.iter() {
-            match *ty {
-                AllocatorTy::Layout => {
-                    arg_tys.push(usize_ty); // size
-                    arg_tys.push(usize_ty); // align
+    if kind == AllocatorKind::Default {
+        for method in ALLOCATOR_METHODS {
+            let mut arg_tys = Vec::with_capacity(method.inputs.len());
+            for ty in method.inputs.iter() {
+                match *ty {
+                    AllocatorTy::Layout => {
+                        arg_tys.push(usize_ty); // size
+                        arg_tys.push(usize_ty); // align
+                    }
+                    AllocatorTy::Ptr => arg_tys.push(usize_ty),
+                    AllocatorTy::Usize => arg_tys.push(usize_ty),
+
+                    AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
                 }
-                AllocatorTy::Ptr => arg_tys.push(usize_ty),
-                AllocatorTy::Usize => arg_tys.push(usize_ty),
-
-                AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
             }
+            let output = match method.output {
+                AllocatorTy::ResultPtr => Some(usize_ty),
+                AllocatorTy::Unit => None,
+
+                AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
+                    panic!("invalid allocator output")
+                }
+            };
+
+            let sig = Signature {
+                call_conv: module.target_config().default_call_conv,
+                params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
+                returns: output.into_iter().map(AbiParam::new).collect(),
+            };
+            crate::common::create_wrapper_function(
+                module,
+                unwind_context,
+                sig,
+                &global_fn_name(method.name),
+                &default_fn_name(method.name),
+            );
         }
-        let output = match method.output {
-            AllocatorTy::ResultPtr => Some(usize_ty),
-            AllocatorTy::Unit => None,
-
-            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
-                panic!("invalid allocator output")
-            }
-        };
-
-        let sig = Signature {
-            call_conv: module.target_config().default_call_conv,
-            params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
-            returns: output.into_iter().map(AbiParam::new).collect(),
-        };
-        crate::common::create_wrapper_function(
-            module,
-            unwind_context,
-            sig,
-            &format!("__rust_{}", method.name),
-            &kind.fn_name(method.name),
-        );
     }
 
     let sig = Signature {
@@ -81,7 +85,7 @@
         unwind_context,
         sig,
         "__rust_alloc_error_handler",
-        &alloc_error_handler_kind.fn_name(sym::oom),
+        &alloc_error_handler_name(alloc_error_handler_kind),
     );
 
     let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
@@ -90,4 +94,11 @@
     let val = oom_strategy.should_panic();
     data_ctx.define(Box::new([val]));
     module.define_data(data_id, &data_ctx).unwrap();
+
+    let data_id =
+        module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap();
+    let mut data_ctx = DataContext::new();
+    data_ctx.set_align(1);
+    data_ctx.define(Box::new([0]));
+    module.define_data(data_id, &data_ctx).unwrap();
 }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index e9dbea1..9c6a0fa 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -630,11 +630,11 @@
                     let to_ty = fx.monomorphize(to_ty);
 
                     fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
-                        ty.builtin_deref(true)
-                            .map(|ty::TypeAndMut { ty: pointee_ty, mutbl: _ }| {
+                        ty.builtin_deref(true).is_some_and(
+                            |ty::TypeAndMut { ty: pointee_ty, mutbl: _ }| {
                                 has_ptr_meta(fx.tcx, pointee_ty)
-                            })
-                            .unwrap_or(false)
+                            },
+                        )
                     }
 
                     if is_fat_ptr(fx, from_ty) {
@@ -966,11 +966,7 @@
     args: &[Value],
     span: Span,
 ) {
-    let def_id = fx
-        .tcx
-        .lang_items()
-        .require(lang_item)
-        .unwrap_or_else(|e| fx.tcx.sess.span_fatal(span, e.to_string()));
+    let def_id = fx.tcx.require_lang_item(lang_item, Some(span));
 
     let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
     let symbol_name = fx.tcx.symbol_name(instance).name;
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index ccb3a0c..5eaa988 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -413,11 +413,7 @@
 
     // Note: must be kept in sync with get_caller_location from cg_ssa
     pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
-        let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, mut span: Span| {
-            // Remove `Inlined` marks as they pollute `expansion_cause`.
-            while span.is_inlined() {
-                span.remove_mark();
-            }
+        let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
             let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
             let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
             let const_loc = fx.tcx.const_caller_location((
diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
index 27e2118..1007b33 100644
--- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
+++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
@@ -227,7 +227,7 @@
         // Using early_warn as no Session is available here
         rustc_session::early_warn(
             rustc_session::config::ErrorOutputType::default(),
-            &format!("error writing ir file: {}", err),
+            format!("error writing ir file: {}", err),
         );
     }
 }
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 0a94a08..97bc8ef 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -1,68 +1,68 @@
-codegen_gcc_unwinding_inline_asm =
-    GCC backend does not support unwinding from inline asm
-
-codegen_gcc_lto_not_supported =
-    LTO is not supported. You may get a linker error.
+codegen_gcc_invalid_minimum_alignment =
+    invalid minimum global alignment: {$err}
 
 codegen_gcc_invalid_monomorphization_basic_integer =
     invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
 
-codegen_gcc_invalid_monomorphization_invalid_float_vector =
-    invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
-
-codegen_gcc_invalid_monomorphization_not_float =
-    invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
-
-codegen_gcc_invalid_monomorphization_unrecognized =
-    invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
-
 codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
     invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
 
-codegen_gcc_invalid_monomorphization_unsupported_element =
-    invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
-
-codegen_gcc_invalid_monomorphization_invalid_bitmask =
-    invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-
-codegen_gcc_invalid_monomorphization_simd_shuffle =
-    invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
-
 codegen_gcc_invalid_monomorphization_expected_simd =
     invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
 
+codegen_gcc_invalid_monomorphization_inserted_type =
+    invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_invalid_bitmask =
+    invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+
+codegen_gcc_invalid_monomorphization_invalid_float_vector =
+    invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
+
 codegen_gcc_invalid_monomorphization_mask_type =
     invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
 
+codegen_gcc_invalid_monomorphization_mismatched_lengths =
+    invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_gcc_invalid_monomorphization_not_float =
+    invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
+
+codegen_gcc_invalid_monomorphization_return_element =
+    invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_return_integer_type =
+    invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
 codegen_gcc_invalid_monomorphization_return_length =
     invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
 
 codegen_gcc_invalid_monomorphization_return_length_input_type =
     invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
 
-codegen_gcc_invalid_monomorphization_return_element =
-    invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
-
 codegen_gcc_invalid_monomorphization_return_type =
     invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
 
-codegen_gcc_invalid_monomorphization_inserted_type =
-    invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+codegen_gcc_invalid_monomorphization_simd_shuffle =
+    invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
 
-codegen_gcc_invalid_monomorphization_return_integer_type =
-    invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
-
-codegen_gcc_invalid_monomorphization_mismatched_lengths =
-    invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+codegen_gcc_invalid_monomorphization_unrecognized =
+    invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
 
 codegen_gcc_invalid_monomorphization_unsupported_cast =
     invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
 
+codegen_gcc_invalid_monomorphization_unsupported_element =
+    invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
+
 codegen_gcc_invalid_monomorphization_unsupported_operation =
     invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
 
-codegen_gcc_invalid_minimum_alignment =
-    invalid minimum global alignment: {$err}
+codegen_gcc_lto_not_supported =
+    LTO is not supported. You may get a linker error.
 
 codegen_gcc_tied_target_features = the target features {$features} must all be either enabled or disabled together
     .help = add the missing features in a `target_feature` attribute
+
+codegen_gcc_unwinding_inline_asm =
+    GCC backend does not support unwinding from inline asm
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index 4bad33e..13f8819 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -1,11 +1,13 @@
 #[cfg(feature="master")]
 use gccjit::FnAttribute;
 use gccjit::{FunctionType, GlobalKind, ToRValue};
-use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
+use rustc_ast::expand::allocator::{
+    alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
+    ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
+};
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::OomStrategy;
-use rustc_span::symbol::sym;
 
 use crate::GccContext;
 
@@ -22,69 +24,71 @@
     let i8p = i8.make_pointer();
     let void = context.new_type::<()>();
 
-    for method in ALLOCATOR_METHODS {
-        let mut types = Vec::with_capacity(method.inputs.len());
-        for ty in method.inputs.iter() {
-            match *ty {
-                AllocatorTy::Layout => {
-                    types.push(usize);
-                    types.push(usize);
+    if kind == AllocatorKind::Default {
+        for method in ALLOCATOR_METHODS {
+            let mut types = Vec::with_capacity(method.inputs.len());
+            for ty in method.inputs.iter() {
+                match *ty {
+                    AllocatorTy::Layout => {
+                        types.push(usize);
+                        types.push(usize);
+                    }
+                    AllocatorTy::Ptr => types.push(i8p),
+                    AllocatorTy::Usize => types.push(usize),
+
+                    AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
                 }
-                AllocatorTy::Ptr => types.push(i8p),
-                AllocatorTy::Usize => types.push(usize),
-
-                AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
             }
-        }
-        let output = match method.output {
-            AllocatorTy::ResultPtr => Some(i8p),
-            AllocatorTy::Unit => None,
+            let output = match method.output {
+                AllocatorTy::ResultPtr => Some(i8p),
+                AllocatorTy::Unit => None,
 
-            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
-                panic!("invalid allocator output")
+                AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
+                    panic!("invalid allocator output")
+                }
+            };
+            let name = global_fn_name(method.name);
+
+            let args: Vec<_> = types.iter().enumerate()
+                .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
+                .collect();
+            let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
+
+            if tcx.sess.target.options.default_hidden_visibility {
+                #[cfg(feature="master")]
+                func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
             }
-        };
-        let name = format!("__rust_{}", method.name);
+            if tcx.sess.must_emit_unwind_tables() {
+                // TODO(antoyo): emit unwind tables.
+            }
 
-        let args: Vec<_> = types.iter().enumerate()
-            .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
-            .collect();
-        let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
-
-        if tcx.sess.target.options.default_hidden_visibility {
+            let callee = default_fn_name(method.name);
+            let args: Vec<_> = types.iter().enumerate()
+                .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
+                .collect();
+            let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
             #[cfg(feature="master")]
-            func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
-        }
-        if tcx.sess.must_emit_unwind_tables() {
-            // TODO(antoyo): emit unwind tables.
-        }
+            callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
 
-        let callee = kind.fn_name(method.name);
-        let args: Vec<_> = types.iter().enumerate()
-            .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
-            .collect();
-        let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
-        #[cfg(feature="master")]
-        callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
+            let block = func.new_block("entry");
 
-        let block = func.new_block("entry");
+            let args = args
+                .iter()
+                .enumerate()
+                .map(|(i, _)| func.get_param(i as i32).to_rvalue())
+                .collect::<Vec<_>>();
+            let ret = context.new_call(None, callee, &args);
+            //llvm::LLVMSetTailCall(ret, True);
+            if output.is_some() {
+                block.end_with_return(None, ret);
+            }
+            else {
+                block.end_with_void_return(None);
+            }
 
-        let args = args
-            .iter()
-            .enumerate()
-            .map(|(i, _)| func.get_param(i as i32).to_rvalue())
-            .collect::<Vec<_>>();
-        let ret = context.new_call(None, callee, &args);
-        //llvm::LLVMSetTailCall(ret, True);
-        if output.is_some() {
-            block.end_with_return(None, ret);
+            // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
+            // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
         }
-        else {
-            block.end_with_void_return(None);
-        }
-
-        // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
-        // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
     }
 
     let types = [usize, usize];
@@ -99,7 +103,7 @@
         func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
     }
 
-    let callee = alloc_error_handler_kind.fn_name(sym::oom);
+    let callee = alloc_error_handler_name(alloc_error_handler_kind);
     let args: Vec<_> = types.iter().enumerate()
         .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
         .collect();
@@ -123,4 +127,9 @@
     let value = tcx.sess.opts.unstable_opts.oom.should_panic();
     let value = context.new_rvalue_from_int(i8, value as i32);
     global.global_set_initializer_rvalue(value);
+
+    let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
+    let global = context.new_global(None, GlobalKind::Exported, i8, name);
+    let value = context.new_rvalue_from_int(i8, 0);
+    global.global_set_initializer_rvalue(value);
 }
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 1cabb05..442ce0e 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -80,8 +80,8 @@
 use rustc_fluent_macro::fluent_messages;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
-use rustc_middle::ty::query::Providers;
 use rustc_session::config::{Lto, OptLevel, OutputFilenames};
 use rustc_session::Session;
 use rustc_span::Symbol;
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 5e750d9..ad51f2d 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -11,7 +11,7 @@
 cstr = "0.2"
 libc = "0.2"
 measureme = "10.0.0"
-object = { version = "0.30.1", default-features = false, features = [
+object = { version = "0.31.1", default-features = false, features = [
     "std",
     "read",
 ] }
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index d776347..55622fd 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -1,3 +1,73 @@
+codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
+
+codegen_llvm_dlltool_fail_import_library =
+    Dlltool could not create import library: {$stdout}
+    {$stderr}
+
+codegen_llvm_dynamic_linking_with_lto =
+    cannot prefer dynamic linking when performing LTO
+    .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+
+codegen_llvm_error_calling_dlltool =
+    Error calling dlltool '{$dlltool_path}': {$error}
+
+codegen_llvm_error_creating_import_library =
+    Error creating import library for {$lib_name}: {$error}
+
+codegen_llvm_error_writing_def_file =
+    Error writing .DEF file: {$error}
+
+codegen_llvm_from_llvm_diag = {$message}
+
+codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
+codegen_llvm_invalid_minimum_alignment =
+    invalid minimum global alignment: {$err}
+
+codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
+codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
+
+codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
+
+codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
+
+codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
+
+codegen_llvm_missing_features =
+    add the missing features in a `target_feature` attribute
+
+codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
+codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
+
+codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
+codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
+
+codegen_llvm_parse_target_machine_config =
+    failed to parse target machine config to target machine: {$error}
+
+codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
+codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
+
+codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
+codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
+
+codegen_llvm_run_passes = failed to run LLVM passes
+codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
+
+codegen_llvm_sanitizer_memtag_requires_mte =
+    `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
+
+codegen_llvm_serialize_module = failed to serialize module {$name}
+codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
+
+codegen_llvm_symbol_already_defined =
+    symbol `{$symbol_name}` is already defined
+
+codegen_llvm_target_feature_disable_or_enable =
+    the target features {$features} must all be either enabled or disabled together
+
+codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
+codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
+
 codegen_llvm_unknown_ctarget_feature =
     unknown feature specified for `-Ctarget-feature`: `{$feature}`
     .note = it is still passed through to the codegen backend
@@ -8,83 +78,13 @@
     unknown feature specified for `-Ctarget-feature`: `{$feature}`
     .note = features must begin with a `+` to enable or `-` to disable it
 
-codegen_llvm_error_creating_import_library =
-    Error creating import library for {$lib_name}: {$error}
-
-codegen_llvm_symbol_already_defined =
-    symbol `{$symbol_name}` is already defined
-
-codegen_llvm_invalid_minimum_alignment =
-    invalid minimum global alignment: {$err}
-
-codegen_llvm_sanitizer_memtag_requires_mte =
-    `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
-
-codegen_llvm_error_writing_def_file =
-    Error writing .DEF file: {$error}
-
-codegen_llvm_error_calling_dlltool =
-    Error calling dlltool '{$dlltool_path}': {$error}
-
-codegen_llvm_dlltool_fail_import_library =
-    Dlltool could not create import library: {$stdout}
-    {$stderr}
-
-codegen_llvm_target_feature_disable_or_enable =
-    the target features {$features} must all be either enabled or disabled together
-
-codegen_llvm_missing_features =
-    add the missing features in a `target_feature` attribute
-
-codegen_llvm_dynamic_linking_with_lto =
-    cannot prefer dynamic linking when performing LTO
-    .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
-
-codegen_llvm_parse_target_machine_config =
-    failed to parse target machine config to target machine: {$error}
-
-codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
-
-codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
-
-codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
-
-codegen_llvm_write_output = could not write output to {$path}
-codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
-
-codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
-codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
-
-codegen_llvm_run_passes = failed to run LLVM passes
-codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
-
-codegen_llvm_serialize_module = failed to serialize module {$name}
-codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
+codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
 
 codegen_llvm_write_ir = failed to write LLVM IR to {$path}
 codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
 
-codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
-codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
-
-codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
-codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
+codegen_llvm_write_output = could not write output to {$path}
+codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
 
 codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
 codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
-
-codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
-codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
-
-codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
-codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
-
-codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
-codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
-
-codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
-codegen_llvm_from_llvm_diag = {$message}
-
-codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
-
-codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 668d929..a575088 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -1,10 +1,12 @@
 use crate::attributes;
 use libc::c_uint;
-use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
+use rustc_ast::expand::allocator::{
+    alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
+    ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
+};
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{DebugInfo, OomStrategy};
-use rustc_span::symbol::sym;
 
 use crate::debuginfo;
 use crate::llvm::{self, False, True};
@@ -29,75 +31,78 @@
     let i8p = llvm::LLVMPointerType(i8, 0);
     let void = llvm::LLVMVoidTypeInContext(llcx);
 
-    for method in ALLOCATOR_METHODS {
-        let mut args = Vec::with_capacity(method.inputs.len());
-        for ty in method.inputs.iter() {
-            match *ty {
-                AllocatorTy::Layout => {
-                    args.push(usize); // size
-                    args.push(usize); // align
+    if kind == AllocatorKind::Default {
+        for method in ALLOCATOR_METHODS {
+            let mut args = Vec::with_capacity(method.inputs.len());
+            for ty in method.inputs.iter() {
+                match *ty {
+                    AllocatorTy::Layout => {
+                        args.push(usize); // size
+                        args.push(usize); // align
+                    }
+                    AllocatorTy::Ptr => args.push(i8p),
+                    AllocatorTy::Usize => args.push(usize),
+
+                    AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
                 }
-                AllocatorTy::Ptr => args.push(i8p),
-                AllocatorTy::Usize => args.push(usize),
-
-                AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
             }
-        }
-        let output = match method.output {
-            AllocatorTy::ResultPtr => Some(i8p),
-            AllocatorTy::Unit => None,
+            let output = match method.output {
+                AllocatorTy::ResultPtr => Some(i8p),
+                AllocatorTy::Unit => None,
 
-            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
-                panic!("invalid allocator output")
+                AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
+                    panic!("invalid allocator output")
+                }
+            };
+            let ty = llvm::LLVMFunctionType(
+                output.unwrap_or(void),
+                args.as_ptr(),
+                args.len() as c_uint,
+                False,
+            );
+            let name = global_fn_name(method.name);
+            let llfn =
+                llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
+
+            if tcx.sess.target.default_hidden_visibility {
+                llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
             }
-        };
-        let ty = llvm::LLVMFunctionType(
-            output.unwrap_or(void),
-            args.as_ptr(),
-            args.len() as c_uint,
-            False,
-        );
-        let name = format!("__rust_{}", method.name);
-        let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
+            if tcx.sess.must_emit_unwind_tables() {
+                let uwtable = attributes::uwtable_attr(llcx);
+                attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
+            }
 
-        if tcx.sess.target.default_hidden_visibility {
-            llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+            let callee = default_fn_name(method.name);
+            let callee =
+                llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
+            llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
+
+            let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
+
+            let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
+            llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
+            let args = args
+                .iter()
+                .enumerate()
+                .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
+                .collect::<Vec<_>>();
+            let ret = llvm::LLVMRustBuildCall(
+                llbuilder,
+                ty,
+                callee,
+                args.as_ptr(),
+                args.len() as c_uint,
+                [].as_ptr(),
+                0 as c_uint,
+            );
+            llvm::LLVMSetTailCall(ret, True);
+            if output.is_some() {
+                llvm::LLVMBuildRet(llbuilder, ret);
+            } else {
+                llvm::LLVMBuildRetVoid(llbuilder);
+            }
+            llvm::LLVMDisposeBuilder(llbuilder);
         }
-        if tcx.sess.must_emit_unwind_tables() {
-            let uwtable = attributes::uwtable_attr(llcx);
-            attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
-        }
-
-        let callee = kind.fn_name(method.name);
-        let callee =
-            llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
-        llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
-
-        let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
-
-        let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
-        llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
-        let args = args
-            .iter()
-            .enumerate()
-            .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
-            .collect::<Vec<_>>();
-        let ret = llvm::LLVMRustBuildCall(
-            llbuilder,
-            ty,
-            callee,
-            args.as_ptr(),
-            args.len() as c_uint,
-            [].as_ptr(),
-            0 as c_uint,
-        );
-        llvm::LLVMSetTailCall(ret, True);
-        if output.is_some() {
-            llvm::LLVMBuildRet(llbuilder, ret);
-        } else {
-            llvm::LLVMBuildRetVoid(llbuilder);
-        }
-        llvm::LLVMDisposeBuilder(llbuilder);
     }
 
     // rust alloc error handler
@@ -118,7 +123,7 @@
         attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
     }
 
-    let callee = alloc_error_handler_kind.fn_name(sym::oom);
+    let callee = alloc_error_handler_name(alloc_error_handler_kind);
     let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
     // -> ! DIFlagNoReturn
     attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
@@ -156,6 +161,14 @@
     let llval = llvm::LLVMConstInt(i8, val as u64, False);
     llvm::LLVMSetInitializer(ll_g, llval);
 
+    let name = NO_ALLOC_SHIM_IS_UNSTABLE;
+    let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
+    if tcx.sess.target.default_hidden_visibility {
+        llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
+    }
+    let llval = llvm::LLVMConstInt(i8, 0, False);
+    llvm::LLVMSetInitializer(ll_g, llval);
+
     if tcx.sess.opts.debuginfo != DebugInfo::None {
         let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod);
         debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index d2e0170..604f68e 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -25,7 +25,6 @@
 use std::io;
 use std::iter;
 use std::path::Path;
-use std::ptr;
 use std::slice;
 use std::sync::Arc;
 
@@ -709,17 +708,6 @@
         let llmod = module.module_llvm.llmod();
         save_temp_bitcode(cgcx, &module, "thin-lto-input");
 
-        // Before we do much else find the "main" `DICompileUnit` that we'll be
-        // using below. If we find more than one though then rustc has changed
-        // in a way we're not ready for, so generate an ICE by returning
-        // an error.
-        let mut cu1 = ptr::null_mut();
-        let mut cu2 = ptr::null_mut();
-        llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
-        if !cu2.is_null() {
-            return Err(write::llvm_err(&diag_handler, LlvmError::MultipleSourceDiCompileUnit));
-        }
-
         // Up next comes the per-module local analyses that we do for Thin LTO.
         // Each of these functions is basically copied from the LLVM
         // implementation and then tailored to suit this implementation. Ideally
@@ -766,43 +754,6 @@
             save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
         }
 
-        // Ok now this is a bit unfortunate. This is also something you won't
-        // find upstream in LLVM's ThinLTO passes! This is a hack for now to
-        // work around bugs in LLVM.
-        //
-        // First discovered in #45511 it was found that as part of ThinLTO
-        // importing passes LLVM will import `DICompileUnit` metadata
-        // information across modules. This means that we'll be working with one
-        // LLVM module that has multiple `DICompileUnit` instances in it (a
-        // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
-        // bugs in LLVM's backend which generates invalid DWARF in a situation
-        // like this:
-        //
-        //  https://bugs.llvm.org/show_bug.cgi?id=35212
-        //  https://bugs.llvm.org/show_bug.cgi?id=35562
-        //
-        // While the first bug there is fixed the second ended up causing #46346
-        // which was basically a resurgence of #45511 after LLVM's bug 35212 was
-        // fixed.
-        //
-        // This function below is a huge hack around this problem. The function
-        // below is defined in `PassWrapper.cpp` and will basically "merge"
-        // all `DICompileUnit` instances in a module. Basically it'll take all
-        // the objects, rewrite all pointers of `DISubprogram` to point to the
-        // first `DICompileUnit`, and then delete all the other units.
-        //
-        // This is probably mangling to the debug info slightly (but hopefully
-        // not too much) but for now at least gets LLVM to emit valid DWARF (or
-        // so it appears). Hopefully we can remove this once upstream bugs are
-        // fixed in LLVM.
-        {
-            let _timer = cgcx
-                .prof
-                .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name());
-            llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
-            save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
-        }
-
         // Alright now that we've done everything related to the ThinLTO
         // analysis it's time to run some optimizations! Here we use the same
         // `run_pass_manager` as the "fat" LTO above except that we tell it to
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 240a9d2..21a1ac3 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -163,7 +163,7 @@
         counter_regions.sort_unstable_by_key(|(_counter, region)| *region);
         for (counter, region) in counter_regions {
             let CodeRegion { file_name, start_line, start_col, end_line, end_col } = *region;
-            let same_file = current_file_name.map_or(false, |p| p == file_name);
+            let same_file = current_file_name.is_some_and(|p| p == file_name);
             if !same_file {
                 if current_file_name.is_some() {
                     current_file_id += 1;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index aaf5dbd..37f3091 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -9,10 +9,9 @@
 use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::bug;
+use rustc_middle::{bug, middle::debugger_visualizer::DebuggerVisualizerType};
 use rustc_session::config::{CrateType, DebugInfo};
 use rustc_span::symbol::sym;
-use rustc_span::DebuggerVisualizerType;
 
 /// Inserts a side-effect free instruction sequence that makes sure that the
 /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 25fe3cb..bd2fba1 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -806,8 +806,7 @@
     name_in_debuginfo.push(codegen_unit_name);
 
     debug!("build_compile_unit_di_node: {:?}", name_in_debuginfo);
-    let rustc_producer =
-        format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),);
+    let rustc_producer = format!("rustc version {}", tcx.sess.cfg_version);
     // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
     let producer = format!("clang LLVM ({})", rustc_producer);
 
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 8305a0a..805843e 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -10,6 +10,7 @@
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(never_type)]
+#![feature(impl_trait_in_assoc_type)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
@@ -37,7 +38,7 @@
 use rustc_fluent_macro::fluent_messages;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
 use rustc_session::Session;
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index aefd5b2..de93a64 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2484,12 +2484,6 @@
         len: usize,
         out_len: &mut usize,
     ) -> *const u8;
-    pub fn LLVMRustThinLTOGetDICompileUnit(
-        M: &Module,
-        CU1: &mut *mut c_void,
-        CU2: &mut *mut c_void,
-    );
-    pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
 
     pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
     pub fn LLVMRustLinkerAdd(
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 2fbdab9..03be065 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -16,7 +16,6 @@
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
-use smallvec::{smallvec, SmallVec};
 use std::ffi::{CStr, CString};
 
 use std::path::Path;
@@ -132,6 +131,60 @@
     }
 }
 
+pub enum TargetFeatureFoldStrength<'a> {
+    // The feature is only tied when enabling the feature, disabling
+    // this feature shouldn't disable the tied feature.
+    EnableOnly(&'a str),
+    // The feature is tied for both enabling and disabling this feature.
+    Both(&'a str),
+}
+
+impl<'a> TargetFeatureFoldStrength<'a> {
+    fn as_str(&self) -> &'a str {
+        match self {
+            TargetFeatureFoldStrength::EnableOnly(feat) => feat,
+            TargetFeatureFoldStrength::Both(feat) => feat,
+        }
+    }
+}
+
+pub struct LLVMFeature<'a> {
+    pub llvm_feature_name: &'a str,
+    pub dependency: Option<TargetFeatureFoldStrength<'a>>,
+}
+
+impl<'a> LLVMFeature<'a> {
+    pub fn new(llvm_feature_name: &'a str) -> Self {
+        Self { llvm_feature_name, dependency: None }
+    }
+
+    pub fn with_dependency(
+        llvm_feature_name: &'a str,
+        dependency: TargetFeatureFoldStrength<'a>,
+    ) -> Self {
+        Self { llvm_feature_name, dependency: Some(dependency) }
+    }
+
+    pub fn contains(&self, feat: &str) -> bool {
+        self.iter().any(|dep| dep == feat)
+    }
+
+    pub fn iter(&'a self) -> impl Iterator<Item = &'a str> {
+        let dependencies = self.dependency.iter().map(|feat| feat.as_str());
+        std::iter::once(self.llvm_feature_name).chain(dependencies)
+    }
+}
+
+impl<'a> IntoIterator for LLVMFeature<'a> {
+    type Item = &'a str;
+    type IntoIter = impl Iterator<Item = &'a str>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        let dependencies = self.dependency.into_iter().map(|feat| feat.as_str());
+        std::iter::once(self.llvm_feature_name).chain(dependencies)
+    }
+}
+
 // WARNING: the features after applying `to_llvm_features` must be known
 // to LLVM or the feature detection code will walk past the end of the feature
 // array, leading to crashes.
@@ -147,42 +200,65 @@
 // Though note that Rust can also be build with an external precompiled version of LLVM
 // which might lead to failures if the oldest tested / supported LLVM version
 // doesn't yet support the relevant intrinsics
-pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
+pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> {
     let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
     match (arch, s) {
-        ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"],
-        ("x86", "pclmulqdq") => smallvec!["pclmul"],
-        ("x86", "rdrand") => smallvec!["rdrnd"],
-        ("x86", "bmi1") => smallvec!["bmi"],
-        ("x86", "cmpxchg16b") => smallvec!["cx16"],
-        // FIXME: These aliases are misleading, and should be removed before avx512_target_feature is
-        // stabilized. They must remain until std::arch switches off them.
-        // rust#100752
-        ("x86", "avx512vaes") => smallvec!["vaes"],
-        ("x86", "avx512gfni") => smallvec!["gfni"],
-        ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
-        ("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
-        ("aarch64", "dpb") => smallvec!["ccpp"],
-        ("aarch64", "dpb2") => smallvec!["ccdp"],
-        ("aarch64", "frintts") => smallvec!["fptoint"],
-        ("aarch64", "fcma") => smallvec!["complxnum"],
-        ("aarch64", "pmuv3") => smallvec!["perfmon"],
-        ("aarch64", "paca") => smallvec!["pauth"],
-        ("aarch64", "pacg") => smallvec!["pauth"],
-        // Rust ties fp and neon together. In LLVM neon implicitly enables fp,
-        // but we manually enable neon when a feature only implicitly enables fp
-        ("aarch64", "f32mm") => smallvec!["f32mm", "neon"],
-        ("aarch64", "f64mm") => smallvec!["f64mm", "neon"],
-        ("aarch64", "fhm") => smallvec!["fp16fml", "neon"],
-        ("aarch64", "fp16") => smallvec!["fullfp16", "neon"],
-        ("aarch64", "jsconv") => smallvec!["jsconv", "neon"],
-        ("aarch64", "sve") => smallvec!["sve", "neon"],
-        ("aarch64", "sve2") => smallvec!["sve2", "neon"],
-        ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"],
-        ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"],
-        ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"],
-        ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"],
-        (_, s) => smallvec![s],
+        ("x86", "sse4.2") => {
+            LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32"))
+        }
+        ("x86", "pclmulqdq") => LLVMFeature::new("pclmul"),
+        ("x86", "rdrand") => LLVMFeature::new("rdrnd"),
+        ("x86", "bmi1") => LLVMFeature::new("bmi"),
+        ("x86", "cmpxchg16b") => LLVMFeature::new("cx16"),
+        ("aarch64", "rcpc2") => LLVMFeature::new("rcpc-immo"),
+        ("aarch64", "dpb") => LLVMFeature::new("ccpp"),
+        ("aarch64", "dpb2") => LLVMFeature::new("ccdp"),
+        ("aarch64", "frintts") => LLVMFeature::new("fptoint"),
+        ("aarch64", "fcma") => LLVMFeature::new("complxnum"),
+        ("aarch64", "pmuv3") => LLVMFeature::new("perfmon"),
+        ("aarch64", "paca") => LLVMFeature::new("pauth"),
+        ("aarch64", "pacg") => LLVMFeature::new("pauth"),
+        // Rust ties fp and neon together.
+        ("aarch64", "neon") => {
+            LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8"))
+        }
+        // In LLVM neon implicitly enables fp, but we manually enable
+        // neon when a feature only implicitly enables fp
+        ("aarch64", "f32mm") => {
+            LLVMFeature::with_dependency("f32mm", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "f64mm") => {
+            LLVMFeature::with_dependency("f64mm", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "fhm") => {
+            LLVMFeature::with_dependency("fp16fml", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "fp16") => {
+            LLVMFeature::with_dependency("fullfp16", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "jsconv") => {
+            LLVMFeature::with_dependency("jsconv", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve") => {
+            LLVMFeature::with_dependency("sve", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2") => {
+            LLVMFeature::with_dependency("sve2", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-aes") => {
+            LLVMFeature::with_dependency("sve2-aes", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-sm4") => {
+            LLVMFeature::with_dependency("sve2-sm4", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-sha3") => {
+            LLVMFeature::with_dependency("sve2-sha3", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-bitperm") => LLVMFeature::with_dependency(
+            "sve2-bitperm",
+            TargetFeatureFoldStrength::EnableOnly("neon"),
+        ),
+        (_, s) => LLVMFeature::new(s),
     }
 }
 
@@ -280,18 +356,17 @@
     let mut rustc_target_features = supported_target_features(sess)
         .iter()
         .map(|(feature, _gate)| {
-            let desc = if let Some(llvm_feature) = to_llvm_features(sess, *feature).first() {
-                // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
+            // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
+            let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name;
+            let desc =
                 match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() {
                     Some(index) => {
                         known_llvm_target_features.insert(llvm_feature);
                         llvm_target_features[index].1
                     }
                     None => "",
-                }
-            } else {
-                ""
-            };
+                };
+
             (*feature, desc)
         })
         .collect::<Vec<_>>();
@@ -475,10 +550,19 @@
             // passing requests down to LLVM. This means that all in-language
             // features also work on the command line instead of having two
             // different names when the LLVM name and the Rust name differ.
+            let llvm_feature = to_llvm_features(sess, feature);
+
             Some(
-                to_llvm_features(sess, feature)
-                    .into_iter()
-                    .map(move |f| format!("{}{}", enable_disable, f)),
+                std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name))
+                    .chain(llvm_feature.dependency.into_iter().filter_map(move |feat| {
+                        match (enable_disable, feat) {
+                            ('-' | '+', TargetFeatureFoldStrength::Both(f))
+                            | ('+', TargetFeatureFoldStrength::EnableOnly(f)) => {
+                                Some(format!("{}{}", enable_disable, f))
+                            }
+                            _ => None,
+                        }
+                    })),
             )
         })
         .flatten();
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index e8f8c32..c24854b 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -125,8 +125,7 @@
 
         // Thread-local variables generally don't support copy relocations.
         let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
-            .map(|v| llvm::LLVMIsThreadLocal(v) == llvm::True)
-            .unwrap_or(false);
+            .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
         if is_thread_local_var {
             return false;
         }
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 02be88d..0ac12d3 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -14,7 +14,7 @@
 tracing = "0.1"
 jobserver = "0.1.22"
 tempfile = "3.2"
-thorin-dwp = "0.4"
+thorin-dwp = "0.6"
 pathdiff = "0.2.0"
 serde_json = "1.0.59"
 snap = "1"
@@ -46,7 +46,7 @@
 libc = "0.2.50"
 
 [dependencies.object]
-version = "0.30.1"
+version = "0.31.1"
 default-features = false
 features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
 
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 375fdec..9aa2b2e 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -1,80 +1,258 @@
-codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
-
-codegen_ssa_version_script_write_failure = failed to write version script: {$error}
-
-codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
-
-codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
-
-codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
-
 codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender
 
-codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
+codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
+
+codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
+
+codegen_ssa_archive_build_failure =
+    failed to build archive: {$error}
+
+codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
+
+codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
 
 codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error}
 
 codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error}
 
+codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
+
+codegen_ssa_erroneous_constant = erroneous constant encountered
+
+codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
+codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
+
+codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error}
+codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error}
+
+codegen_ssa_failed_to_write = failed to write {$path}: {$error}
+
 codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
 
 codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced
 
-codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
+codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
+    .note = an unsuffixed integer value, e.g., `1`, is expected
 
 codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
 
-codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
+codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
 
-codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
+codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
+    .note = the attribute requires exactly one argument
 
-codegen_ssa_rlib_missing_format = could not find formats for rlibs
+codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
 
-codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file
+codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
 
-codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
+codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
-codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
+codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
+
+codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
+
+codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
+
+codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
+
+codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
+
+codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+
+codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+
+codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
+
+codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
+
+codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
+
+codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
+
+codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
+
+codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
+
+codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
+
+codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
+    .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
+
+codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
+
+codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
+
+codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
+
+codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error
+
+codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
+
+codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
+
+codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
+
+codegen_ssa_linker_not_found = linker `{$linker_path}` not found
+    .note = {$error}
+
+codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
 
 codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
 
-codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
+codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
+
+codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
+
+codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
+
+codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found
+
+codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
+
+codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
+    .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
+
+codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
+
+codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc
+
+codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
+
+codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
+    .note = {$output}
+
+codegen_ssa_read_file = failed to read file: {$message}
+
+codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
+
+codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error}
+
+codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
+
+codegen_ssa_rlib_missing_format = could not find formats for rlibs
+
+codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
+
+codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file
+
+codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
+
+codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
 
 codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link
 
-codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
+codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
 
-codegen_ssa_thorin_read_input_failure = failed to read input file
+codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
+    .note = {$output}
 
-codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind
+codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
 
-codegen_ssa_thorin_parse_input_object_file = failed to parse input object file
-
-codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file
-
-codegen_ssa_thorin_parse_archive_member = failed to parse archive member
-
-codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object
+codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
+    .label = cannot be applied to safe trait method
+    .label_def = not an `unsafe` function
 
 codegen_ssa_thorin_decompress_data = failed to decompress compressed section
 
-codegen_ssa_thorin_section_without_name = section without name at offset {$offset}
+codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit})
 
-codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset}
+codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data
+
+codegen_ssa_thorin_gimli_read = {$error}
+codegen_ssa_thorin_gimli_write = {$error}
+
+codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format}
+
+codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object
+
+codegen_ssa_thorin_io = {$error}
+codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id})
+
+codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found
+
+codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}`
+
+codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings
+
+codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections
+
+codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package
 
 codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset}
 
-codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
-
-codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id})
-
 codegen_ssa_thorin_no_compilation_units = input object has no compilation units
 
 codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit
 
-codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit
+codegen_ssa_thorin_not_output_object_created = no output object was created from inputs
 
-codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}`
+codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier)
+
+codegen_ssa_thorin_object_read = {$error}
+codegen_ssa_thorin_object_write = {$error}
+codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section
+
+codegen_ssa_thorin_parse_archive_member = failed to parse archive member
+
+codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section
+
+codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file
+
+codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind
+
+codegen_ssa_thorin_parse_input_object_file = failed to parse input object file
+
+codegen_ssa_thorin_parse_unit = failed to parse unit
 
 codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations
 
@@ -82,225 +260,47 @@
 
 codegen_ssa_thorin_parse_unit_header = failed to parse unit header
 
-codegen_ssa_thorin_parse_unit = failed to parse unit
+codegen_ssa_thorin_read_input_failure = failed to read input file
 
-codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format}
-
-codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section
-
-codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section
-
-codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section
-
-codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index
+codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset}
 
 codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index
 
 codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index
 
-codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data
+codegen_ssa_thorin_section_without_name = section without name at offset {$offset}
 
-codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections
+codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section
 
-codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package
+codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit
 
-codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier)
+codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index
 
-codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit})
-
-codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found
-
-codegen_ssa_thorin_not_output_object_created = no output object was created from inputs
-
-codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings
-
-codegen_ssa_thorin_io = {$error}
-codegen_ssa_thorin_object_read = {$error}
-codegen_ssa_thorin_object_write = {$error}
-codegen_ssa_thorin_gimli_read = {$error}
-codegen_ssa_thorin_gimli_write = {$error}
-
-codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error
-
-codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
-
-codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
-
-codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
-
-codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
-
-codegen_ssa_linker_not_found = linker `{$linker_path}` not found
-    .note = {$error}
+codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
 
 codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}`
     .note = {$error}
     .command_note = {$command_formatted}
 
-codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found
-
-codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
-
-codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
-
-codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
-    .note = {$output}
+codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
 
 codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
 
-codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
-    .note = {$output}
-
-codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
-
-codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
-
-codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
-
-codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
-
-codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
-
-codegen_ssa_failed_to_write = failed to write {$path}: {$error}
-
 codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error}
 
-codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error}
-
-codegen_ssa_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc
-
-codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error}
-codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error}
-
-codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
-
-codegen_ssa_read_file = failed to read file: {$message}
-
-codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
-
-codegen_ssa_archive_build_failure =
-    failed to build archive: {$error}
-
 codegen_ssa_unknown_archive_kind =
     Don't know how to build archive of type: {$kind}
 
-codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
-codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
-    .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
-
-codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
-
-codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
-
-codegen_ssa_erroneous_constant = erroneous constant encountered
-
-codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
-
-codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
+codegen_ssa_unknown_atomic_operation = unknown atomic operation
 
 codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
 
-codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
+codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
 
-codegen_ssa_unknown_atomic_operation = unknown atomic operation
+codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
 
-codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
+codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
 
-codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
+codegen_ssa_version_script_write_failure = failed to write version script: {$error}
 
-codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
-
-codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
-
-codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
-
-codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
-
-codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
-
-codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-
-codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
-
-codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
-
-codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
-
-codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
-
-codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
-
-codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
-
-codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
-
-codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
-
-codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
-
-codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
-
-codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
-
-codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-
-codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
-
-codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
-
-codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
-
-codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
-
-codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
-
-codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
-
-codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
-
-codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
-
-codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
-
-codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
-    .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
-
-codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
-    .note = the attribute requires exactly one argument
-
-codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
-    .note = an unsuffixed integer value, e.g., `1`, is expected
-
-codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
-    .label = cannot be applied to safe trait method
-    .label_def = not an `unsafe` function
+codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index ea06cb0..8a00c42 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -9,6 +9,7 @@
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_metadata::find_native_static_library;
 use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
@@ -21,7 +22,6 @@
 /// need out of the shared crate context before we get rid of it.
 use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
-use rustc_span::DebuggerVisualizerFile;
 use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
 use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
 use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
@@ -574,6 +574,8 @@
         }
     }
 
+    all_native_libs.extend_from_slice(&codegen_results.crate_info.used_libraries);
+
     if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
         print_native_static_libs(sess, &all_native_libs, &all_rust_dylibs);
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 1e57f42..cd56f85 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -144,7 +144,7 @@
             cmd,
             sess,
             target_cpu,
-            hinted_static: false,
+            hinted_static: None,
             is_ld: cc == Cc::No,
             is_gnu: flavor.is_gnu(),
         }) as Box<dyn Linker>,
@@ -214,7 +214,7 @@
     cmd: Command,
     sess: &'a Session,
     target_cpu: &'a str,
-    hinted_static: bool, // Keeps track of the current hinting mode.
+    hinted_static: Option<bool>, // Keeps track of the current hinting mode.
     // Link as ld
     is_ld: bool,
     is_gnu: bool,
@@ -275,9 +275,9 @@
         if !self.takes_hints() {
             return;
         }
-        if !self.hinted_static {
+        if self.hinted_static != Some(true) {
             self.linker_arg("-Bstatic");
-            self.hinted_static = true;
+            self.hinted_static = Some(true);
         }
     }
 
@@ -285,9 +285,9 @@
         if !self.takes_hints() {
             return;
         }
-        if self.hinted_static {
+        if self.hinted_static != Some(false) {
             self.linker_arg("-Bdynamic");
-            self.hinted_static = false;
+            self.hinted_static = Some(false);
         }
     }
 
@@ -1484,25 +1484,25 @@
 pub struct AixLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    hinted_static: bool,
+    hinted_static: Option<bool>,
 }
 
 impl<'a> AixLinker<'a> {
     pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> {
-        AixLinker { cmd: cmd, sess: sess, hinted_static: false }
+        AixLinker { cmd: cmd, sess: sess, hinted_static: None }
     }
 
     fn hint_static(&mut self) {
-        if !self.hinted_static {
+        if self.hinted_static != Some(true) {
             self.cmd.arg("-bstatic");
-            self.hinted_static = true;
+            self.hinted_static = Some(true);
         }
     }
 
     fn hint_dynamic(&mut self) {
-        if self.hinted_static {
+        if self.hinted_static != Some(false) {
             self.cmd.arg("-bdynamic");
-            self.hinted_static = false;
+            self.hinted_static = Some(false);
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 8968133..ad27b85 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -14,8 +14,7 @@
 
 use object::elf::NT_GNU_PROPERTY_TYPE_0;
 use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::owned_slice::try_slice_owned;
-use rustc_data_structures::sync::MetadataRef;
+use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
 use rustc_metadata::fs::METADATA_FILENAME;
 use rustc_metadata::EncodedMetadata;
 use rustc_session::cstore::MetadataLoader;
@@ -39,7 +38,7 @@
 fn load_metadata_with(
     path: &Path,
     f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
-) -> Result<MetadataRef, String> {
+) -> Result<OwnedSlice, String> {
     let file =
         File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;
 
@@ -49,7 +48,7 @@
 }
 
 impl MetadataLoader for DefaultMetadataLoader {
-    fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
+    fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
         load_metadata_with(path, |data| {
             let archive = object::read::archive::ArchiveFile::parse(&*data)
                 .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
@@ -69,7 +68,7 @@
         })
     }
 
-    fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
+    fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
         load_metadata_with(path, |data| search_for_section(path, data, ".rustc"))
     }
 }
@@ -189,6 +188,11 @@
     };
 
     let mut file = write::Object::new(binary_format, architecture, endianness);
+    if sess.target.is_like_osx {
+        if let Some(build_version) = macho_object_build_version_for_target(&sess.target) {
+            file.set_macho_build_version(build_version)
+        }
+    }
     let e_flags = match architecture {
         Architecture::Mips => {
             let arch = match sess.target.options.cpu.as_ref() {
@@ -259,6 +263,33 @@
     Some(file)
 }
 
+/// Apple's LD, when linking for Mac Catalyst, requires object files to
+/// contain information about what they were built for (LC_BUILD_VERSION):
+/// the platform (macOS/watchOS etc), minimum OS version, and SDK version.
+/// This returns a `MachOBuildVersion` if necessary for the target.
+fn macho_object_build_version_for_target(
+    target: &Target,
+) -> Option<object::write::MachOBuildVersion> {
+    if !target.llvm_target.ends_with("-macabi") {
+        return None;
+    }
+    /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
+    /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
+    fn pack_version((major, minor): (u32, u32)) -> u32 {
+        (major << 16) | (minor << 8)
+    }
+
+    let platform = object::macho::PLATFORM_MACCATALYST;
+    let min_os = (14, 0);
+    let sdk = (16, 2);
+
+    let mut build_version = object::write::MachOBuildVersion::default();
+    build_version.platform = platform;
+    build_version.minos = pack_version(min_os);
+    build_version.sdk = pack_version(sdk);
+    Some(build_version)
+}
+
 pub enum MetadataPosition {
     First,
     Last,
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 8f2f829..a8b6030 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -2,7 +2,7 @@
 
 use std::collections::hash_map::Entry::*;
 
-use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
+use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
@@ -11,7 +11,7 @@
     metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
 };
 use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, SymbolName, TyCtxt};
@@ -241,6 +241,17 @@
                 used: false,
             },
         ));
+
+        let exported_symbol =
+            ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE));
+        symbols.push((
+            exported_symbol,
+            SymbolExportInfo {
+                level: SymbolExportLevel::Rust,
+                kind: SymbolExportKind::Data,
+                used: false,
+            },
+        ))
     }
 
     if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index ae45ae9..15c7847 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -17,28 +17,25 @@
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
-
-use rustc_data_structures::sync::par_iter;
-#[cfg(parallel_compiler)]
-use rustc_data_structures::sync::ParallelIterator;
+use rustc_data_structures::sync::par_map;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
+use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
 use rustc_middle::middle::exported_symbols;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::middle::lang_items;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Symbol;
-use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
 use rustc_target::abi::{Align, FIRST_VARIANT};
 
 use std::collections::BTreeSet;
@@ -689,7 +686,7 @@
     // This likely is a temporary measure. Once we don't have to support the
     // non-parallel compiler anymore, we can compile CGUs end-to-end in
     // parallel and get rid of the complicated scheduling logic.
-    let mut pre_compiled_cgus = if cfg!(parallel_compiler) {
+    let mut pre_compiled_cgus = if tcx.sess.threads() > 1 {
         tcx.sess.time("compile_first_CGU_batch", || {
             // Try to find one CGU to compile per thread.
             let cgus: Vec<_> = cgu_reuse
@@ -702,12 +699,10 @@
             // Compile the found CGUs in parallel.
             let start_time = Instant::now();
 
-            let pre_compiled_cgus = par_iter(cgus)
-                .map(|(i, _)| {
-                    let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
-                    (i, module)
-                })
-                .collect();
+            let pre_compiled_cgus = par_map(cgus, |(i, _)| {
+                let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
+                (i, module)
+            });
 
             total_codegen_time += start_time.elapsed();
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 8dae5da..d6c2301 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -7,7 +7,7 @@
 use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::mono::Linkage;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self as ty, TyCtxt};
 use rustc_session::{lint, parse::feature_err};
 use rustc_span::symbol::Ident;
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index c3cc17c..31854c7 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -28,16 +28,17 @@
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir::def_id::CrateNum;
 use rustc_middle::dep_graph::WorkProduct;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_serialize::opaque::{FileEncoder, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
 use rustc_session::utils::NativeLibKind;
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_span::DebuggerVisualizerFile;
 use std::collections::BTreeSet;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -175,11 +176,11 @@
     pub crate_info: CrateInfo,
 }
 
-pub enum CodegenErrors<'a> {
+pub enum CodegenErrors {
     WrongFileType,
     EmptyVersionNumber,
     EncodingVersionMismatch { version_array: String, rlink_version: u32 },
-    RustcVersionMismatch { rustc_version: String, current_version: &'a str },
+    RustcVersionMismatch { rustc_version: String },
 }
 
 pub fn provide(providers: &mut Providers) {
@@ -213,10 +214,9 @@
 const RLINK_VERSION: u32 = 1;
 const RLINK_MAGIC: &[u8] = b"rustlink";
 
-const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
-
 impl CodegenResults {
     pub fn serialize_rlink(
+        sess: &Session,
         rlink_file: &Path,
         codegen_results: &CodegenResults,
     ) -> Result<usize, io::Error> {
@@ -225,12 +225,12 @@
         // `emit_raw_bytes` is used to make sure that the version representation does not depend on
         // Encoder's inner representation of `u32`.
         encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
-        encoder.emit_str(RUSTC_VERSION.unwrap());
+        encoder.emit_str(sess.cfg_version);
         Encodable::encode(codegen_results, &mut encoder);
         encoder.finish()
     }
 
-    pub fn deserialize_rlink<'a>(data: Vec<u8>) -> Result<Self, CodegenErrors<'a>> {
+    pub fn deserialize_rlink(sess: &Session, data: Vec<u8>) -> Result<Self, CodegenErrors> {
         // The Decodable machinery is not used here because it panics if the input data is invalid
         // and because its internal representation may change.
         if !data.starts_with(RLINK_MAGIC) {
@@ -252,11 +252,9 @@
 
         let mut decoder = MemDecoder::new(&data[4..], 0);
         let rustc_version = decoder.read_str();
-        let current_version = RUSTC_VERSION.unwrap();
-        if rustc_version != current_version {
+        if rustc_version != sess.cfg_version {
             return Err(CodegenErrors::RustcVersionMismatch {
                 rustc_version: rustc_version.to_string(),
-                current_version,
             });
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 569599f..8350748 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -84,7 +84,7 @@
 
 struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     fx: &'mir FunctionCx<'a, 'tcx, Bx>,
-    dominators: Dominators<mir::BasicBlock>,
+    dominators: &'mir Dominators<mir::BasicBlock>,
     locals: IndexVec<mir::Local, LocalKind>,
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index a832999..d516ac4 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1031,7 +1031,7 @@
         });
 
         let needs_location =
-            instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx()));
+            instance.is_some_and(|i| i.def.requires_caller_location(self.cx.tcx()));
         if needs_location {
             let mir_args = if let Some(num_untupled) = num_untupled {
                 first_args.len() + num_untupled
@@ -1450,11 +1450,7 @@
     ) -> OperandRef<'tcx, Bx::Value> {
         let tcx = bx.tcx();
 
-        let mut span_to_caller_location = |mut span: Span| {
-            // Remove `Inlined` marks as they pollute `expansion_cause`.
-            while span.is_inlined() {
-                span.remove_mark();
-            }
+        let mut span_to_caller_location = |span: Span| {
             let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
             let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
             let const_loc = tcx.const_caller_location((
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 4e5e2dd..bba2800 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -8,7 +8,7 @@
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
-use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx};
+use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx};
 
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
@@ -41,6 +41,9 @@
 
     /// `.place.projection` from `mir::VarDebugInfo`.
     pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
+
+    /// `references` from `mir::VarDebugInfo`.
+    pub references: u8,
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -80,6 +83,7 @@
     fn deref(&self, bx: &mut Bx) -> Self;
     fn layout(&self) -> TyAndLayout<'tcx>;
     fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self;
+    fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self;
     fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
 }
 
@@ -98,6 +102,11 @@
         PlaceRef::project_field(*self, bx, field.index())
     }
 
+    fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self {
+        let lloffset = bx.cx().const_usize(offset);
+        self.project_index(bx, lloffset)
+    }
+
     fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
         self.project_downcast(bx, variant)
     }
@@ -120,6 +129,10 @@
         self.field(bx.cx(), field.index())
     }
 
+    fn project_constant_index(&self, bx: &mut Bx, index: u64) -> Self {
+        self.field(bx.cx(), index as usize)
+    }
+
     fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
         self.for_variant(bx.cx(), variant)
     }
@@ -165,6 +178,18 @@
             mir::ProjectionElem::Downcast(_, variant) => {
                 place = place.downcast(bx, variant);
             }
+            mir::ProjectionElem::ConstantIndex {
+                offset: index,
+                min_length: _,
+                from_end: false,
+            } => {
+                let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
+                let FieldsShape::Array { stride, count: _ } = place.layout().fields else {
+                    span_bug!(var.source_info.span, "ConstantIndex on non-array type {:?}", place.layout())
+                };
+                *offset += stride * index;
+                place = place.project_constant_index(bx, index);
+            }
             _ => {
                 // Sanity check for `can_use_in_debuginfo`.
                 debug_assert!(!elem.can_use_in_debuginfo());
@@ -293,6 +318,7 @@
                     dbg_var,
                     fragment: None,
                     projection: ty::List::empty(),
+                    references: 0,
                 })
             }
         } else {
@@ -358,57 +384,76 @@
         let vars = vars.iter().cloned().chain(fallback_var);
 
         for var in vars {
-            let Some(dbg_var) = var.dbg_var else { continue };
-            let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
-
-            let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
-                calculate_debuginfo_offset(bx, local, &var, base.layout);
-
-            // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
-            // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
-            // not DWARF and LLVM doesn't support translating the resulting
-            // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
-            // Creating extra allocas on the stack makes the resulting debug info simple enough
-            // that LLVM can generate correct CodeView records and thus the values appear in the
-            // debugger. (#83709)
-            let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
-                && self.mir.local_kind(local) == mir::LocalKind::Arg
-                // LLVM can handle simple things but anything more complex than just a direct
-                // offset or one indirect offset of 0 is too complex for it to generate CV records
-                // correctly.
-                && (direct_offset != Size::ZERO
-                    || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
-
-            if should_create_individual_allocas {
-                let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
-                    calculate_debuginfo_offset(bx, local, &var, base);
-
-                // Create a variable which will be a pointer to the actual value
-                let ptr_ty = bx
-                    .tcx()
-                    .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
-                let ptr_layout = bx.layout_of(ptr_ty);
-                let alloca = PlaceRef::alloca(bx, ptr_layout);
-                bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
-
-                // Write the pointer to the variable
-                bx.store(place.llval, alloca.llval, alloca.align);
-
-                // Point the debug info to `*alloca` for the current variable
-                bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
-            } else {
-                bx.dbg_var_addr(
-                    dbg_var,
-                    dbg_loc,
-                    base.llval,
-                    direct_offset,
-                    &indirect_offsets,
-                    None,
-                );
-            }
+            self.debug_introduce_local_as_var(bx, local, base, var);
         }
     }
 
+    fn debug_introduce_local_as_var(
+        &self,
+        bx: &mut Bx,
+        local: mir::Local,
+        mut base: PlaceRef<'tcx, Bx::Value>,
+        var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
+    ) {
+        let Some(dbg_var) = var.dbg_var else { return };
+        let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
+
+        let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
+            calculate_debuginfo_offset(bx, local, &var, base.layout);
+        let mut indirect_offsets = &indirect_offsets[..];
+
+        // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
+        // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
+        // not DWARF and LLVM doesn't support translating the resulting
+        // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
+        // Creating extra allocas on the stack makes the resulting debug info simple enough
+        // that LLVM can generate correct CodeView records and thus the values appear in the
+        // debugger. (#83709)
+        let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
+            && self.mir.local_kind(local) == mir::LocalKind::Arg
+            // LLVM can handle simple things but anything more complex than just a direct
+            // offset or one indirect offset of 0 is too complex for it to generate CV records
+            // correctly.
+            && (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
+
+        let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
+            // Create a variable which will be a pointer to the actual value
+            let ptr_ty = bx
+                .tcx()
+                .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
+            let ptr_layout = bx.layout_of(ptr_ty);
+            let alloca = PlaceRef::alloca(bx, ptr_layout);
+            bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
+
+            // Write the pointer to the variable
+            bx.store(place.llval, alloca.llval, alloca.align);
+
+            // Point the debug info to `*alloca` for the current variable
+            alloca
+        };
+
+        if var.references > 0 {
+            base = calculate_debuginfo_offset(bx, local, &var, base).result;
+
+            // Point the debug info to `&...&base == alloca` for the current variable
+            for refcount in 0..var.references {
+                base = create_alloca(bx, base, refcount);
+            }
+
+            direct_offset = Size::ZERO;
+            indirect_offsets = &[];
+        } else if should_create_individual_allocas {
+            let place = calculate_debuginfo_offset(bx, local, &var, base).result;
+
+            // Point the debug info to `*alloca` for the current variable
+            base = create_alloca(bx, place, 0);
+            direct_offset = Size::ZERO;
+            indirect_offsets = &[Size::ZERO];
+        }
+
+        bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
+    }
+
     pub fn debug_introduce_locals(&self, bx: &mut Bx) {
         if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
             for local in self.locals.indices() {
@@ -439,7 +484,7 @@
             };
 
             let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
-                let (var_ty, var_kind) = match var.value {
+                let (mut var_ty, var_kind) = match var.value {
                     mir::VarDebugInfoContents::Place(place) => {
                         let var_ty = self.monomorphized_place_ty(place.as_ref());
                         let var_kind = if let Some(arg_index) = var.argument_index
@@ -476,6 +521,11 @@
                     }
                 };
 
+                for _ in 0..var.references {
+                    var_ty =
+                        bx.tcx().mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty });
+                }
+
                 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
             });
 
@@ -487,6 +537,7 @@
                         dbg_var,
                         fragment: None,
                         projection: place.projection,
+                        references: var.references,
                     });
                 }
                 mir::VarDebugInfoContents::Const(c) => {
@@ -540,6 +591,7 @@
                                 Some(fragment_start..fragment_start + fragment_layout.size)
                             },
                             projection: place.projection,
+                            references: var.references,
                         });
                     }
                 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 9efbb34..2301c3e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -402,8 +402,6 @@
         indirect_dest: PlaceRef<'tcx, V>,
     ) {
         debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest);
-        let flags = MemFlags::empty();
-
         // `indirect_dest` must have `*mut T` type. We extract `T` out of it.
         let unsized_ty = indirect_dest
             .layout
@@ -416,17 +414,23 @@
             bug!("store_unsized called with a sized value")
         };
 
-        // FIXME: choose an appropriate alignment, or use dynamic align somehow
-        let max_align = Align::from_bits(128).unwrap();
-        let min_align = Align::from_bits(8).unwrap();
-
-        // Allocate an appropriate region on the stack, and copy the value into it
-        let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
-        let lldst = bx.byte_array_alloca(llsize, max_align);
-        bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags);
+        // Allocate an appropriate region on the stack, and copy the value into it. Since alloca
+        // doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
+        // pointer manually.
+        let (size, align) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
+        let one = bx.const_usize(1);
+        let align_minus_1 = bx.sub(align, one);
+        let size_extra = bx.add(size, align_minus_1);
+        let min_align = Align::ONE;
+        let alloca = bx.byte_array_alloca(size_extra, min_align);
+        let address = bx.ptrtoint(alloca, bx.type_isize());
+        let neg_address = bx.neg(address);
+        let offset = bx.and(neg_address, align_minus_1);
+        let dst = bx.inbounds_gep(bx.type_i8(), alloca, &[offset]);
+        bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty());
 
         // Store the allocated region and the extra to the indirect place.
-        let indirect_operand = OperandValue::Pair(lldst, llextra);
+        let indirect_operand = OperandValue::Pair(dst, llextra);
         indirect_operand.store(bx, indirect_dest);
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 1cfc4b9..c5976a6 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -8,7 +8,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
@@ -173,16 +173,13 @@
     ("avx512dq", Some(sym::avx512_target_feature)),
     ("avx512er", Some(sym::avx512_target_feature)),
     ("avx512f", Some(sym::avx512_target_feature)),
-    ("avx512gfni", Some(sym::avx512_target_feature)),
     ("avx512ifma", Some(sym::avx512_target_feature)),
     ("avx512pf", Some(sym::avx512_target_feature)),
-    ("avx512vaes", Some(sym::avx512_target_feature)),
     ("avx512vbmi", Some(sym::avx512_target_feature)),
     ("avx512vbmi2", Some(sym::avx512_target_feature)),
     ("avx512vl", Some(sym::avx512_target_feature)),
     ("avx512vnni", Some(sym::avx512_target_feature)),
     ("avx512vp2intersect", Some(sym::avx512_target_feature)),
-    ("avx512vpclmulqdq", Some(sym::avx512_target_feature)),
     ("avx512vpopcntdq", Some(sym::avx512_target_feature)),
     ("bmi1", None),
     ("bmi2", None),
@@ -253,6 +250,7 @@
     ("f", Some(sym::riscv_target_feature)),
     ("m", Some(sym::riscv_target_feature)),
     ("relax", Some(sym::riscv_target_feature)),
+    ("unaligned-scalar-mem", Some(sym::riscv_target_feature)),
     ("v", Some(sym::riscv_target_feature)),
     ("zba", Some(sym::riscv_target_feature)),
     ("zbb", Some(sym::riscv_target_feature)),
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 64bebe5..d83bfc7 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -1,3 +1,5 @@
+use std::any::Any;
+
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
 use crate::back::write::TargetMachineFactoryFn;
@@ -5,11 +7,12 @@
 
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_errors::ErrorGuaranteed;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_session::{
     config::{self, OutputFilenames, PrintRequest},
@@ -20,10 +23,6 @@
 use rustc_target::abi::call::FnAbi;
 use rustc_target::spec::Target;
 
-pub use rustc_data_structures::sync::MetadataRef;
-
-use std::any::Any;
-
 pub trait BackendTypes {
     type Value: CodegenObject;
     type Function: CodegenObject;
@@ -117,7 +116,9 @@
     ) -> Result<(), ErrorGuaranteed>;
 }
 
-pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync {
+pub trait ExtraBackendMethods:
+    CodegenBackend + WriteBackendMethods + Sized + Send + Sync + DynSend + DynSync
+{
     fn codegen_allocator<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index f6751df..7d56cf0 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -1,10 +1,36 @@
-const_eval_unstable_in_stable =
-    const-stable function cannot use `#[feature({$gate})]`
-    .unstable_sugg = if it is not part of the public API, make this function unstably const
-    .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
+const_eval_interior_mutability_borrow =
+    cannot borrow here, since the borrowed element may contain interior mutability
 
-const_eval_thread_local_access =
-    thread-local statics cannot be accessed at compile-time
+const_eval_interior_mutable_data_refer =
+    {$kind}s cannot refer to interior mutable data
+    .label = this borrow of an interior mutable value may end up in the final value
+    .help = to fix this, the value can be extracted to a separate `static` item and then referenced
+    .teach_note =
+        A constant containing interior mutable data behind a reference can allow you to modify that data.
+        This would make multiple uses of a constant to be able to see different values and allow circumventing
+        the `Send` and `Sync` requirements for shared mutable data, which is unsound.
+
+const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
+
+const_eval_mut_deref =
+    mutation through a reference is not allowed in {$kind}s
+
+const_eval_non_const_fmt_macro_call =
+    cannot call non-const formatting macro in {$kind}s
+
+const_eval_non_const_fn_call =
+    cannot call non-const fn `{$def_path_str}` in {$kind}s
+
+const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
+
+const_eval_raw_ptr_comparison =
+    pointers cannot be reliably compared during const eval
+    .note = see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+
+const_eval_raw_ptr_to_int =
+    pointers cannot be cast to integers during const eval
+    .note = at compile-time, pointers do not have an integer value
+    .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 const_eval_static_access =
     {$kind}s cannot refer to statics
@@ -12,29 +38,23 @@
     .teach_note = `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.
     .teach_help = To fix this, the value can be extracted to a `const` and then used.
 
-const_eval_raw_ptr_to_int =
-    pointers cannot be cast to integers during const eval
-    .note = at compile-time, pointers do not have an integer value
-    .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-
-const_eval_raw_ptr_comparison =
-    pointers cannot be reliably compared during const eval
-    .note = see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
-
-const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
-
-const_eval_mut_deref =
-    mutation through a reference is not allowed in {$kind}s
+const_eval_thread_local_access =
+    thread-local statics cannot be accessed at compile-time
 
 const_eval_transient_mut_borrow = mutable references are not allowed in {$kind}s
 
 const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {$kind}s
 
-const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
-
 const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {$kind}s
 
-const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
+const_eval_unallowed_heap_allocations =
+    allocations are not allowed in {$kind}s
+    .label = allocation not allowed in {$kind}s
+    .teach_note =
+        The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
+
+const_eval_unallowed_inline_asm =
+    inline assembly is not allowed in {$kind}s
 
 const_eval_unallowed_mutable_refs =
     mutable references are not allowed in the final value of {$kind}s
@@ -60,32 +80,12 @@
 
         If you really want global mutable state, try using static mut or a global UnsafeCell.
 
-const_eval_non_const_fmt_macro_call =
-    cannot call non-const formatting macro in {$kind}s
-
-const_eval_non_const_fn_call =
-    cannot call non-const fn `{$def_path_str}` in {$kind}s
-
 const_eval_unallowed_op_in_const_context =
     {$msg}
 
-const_eval_unallowed_heap_allocations =
-    allocations are not allowed in {$kind}s
-    .label = allocation not allowed in {$kind}s
-    .teach_note =
-        The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
+const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
 
-const_eval_unallowed_inline_asm =
-    inline assembly is not allowed in {$kind}s
-
-const_eval_interior_mutable_data_refer =
-    {$kind}s cannot refer to interior mutable data
-    .label = this borrow of an interior mutable value may end up in the final value
-    .help = to fix this, the value can be extracted to a separate `static` item and then referenced
-    .teach_note =
-        A constant containing interior mutable data behind a reference can allow you to modify that data.
-        This would make multiple uses of a constant to be able to see different values and allow circumventing
-        the `Send` and `Sync` requirements for shared mutable data, which is unsound.
-
-const_eval_interior_mutability_borrow =
-    cannot borrow here, since the borrowed element may contain interior mutability
+const_eval_unstable_in_stable =
+    const-stable function cannot use `#[feature({$gate})]`
+    .unstable_sugg = if it is not part of the public API, make this function unstably const
+    .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index cdef3fb..c591ff7 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -3,7 +3,8 @@
 
 use rustc_errors::Diagnostic;
 use rustc_middle::mir::AssertKind;
-use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt};
+use rustc_middle::query::TyCtxtAt;
+use rustc_middle::ty::{layout::LayoutError, ConstInt};
 use rustc_span::{Span, Symbol};
 
 use super::InterpCx;
@@ -169,14 +170,14 @@
                 // See <https://github.com/rust-lang/rust/pull/63152>.
                 let mut err = struct_error(tcx, &self.error.to_string());
                 self.decorate(&mut err, decorate);
-                ErrorHandled::Reported(err.emit())
+                ErrorHandled::Reported(err.emit().into())
             }
             _ => {
                 // Report as hard error.
                 let mut err = struct_error(tcx, message);
                 err.span_label(self.span, self.error.to_string());
                 self.decorate(&mut err, decorate);
-                ErrorHandled::Reported(err.emit())
+                ErrorHandled::Reported(err.emit().into())
             }
         }
     }
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 088a824..fa8253d 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -2,7 +2,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::Symbol;
 
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 814b67b..58b5755 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -382,7 +382,7 @@
                         rustc_span::DUMMY_SP,
                         "This is likely a const item that is missing from its impl",
                     );
-                    throw_inval!(AlreadyReported(guar));
+                    throw_inval!(AlreadyReported(guar.into()));
                 } else {
                     // `find_mir_or_eval_fn` checks that this is a const fn before even calling us,
                     // so this should be unreachable.
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index b2197a0..7e94578 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -7,14 +7,13 @@
 use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
 use rustc_index::IndexVec;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{ErrorHandled, InterpError};
+use rustc_middle::mir::interpret::{ErrorHandled, InterpError, ReportedErrorInfo};
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
     TyAndLayout,
 };
-use rustc_middle::ty::{
-    self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
-};
+use rustc_middle::ty::{self, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
 use rustc_span::Span;
@@ -470,7 +469,7 @@
         };
         // do not continue if typeck errors occurred (can only occur in local crate)
         if let Some(err) = body.tainted_by_errors {
-            throw_inval!(AlreadyReported(err));
+            throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err)));
         }
         Ok(body)
     }
@@ -517,7 +516,7 @@
             Ok(None) => throw_inval!(TooGeneric),
 
             // FIXME(eddyb) this could be a bit more specific than `AlreadyReported`.
-            Err(error_reported) => throw_inval!(AlreadyReported(error_reported)),
+            Err(error_reported) => throw_inval!(AlreadyReported(error_reported.into())),
         }
     }
 
@@ -905,7 +904,7 @@
         query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| {
             match err {
                 ErrorHandled::Reported(err) => {
-                    if let Some(span) = span {
+                    if !err.is_tainted_by_errors() && let Some(span) = span {
                         // To make it easier to figure out where this error comes from, also add a note at the current location.
                         self.tcx.sess.span_note_without_error(span, "erroneous constant used");
                     }
@@ -950,7 +949,20 @@
         // This deliberately does *not* honor `requires_caller_location` since it is used for much
         // more than just panics.
         for frame in stack.iter().rev() {
-            let span = frame.current_span();
+            let span = match frame.loc {
+                Left(loc) => {
+                    // If the stacktrace passes through MIR-inlined source scopes, add them.
+                    let mir::SourceInfo { mut span, scope } = *frame.body.source_info(loc);
+                    let mut scope_data = &frame.body.source_scopes[scope];
+                    while let Some((instance, call_span)) = scope_data.inlined {
+                        frames.push(FrameInfo { span, instance });
+                        span = call_span;
+                        scope_data = &frame.body.source_scopes[scope_data.parent_scope.unwrap()];
+                    }
+                    span
+                }
+                Right(span) => span,
+            };
             frames.push(FrameInfo { span, instance: frame.instance });
         }
         trace!("generate stacktrace: {:#?}", frames);
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index 3701eb9..df5b581 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -111,11 +111,7 @@
         location
     }
 
-    pub(crate) fn location_triple_for_span(&self, mut span: Span) -> (Symbol, u32, u32) {
-        // Remove `Inlined` marks as they pollute `expansion_cause`.
-        while span.is_inlined() {
-            span.remove_mark();
-        }
+    pub(crate) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
         let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
         let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
         (
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index a7f6607..e30af165 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -595,7 +595,7 @@
             // FIXME(generic_const_exprs): `ConstKind::Expr` should be able to be evaluated
             ty::ConstKind::Expr(_) => throw_inval!(TooGeneric),
             ty::ConstKind::Error(reported) => {
-                throw_inval!(AlreadyReported(reported))
+                throw_inval!(AlreadyReported(reported.into()))
             }
             ty::ConstKind::Unevaluated(uv) => {
                 let instance = self.resolve(uv.def, uv.substs)?;
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 1b66eca..c36282d 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -35,8 +35,8 @@
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
+use rustc_middle::query::Providers;
 use rustc_middle::ty;
-use rustc_middle::ty::query::Providers;
 
 fluent_messages! { "../messages.ftl" }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 696c451..138bc3e 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -944,7 +944,7 @@
                         tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate)
                     };
                     let feature_gate_declared = gate_declared(gate);
-                    let implied_gate_declared = implied_by.map(gate_declared).unwrap_or(false);
+                    let implied_gate_declared = implied_by.is_some_and(gate_declared);
                     if !feature_gate_declared && !implied_gate_declared {
                         self.check_op(ops::FnCallUnstable(callee, Some(gate)));
                         return;
@@ -971,7 +971,7 @@
                 // have no `rustc_const_stable` attributes to be const-unstable as well. This
                 // should be fixed later.
                 let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none()
-                    && tcx.lookup_stability(callee).map_or(false, |s| s.is_unstable());
+                    && tcx.lookup_stability(callee).is_some_and(|s| s.is_unstable());
                 if callee_is_unstable_unmarked {
                     trace!("callee_is_unstable_unmarked");
                     // We do not use `const` modifiers for intrinsic "functions", as intrinsics are
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index 0e45019..8ebfee8 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -139,5 +139,5 @@
         return false;
     }
 
-    tcx.lookup_const_stability(parent.owner).map_or(false, |stab| stab.is_const_stable())
+    tcx.lookup_const_stability(parent.owner).is_some_and(|stab| stab.is_const_stable())
 }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index f46c2d0..3c350e2 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -164,7 +164,7 @@
                 if let Some(root) = post_contract_node.get(&bb) {
                     break *root;
                 }
-                let parent = doms.immediate_dominator(bb);
+                let parent = doms.immediate_dominator(bb).unwrap();
                 dom_path.push(bb);
                 if !self.body.basic_blocks[parent].is_cleanup {
                     break bb;
@@ -448,7 +448,15 @@
         };
         match debuginfo.value {
             VarDebugInfoContents::Const(_) => {}
-            VarDebugInfoContents::Place(place) => check_place(place),
+            VarDebugInfoContents::Place(place) => {
+                check_place(place);
+                if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
+                    self.fail(
+                        START_BLOCK.start_location(),
+                        format!("debuginfo {:?}, has both ref and deref", debuginfo),
+                    );
+                }
+            }
             VarDebugInfoContents::Composite { ty, ref fragments } => {
                 for f in fragments {
                     check_place(f.contents);
diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs
index f5f3d5d..d6a2ffb 100644
--- a/compiler/rustc_const_eval/src/util/compare_types.rs
+++ b/compiler/rustc_const_eval/src/util/compare_types.rs
@@ -3,8 +3,8 @@
 //! FIXME: Move this to a more general place. The utility of this extends to
 //! other areas of the compiler as well.
 
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCause;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::traits::{DefiningAnchor, ObligationCause};
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_trait_selection::traits::ObligationCtxt;
 
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 4e80a28..11ad5b4 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -58,11 +58,12 @@
             // Types with identity (print the module path).
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
 
+            ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
             ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
             ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"),
         }
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index c815bb2..78f73d1 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -16,6 +16,7 @@
 measureme = "10.0.0"
 rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc-rayon = { version = "0.5.0", optional = true }
+rustc_arena = { path = "../rustc_arena" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 rustc-hash = "1.1.0"
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index e76bdac..a5db14d 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -26,7 +26,7 @@
     struct PreorderIndex {}
 }
 
-pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
+pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
     // compute the post order index (rank) for each node
     let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes());
 
@@ -109,28 +109,27 @@
         // they have been placed in the bucket.
         //
         // We compute a partial set of immediate dominators here.
-        let z = parent[w];
-        for &v in bucket[z].iter() {
+        for &v in bucket[w].iter() {
             // This uses the result of Lemma 5 from section 2 from the original
             // 1979 paper, to compute either the immediate or relative dominator
             // for a given vertex v.
             //
             // eval returns a vertex y, for which semi[y] is minimum among
-            // vertices semi[v] +> y *> v. Note that semi[v] = z as we're in the
-            // z bucket.
+            // vertices semi[v] +> y *> v. Note that semi[v] = w as we're in the
+            // w bucket.
             //
             // Given such a vertex y, semi[y] <= semi[v] and idom[y] = idom[v].
             // If semi[y] = semi[v], though, idom[v] = semi[v].
             //
             // Using this, we can either set idom[v] to be:
-            //  * semi[v] (i.e. z), if semi[y] is z
+            //  * semi[v] (i.e. w), if semi[y] is w
             //  * idom[y], otherwise
             //
             // We don't directly set to idom[y] though as it's not necessarily
             // known yet. The second preorder traversal will cleanup by updating
             // the idom for any that were missed in this pass.
             let y = eval(&mut parent, lastlinked, &semi, &mut label, v);
-            idom[v] = if semi[y] < z { y } else { z };
+            idom[v] = if semi[y] < w { y } else { w };
         }
 
         // This loop computes the semi[w] for w.
@@ -213,10 +212,11 @@
         // If we don't yet know the idom directly, then push this vertex into
         // our semidominator's bucket, where it will get processed at a later
         // stage to compute its immediate dominator.
-        if parent[w] != semi[w] {
+        let z = parent[w];
+        if z != semi[w] {
             bucket[semi[w]].push(w);
         } else {
-            idom[w] = parent[w];
+            idom[w] = z;
         }
 
         // Optimization: We share the parent array between processed and not
@@ -242,7 +242,12 @@
         immediate_dominators[*node] = Some(pre_order_to_real[idom[idx]]);
     }
 
-    Dominators { post_order_rank, immediate_dominators }
+    let start_node = graph.start_node();
+    immediate_dominators[start_node] = None;
+
+    let time = compute_access_time(start_node, &immediate_dominators);
+
+    Dominators { start_node, post_order_rank, immediate_dominators, time }
 }
 
 /// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -308,34 +313,31 @@
 /// Tracks the list of dominators for each node.
 #[derive(Clone, Debug)]
 pub struct Dominators<N: Idx> {
+    start_node: N,
     post_order_rank: IndexVec<N, usize>,
     // Even though we track only the immediate dominator of each node, it's
     // possible to get its full list of dominators by looking up the dominator
     // of each dominator. (See the `impl Iterator for Iter` definition).
     immediate_dominators: IndexVec<N, Option<N>>,
+    time: IndexVec<N, Time>,
 }
 
 impl<Node: Idx> Dominators<Node> {
-    /// Whether the given Node has an immediate dominator.
+    /// Returns true if node is reachable from the start node.
     pub fn is_reachable(&self, node: Node) -> bool {
-        self.immediate_dominators[node].is_some()
+        node == self.start_node || self.immediate_dominators[node].is_some()
     }
 
-    pub fn immediate_dominator(&self, node: Node) -> Node {
-        assert!(self.is_reachable(node), "node {node:?} is not reachable");
-        self.immediate_dominators[node].unwrap()
+    /// Returns the immediate dominator of node, if any.
+    pub fn immediate_dominator(&self, node: Node) -> Option<Node> {
+        self.immediate_dominators[node]
     }
 
     /// Provides an iterator over each dominator up the CFG, for the given Node.
     /// See the `impl Iterator for Iter` definition to understand how this works.
     pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
         assert!(self.is_reachable(node), "node {node:?} is not reachable");
-        Iter { dominators: self, node: Some(node) }
-    }
-
-    pub fn dominates(&self, dom: Node, node: Node) -> bool {
-        // FIXME -- could be optimized by using post-order-rank
-        self.dominators(node).any(|n| n == dom)
+        Iter { dom_tree: self, node: Some(node) }
     }
 
     /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
@@ -345,10 +347,22 @@
     pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> {
         self.post_order_rank[rhs].partial_cmp(&self.post_order_rank[lhs])
     }
+
+    /// Returns true if `a` dominates `b`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `b` is unreachable.
+    pub fn dominates(&self, a: Node, b: Node) -> bool {
+        let a = self.time[a];
+        let b = self.time[b];
+        assert!(b.start != 0, "node {b:?} is not reachable");
+        a.start <= b.start && b.finish <= a.finish
+    }
 }
 
 pub struct Iter<'dom, Node: Idx> {
-    dominators: &'dom Dominators<Node>,
+    dom_tree: &'dom Dominators<Node>,
     node: Option<Node>,
 }
 
@@ -357,15 +371,74 @@
 
     fn next(&mut self) -> Option<Self::Item> {
         if let Some(node) = self.node {
-            let dom = self.dominators.immediate_dominator(node);
-            if dom == node {
-                self.node = None; // reached the root
-            } else {
-                self.node = Some(dom);
-            }
+            self.node = self.dom_tree.immediate_dominator(node);
             Some(node)
         } else {
             None
         }
     }
 }
+
+/// Describes the number of vertices discovered at the time when processing of a particular vertex
+/// started and when it finished. Both values are zero for unreachable vertices.
+#[derive(Copy, Clone, Default, Debug)]
+struct Time {
+    start: u32,
+    finish: u32,
+}
+
+fn compute_access_time<N: Idx>(
+    start_node: N,
+    immediate_dominators: &IndexSlice<N, Option<N>>,
+) -> IndexVec<N, Time> {
+    // Transpose the dominator tree edges, so that child nodes of vertex v are stored in
+    // node[edges[v].start..edges[v].end].
+    let mut edges: IndexVec<N, std::ops::Range<u32>> =
+        IndexVec::from_elem(0..0, immediate_dominators);
+    for &idom in immediate_dominators.iter() {
+        if let Some(idom) = idom {
+            edges[idom].end += 1;
+        }
+    }
+    let mut m = 0;
+    for e in edges.iter_mut() {
+        m += e.end;
+        e.start = m;
+        e.end = m;
+    }
+    let mut node = IndexVec::from_elem_n(Idx::new(0), m.try_into().unwrap());
+    for (i, &idom) in immediate_dominators.iter_enumerated() {
+        if let Some(idom) = idom {
+            edges[idom].start -= 1;
+            node[edges[idom].start] = i;
+        }
+    }
+
+    // Perform a depth-first search of the dominator tree. Record the number of vertices discovered
+    // when vertex v is discovered first as time[v].start, and when its processing is finished as
+    // time[v].finish.
+    let mut time: IndexVec<N, Time> = IndexVec::from_elem(Time::default(), immediate_dominators);
+    let mut stack = Vec::new();
+
+    let mut discovered = 1;
+    stack.push(start_node);
+    time[start_node].start = discovered;
+
+    while let Some(&i) = stack.last() {
+        let e = &mut edges[i];
+        if e.start == e.end {
+            // Finish processing vertex i.
+            time[i].finish = discovered;
+            stack.pop();
+        } else {
+            let j = node[e.start];
+            e.start += 1;
+            // Start processing vertex j.
+            discovered += 1;
+            time[j].start = discovered;
+            stack.push(j);
+        }
+    }
+
+    time
+}
diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
index ff31d8f..5472bb8 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
@@ -8,7 +8,7 @@
 
     let dominators = dominators(&graph);
     let immediate_dominators = &dominators.immediate_dominators;
-    assert_eq!(immediate_dominators[0], Some(0));
+    assert_eq!(immediate_dominators[0], None);
     assert_eq!(immediate_dominators[1], Some(0));
     assert_eq!(immediate_dominators[2], Some(0));
     assert_eq!(immediate_dominators[3], Some(0));
@@ -30,7 +30,7 @@
     assert_eq!(immediate_dominators[3], Some(6));
     assert_eq!(immediate_dominators[4], Some(6));
     assert_eq!(immediate_dominators[5], Some(6));
-    assert_eq!(immediate_dominators[6], Some(6));
+    assert_eq!(immediate_dominators[6], None);
 }
 
 #[test]
@@ -43,3 +43,40 @@
 
     dominators(&graph);
 }
+
+#[test]
+fn immediate_dominator() {
+    let graph = TestGraph::new(1, &[(1, 2), (2, 3)]);
+    let dominators = dominators(&graph);
+    assert_eq!(dominators.immediate_dominator(0), None);
+    assert_eq!(dominators.immediate_dominator(1), None);
+    assert_eq!(dominators.immediate_dominator(2), Some(1));
+    assert_eq!(dominators.immediate_dominator(3), Some(2));
+}
+
+#[test]
+fn transitive_dominator() {
+    let graph = TestGraph::new(
+        0,
+        &[
+            // First tree branch.
+            (0, 1),
+            (1, 2),
+            (2, 3),
+            (3, 4),
+            // Second tree branch.
+            (1, 5),
+            (5, 6),
+            // Third tree branch.
+            (0, 7),
+            // These links make 0 the dominator for 2 and 3.
+            (7, 2),
+            (5, 3),
+        ],
+    );
+
+    let dom_tree = dominators(&graph);
+    let immediate_dominators = &dom_tree.immediate_dominators;
+    assert_eq!(immediate_dominators[2], Some(0));
+    assert_eq!(immediate_dominators[3], Some(0)); // This used to return Some(1).
+}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 004017e..859e384 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -26,6 +26,7 @@
 #![feature(test)]
 #![feature(thread_id_value)]
 #![feature(vec_into_raw_parts)]
+#![feature(allocator_api)]
 #![feature(get_mut_unchecked)]
 #![feature(lint_reasons)]
 #![feature(unwrap_infallible)]
@@ -77,6 +78,7 @@
 pub mod stable_hasher;
 mod atomic_ref;
 pub mod fingerprint;
+pub mod marker;
 pub mod profiling;
 pub mod sharded;
 pub mod stack;
@@ -100,21 +102,27 @@
 pub use ena::undo_log;
 pub use ena::unify;
 
-pub struct OnDrop<F: Fn()>(pub F);
+/// Returns a structure that calls `f` when dropped.
+pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
+    OnDrop(Some(f))
+}
 
-impl<F: Fn()> OnDrop<F> {
-    /// Forgets the function which prevents it from running.
-    /// Ensure that the function owns no memory, otherwise it will be leaked.
+pub struct OnDrop<F: FnOnce()>(Option<F>);
+
+impl<F: FnOnce()> OnDrop<F> {
+    /// Disables on-drop call.
     #[inline]
-    pub fn disable(self) {
-        std::mem::forget(self);
+    pub fn disable(mut self) {
+        self.0.take();
     }
 }
 
-impl<F: Fn()> Drop for OnDrop<F> {
+impl<F: FnOnce()> Drop for OnDrop<F> {
     #[inline]
     fn drop(&mut self) {
-        (self.0)();
+        if let Some(f) = self.0.take() {
+            f();
+        }
     }
 }
 
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
new file mode 100644
index 0000000..f8c06f9
--- /dev/null
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -0,0 +1,257 @@
+cfg_if!(
+    if #[cfg(not(parallel_compiler))] {
+        pub auto trait DynSend {}
+        pub auto trait DynSync {}
+
+        impl<T> DynSend for T {}
+        impl<T> DynSync for T {}
+    } else {
+        #[rustc_on_unimplemented(
+            message = "`{Self}` doesn't implement `DynSend`. \
+            Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`"
+        )]
+        // This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
+        // is true. These types can be wrapped in a `FromDyn` to get a `Send` type. Wrapping a
+        // `Send` type in `IntoDynSyncSend` will create a `DynSend` type.
+        pub unsafe auto trait DynSend {}
+
+        #[rustc_on_unimplemented(
+            message = "`{Self}` doesn't implement `DynSync`. \
+            Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Sync`"
+        )]
+        // This is an auto trait for types which can be shared across threads if `sync::is_dyn_thread_safe()`
+        // is true. These types can be wrapped in a `FromDyn` to get a `Sync` type. Wrapping a
+        // `Sync` type in `IntoDynSyncSend` will create a `DynSync` type.
+        pub unsafe auto trait DynSync {}
+
+        // Same with `Sync` and `Send`.
+        unsafe impl<T: DynSync + ?Sized> DynSend for &T {}
+
+        macro_rules! impls_dyn_send_neg {
+            ($([$t1: ty $(where $($generics1: tt)*)?])*) => {
+                $(impl$(<$($generics1)*>)? !DynSend for $t1 {})*
+            };
+        }
+
+        // Consistent with `std`
+        impls_dyn_send_neg!(
+            [std::env::Args]
+            [std::env::ArgsOs]
+            [*const T where T: ?Sized]
+            [*mut T where T: ?Sized]
+            [std::ptr::NonNull<T> where T: ?Sized]
+            [std::rc::Rc<T> where T: ?Sized]
+            [std::rc::Weak<T> where T: ?Sized]
+            [std::sync::MutexGuard<'_, T> where T: ?Sized]
+            [std::sync::RwLockReadGuard<'_, T> where T: ?Sized]
+            [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized]
+            [std::io::StdoutLock<'_>]
+            [std::io::StderrLock<'_>]
+        );
+        cfg_if!(
+            // Consistent with `std`
+            // `os_imp::Env` is `!Send` in these platforms
+            if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
+                impl !DynSend for std::env::VarsOs {}
+            }
+        );
+
+        macro_rules! already_send {
+            ($([$ty: ty])*) => {
+                $(unsafe impl DynSend for $ty where $ty: Send {})*
+            };
+        }
+
+        // These structures are already `Send`.
+        already_send!(
+            [std::backtrace::Backtrace]
+            [std::io::Stdout]
+            [std::io::Stderr]
+            [std::io::Error]
+            [std::fs::File]
+            [rustc_arena::DroplessArena]
+            [crate::memmap::Mmap]
+            [crate::profiling::SelfProfiler]
+            [crate::owned_slice::OwnedSlice]
+        );
+
+        macro_rules! impl_dyn_send {
+            ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => {
+                $(unsafe impl<$($generics2)*> DynSend for $ty {})*
+            };
+        }
+
+        impl_dyn_send!(
+            [std::sync::atomic::AtomicPtr<T> where T]
+            [std::sync::Mutex<T> where T: ?Sized+ DynSend]
+            [std::sync::mpsc::Sender<T> where T: DynSend]
+            [std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
+            [std::sync::LazyLock<T, F> where T: DynSend, F: DynSend]
+            [std::collections::HashSet<K, S> where K: DynSend, S: DynSend]
+            [std::collections::HashMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
+            [std::collections::BTreeMap<K, V, A> where K: DynSend, V: DynSend, A: std::alloc::Allocator + Clone + DynSend]
+            [Vec<T, A> where T: DynSend, A: std::alloc::Allocator + DynSend]
+            [Box<T, A> where T: ?Sized + DynSend, A: std::alloc::Allocator + DynSend]
+            [crate::sync::Lock<T> where T: DynSend]
+            [crate::sync::RwLock<T> where T: DynSend]
+            [crate::tagged_ptr::CopyTaggedPtr<P, T, CP> where P: Send + crate::tagged_ptr::Pointer, T: Send + crate::tagged_ptr::Tag, const CP: bool]
+            [rustc_arena::TypedArena<T> where T: DynSend]
+            [indexmap::IndexSet<V, S> where V: DynSend, S: DynSend]
+            [indexmap::IndexMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
+            [thin_vec::ThinVec<T> where T: DynSend]
+            [smallvec::SmallVec<A> where A: smallvec::Array + DynSend]
+        );
+
+        macro_rules! impls_dyn_sync_neg {
+            ($([$t1: ty $(where $($generics1: tt)*)?])*) => {
+                $(impl$(<$($generics1)*>)? !DynSync for $t1 {})*
+            };
+        }
+
+        // Consistent with `std`
+        impls_dyn_sync_neg!(
+            [std::env::Args]
+            [std::env::ArgsOs]
+            [*const T where T: ?Sized]
+            [*mut T where T: ?Sized]
+            [std::cell::Cell<T> where T: ?Sized]
+            [std::cell::RefCell<T> where T: ?Sized]
+            [std::cell::UnsafeCell<T> where T: ?Sized]
+            [std::ptr::NonNull<T> where T: ?Sized]
+            [std::rc::Rc<T> where T: ?Sized]
+            [std::rc::Weak<T> where T: ?Sized]
+            [std::cell::OnceCell<T> where T]
+            [std::sync::mpsc::Receiver<T> where T]
+            [std::sync::mpsc::Sender<T> where T]
+        );
+        cfg_if!(
+            // Consistent with `std`
+            // `os_imp::Env` is `!Sync` in these platforms
+            if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
+                impl !DynSync for std::env::VarsOs {}
+            }
+        );
+
+        macro_rules! already_sync {
+            ($([$ty: ty])*) => {
+                $(unsafe impl DynSync for $ty where $ty: Sync {})*
+            };
+        }
+
+        // These structures are already `Sync`.
+        already_sync!(
+            [std::sync::atomic::AtomicBool]
+            [std::sync::atomic::AtomicUsize]
+            [std::sync::atomic::AtomicU8]
+            [std::sync::atomic::AtomicU32]
+            [std::sync::atomic::AtomicU64]
+            [std::backtrace::Backtrace]
+            [std::io::Error]
+            [std::fs::File]
+            [jobserver_crate::Client]
+            [crate::memmap::Mmap]
+            [crate::profiling::SelfProfiler]
+            [crate::owned_slice::OwnedSlice]
+        );
+
+        macro_rules! impl_dyn_sync {
+            ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => {
+                $(unsafe impl<$($generics2)*> DynSync for $ty {})*
+            };
+        }
+
+        impl_dyn_sync!(
+            [std::sync::atomic::AtomicPtr<T> where T]
+            [std::sync::OnceLock<T> where T: DynSend + DynSync]
+            [std::sync::Mutex<T> where T: ?Sized + DynSend]
+            [std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
+            [std::sync::LazyLock<T, F> where T: DynSend + DynSync, F: DynSend]
+            [std::collections::HashSet<K, S> where K: DynSync, S: DynSync]
+            [std::collections::HashMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
+            [std::collections::BTreeMap<K, V, A> where K: DynSync, V: DynSync, A: std::alloc::Allocator + Clone + DynSync]
+            [Vec<T, A> where T: DynSync, A: std::alloc::Allocator + DynSync]
+            [Box<T, A> where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync]
+            [crate::sync::Lock<T> where T: DynSend]
+            [crate::sync::RwLock<T> where T: DynSend + DynSync]
+            [crate::sync::OneThread<T> where T]
+            [crate::sync::WorkerLocal<T> where T: DynSend]
+            [crate::intern::Interned<'a, T> where 'a, T: DynSync]
+            [crate::tagged_ptr::CopyTaggedPtr<P, T, CP> where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool]
+            [parking_lot::lock_api::Mutex<R, T> where R: DynSync, T: ?Sized + DynSend]
+            [parking_lot::lock_api::RwLock<R, T> where R: DynSync, T: ?Sized + DynSend + DynSync]
+            [indexmap::IndexSet<V, S> where V: DynSync, S: DynSync]
+            [indexmap::IndexMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
+            [smallvec::SmallVec<A> where A: smallvec::Array + DynSync]
+            [thin_vec::ThinVec<T> where T: DynSync]
+        );
+    }
+);
+
+pub fn assert_dyn_sync<T: ?Sized + DynSync>() {}
+pub fn assert_dyn_send<T: ?Sized + DynSend>() {}
+pub fn assert_dyn_send_val<T: ?Sized + DynSend>(_t: &T) {}
+pub fn assert_dyn_send_sync_val<T: ?Sized + DynSync + DynSend>(_t: &T) {}
+
+#[derive(Copy, Clone)]
+pub struct FromDyn<T>(T);
+
+impl<T> FromDyn<T> {
+    #[inline(always)]
+    pub fn from(val: T) -> Self {
+        // Check that `sync::is_dyn_thread_safe()` is true on creation so we can
+        // implement `Send` and `Sync` for this structure when `T`
+        // implements `DynSend` and `DynSync` respectively.
+        #[cfg(parallel_compiler)]
+        assert!(crate::sync::is_dyn_thread_safe());
+        FromDyn(val)
+    }
+
+    #[inline(always)]
+    pub fn into_inner(self) -> T {
+        self.0
+    }
+}
+
+// `FromDyn` is `Send` if `T` is `DynSend`, since it ensures that sync::is_dyn_thread_safe() is true.
+#[cfg(parallel_compiler)]
+unsafe impl<T: DynSend> Send for FromDyn<T> {}
+
+// `FromDyn` is `Sync` if `T` is `DynSync`, since it ensures that sync::is_dyn_thread_safe() is true.
+#[cfg(parallel_compiler)]
+unsafe impl<T: DynSync> Sync for FromDyn<T> {}
+
+impl<T> std::ops::Deref for FromDyn<T> {
+    type Target = T;
+
+    #[inline(always)]
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+// A wrapper to convert a struct that is already a `Send` or `Sync` into
+// an instance of `DynSend` and `DynSync`, since the compiler cannot infer
+// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
+#[derive(Copy, Clone)]
+pub struct IntoDynSyncSend<T: ?Sized>(pub T);
+
+#[cfg(parallel_compiler)]
+unsafe impl<T: ?Sized + Send> DynSend for IntoDynSyncSend<T> {}
+#[cfg(parallel_compiler)]
+unsafe impl<T: ?Sized + Sync> DynSync for IntoDynSyncSend<T> {}
+
+impl<T> std::ops::Deref for IntoDynSyncSend<T> {
+    type Target = T;
+
+    #[inline(always)]
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T> std::ops::DerefMut for IntoDynSyncSend<T> {
+    #[inline(always)]
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.0
+    }
+}
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 27a869e..a479086 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -366,7 +366,7 @@
                     && self
                         .error_cache
                         .get(&obligation_tree_id)
-                        .map_or(false, |errors| errors.contains(v.key()));
+                        .is_some_and(|errors| errors.contains(v.key()));
 
                 if already_failed {
                     Err(())
diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index 311a42a..cbb3047 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -1,5 +1,6 @@
 use std::{borrow::Borrow, ops::Deref};
 
+use crate::sync::Lrc;
 // Use our fake Send/Sync traits when on not parallel compiler,
 // so that `OwnedSlice` only implements/requires Send/Sync
 // for parallel compiler builds.
@@ -7,7 +8,7 @@
 
 /// An owned slice.
 ///
-/// This is similar to `Box<[u8]>` but allows slicing and using anything as the
+/// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
 /// backing buffer.
 ///
 /// See [`slice_owned`] for `OwnedSlice` construction and examples.
@@ -16,6 +17,7 @@
 ///
 /// This is essentially a replacement for `owning_ref` which is a lot simpler
 /// and even sound! 🌸
+#[derive(Clone)]
 pub struct OwnedSlice {
     /// This is conceptually a `&'self.owner [u8]`.
     bytes: *const [u8],
@@ -31,7 +33,7 @@
     //       \/
     //      ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
     #[expect(dead_code)]
-    owner: Box<dyn Send + Sync>,
+    owner: Lrc<dyn Send + Sync>,
 }
 
 /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@@ -72,10 +74,10 @@
     O: Send + Sync + 'static,
     F: FnOnce(&O) -> Result<&[u8], E>,
 {
-    // We box the owner of the bytes, so it doesn't move.
+    // We wrap the owner of the bytes in, so it doesn't move.
     //
     // Since the owner does not move and we don't access it in any way
-    // before drop, there is nothing that can invalidate the bytes pointer.
+    // before dropping, there is nothing that can invalidate the bytes pointer.
     //
     // Thus, "extending" the lifetime of the reference returned from `F` is fine.
     // We pretend that we pass it a reference that lives as long as the returned slice.
@@ -83,12 +85,39 @@
     // N.B. the HRTB on the `slicer` is important — without it the caller could provide
     // a short lived slice, unrelated to the owner.
 
-    let owner = Box::new(owner);
+    let owner = Lrc::new(owner);
     let bytes = slicer(&*owner)?;
 
     Ok(OwnedSlice { bytes, owner })
 }
 
+impl OwnedSlice {
+    /// Slice this slice by `slicer`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
+    /// let vec = vec![1, 2, 3, 4];
+    ///
+    /// // Identical to slicing via `&v[1..3]` but produces an owned slice
+    /// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
+    /// assert_eq!(&*slice, [1, 2, 3, 4]);
+    ///
+    /// let slice = slice.slice(|slice| &slice[1..][..2]);
+    /// assert_eq!(&*slice, [2, 3]);
+    /// ```
+    ///
+    pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
+        // This is basically identical to `try_slice_owned`,
+        // `slicer` can only return slices of its argument or some static data,
+        // both of which are valid while `owner` is alive.
+
+        let bytes = slicer(&self);
+        OwnedSlice { bytes, ..self }
+    }
+}
+
 impl Deref for OwnedSlice {
     type Target = [u8];
 
@@ -108,11 +137,11 @@
     }
 }
 
-// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Send`
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
 #[cfg(parallel_compiler)]
 unsafe impl Send for OwnedSlice {}
 
-// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Sync`
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
 #[cfg(parallel_compiler)]
 unsafe impl Sync for OwnedSlice {}
 
diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
index e715fb5..520871a 100644
--- a/compiler/rustc_data_structures/src/owned_slice/tests.rs
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -7,8 +7,8 @@
 };
 
 use crate::{
+    defer,
     owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
-    OnDrop,
 };
 
 #[test]
@@ -26,7 +26,7 @@
 }
 
 #[test]
-fn slice_the_slice() {
+fn slice_owned_the_slice() {
     let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
     let slice = slice_owned(slice, |s| &s[1..][..4]);
     let slice = slice_owned(slice, |s| s);
@@ -36,6 +36,16 @@
 }
 
 #[test]
+fn slice_the_slice() {
+    let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice)
+        .slice(|s| &s[1..][..4])
+        .slice(|s| s)
+        .slice(|s| &s[1..]);
+
+    assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
+}
+
+#[test]
 fn try_and_fail() {
     let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));
 
@@ -56,7 +66,7 @@
 fn drop_drops() {
     let flag = Arc::new(AtomicBool::new(false));
     let flag_prime = Arc::clone(&flag);
-    let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed));
+    let d = defer(move || flag_prime.store(true, atomic::Ordering::Relaxed));
 
     let slice = slice_owned(d, |_| &[]);
 
@@ -69,6 +79,6 @@
 
 #[test]
 fn send_sync() {
-    crate::sync::assert_send::<OwnedSlice>();
-    crate::sync::assert_sync::<OwnedSlice>();
+    crate::sync::assert_dyn_send::<OwnedSlice>();
+    crate::sync::assert_dyn_sync::<OwnedSlice>();
 }
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index e73ca56..6c3197d 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -39,7 +39,7 @@
 //!
 //! [^2] `MTLockRef` is a typedef.
 
-use crate::owned_slice::OwnedSlice;
+pub use crate::marker::*;
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
 use std::ops::{Deref, DerefMut};
@@ -55,6 +55,43 @@
 
 mod vec;
 
+mod mode {
+    use super::Ordering;
+    use std::sync::atomic::AtomicU8;
+
+    const UNINITIALIZED: u8 = 0;
+    const DYN_NOT_THREAD_SAFE: u8 = 1;
+    const DYN_THREAD_SAFE: u8 = 2;
+
+    static DYN_THREAD_SAFE_MODE: AtomicU8 = AtomicU8::new(UNINITIALIZED);
+
+    // Whether thread safety is enabled (due to running under multiple threads).
+    #[inline]
+    pub fn is_dyn_thread_safe() -> bool {
+        match DYN_THREAD_SAFE_MODE.load(Ordering::Relaxed) {
+            DYN_NOT_THREAD_SAFE => false,
+            DYN_THREAD_SAFE => true,
+            _ => panic!("uninitialized dyn_thread_safe mode!"),
+        }
+    }
+
+    // Only set by the `-Z threads` compile option
+    pub fn set_dyn_thread_safe_mode(mode: bool) {
+        let set: u8 = if mode { DYN_THREAD_SAFE } else { DYN_NOT_THREAD_SAFE };
+        let previous = DYN_THREAD_SAFE_MODE.compare_exchange(
+            UNINITIALIZED,
+            set,
+            Ordering::Relaxed,
+            Ordering::Relaxed,
+        );
+
+        // Check that the mode was either uninitialized or was already set to the requested mode.
+        assert!(previous.is_ok() || previous == Err(set));
+    }
+}
+
+pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
+
 cfg_if! {
     if #[cfg(not(parallel_compiler))] {
         pub unsafe auto trait Send {}
@@ -149,7 +186,7 @@
 
         #[macro_export]
         macro_rules! parallel {
-            ($($blocks:tt),*) => {
+            ($($blocks:block),*) => {
                 // We catch panics here ensuring that all the blocks execute.
                 // This makes behavior consistent with the parallel compiler.
                 let mut panic = None;
@@ -168,12 +205,6 @@
             }
         }
 
-        pub use Iterator as ParallelIterator;
-
-        pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
-            t.into_iter()
-        }
-
         pub fn par_for_each_in<T: IntoIterator>(t: T, mut for_each: impl FnMut(T::Item) + Sync + Send) {
             // We catch panics here ensuring that all the loop iterations execute.
             // This makes behavior consistent with the parallel compiler.
@@ -190,7 +221,28 @@
             }
         }
 
-        pub type MetadataRef = OwnedSlice;
+        pub fn par_map<T: IntoIterator, R, C: FromIterator<R>>(
+            t: T,
+            mut map: impl FnMut(<<T as IntoIterator>::IntoIter as Iterator>::Item) -> R,
+        ) -> C {
+            // We catch panics here ensuring that all the loop iterations execute.
+            let mut panic = None;
+            let r = t.into_iter().filter_map(|i| {
+                match catch_unwind(AssertUnwindSafe(|| map(i))) {
+                    Ok(r) => Some(r),
+                    Err(p) => {
+                        if panic.is_none() {
+                            panic = Some(p);
+                        }
+                        None
+                    }
+                }
+            }).collect();
+            if let Some(panic) = panic {
+                resume_unwind(panic);
+            }
+            r
+        }
 
         pub use std::rc::Rc as Lrc;
         pub use std::rc::Weak as Weak;
@@ -302,49 +354,166 @@
         use parking_lot::RwLock as InnerRwLock;
 
         use std::thread;
-        pub use rayon::{join, scope};
+
+        #[inline]
+        pub fn join<A, B, RA: DynSend, RB: DynSend>(oper_a: A, oper_b: B) -> (RA, RB)
+        where
+            A: FnOnce() -> RA + DynSend,
+            B: FnOnce() -> RB + DynSend,
+        {
+            if mode::is_dyn_thread_safe() {
+                let oper_a = FromDyn::from(oper_a);
+                let oper_b = FromDyn::from(oper_b);
+                let (a, b) = rayon::join(move || FromDyn::from(oper_a.into_inner()()), move || FromDyn::from(oper_b.into_inner()()));
+                (a.into_inner(), b.into_inner())
+            } else {
+                (oper_a(), oper_b())
+            }
+        }
+
+        // This function only works when `mode::is_dyn_thread_safe()`.
+        pub fn scope<'scope, OP, R>(op: OP) -> R
+        where
+            OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend,
+            R: DynSend,
+        {
+            let op = FromDyn::from(op);
+            rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner()
+        }
 
         /// Runs a list of blocks in parallel. The first block is executed immediately on
         /// the current thread. Use that for the longest running block.
         #[macro_export]
         macro_rules! parallel {
-            (impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
+            (impl $fblock:block [$($c:expr,)*] [$block:expr $(, $rest:expr)*]) => {
                 parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
             };
-            (impl $fblock:tt [$($blocks:tt,)*] []) => {
+            (impl $fblock:block [$($blocks:expr,)*] []) => {
                 ::rustc_data_structures::sync::scope(|s| {
+                    $(let block = rustc_data_structures::sync::FromDyn::from(|| $blocks);
+                    s.spawn(move |_| block.into_inner()());)*
+                    (|| $fblock)();
+                });
+            };
+            ($fblock:block, $($blocks:block),*) => {
+                if rustc_data_structures::sync::is_dyn_thread_safe() {
+                    // Reverse the order of the later blocks since Rayon executes them in reverse order
+                    // when using a single thread. This ensures the execution order matches that
+                    // of a single threaded rustc.
+                    parallel!(impl $fblock [] [$($blocks),*]);
+                } else {
+                    // We catch panics here ensuring that all the blocks execute.
+                    // This makes behavior consistent with the parallel compiler.
+                    let mut panic = None;
+                    if let Err(p) = ::std::panic::catch_unwind(
+                        ::std::panic::AssertUnwindSafe(|| $fblock)
+                    ) {
+                        if panic.is_none() {
+                            panic = Some(p);
+                        }
+                    }
                     $(
-                        s.spawn(|_| $blocks);
+                        if let Err(p) = ::std::panic::catch_unwind(
+                            ::std::panic::AssertUnwindSafe(|| $blocks)
+                        ) {
+                            if panic.is_none() {
+                                panic = Some(p);
+                            }
+                        }
                     )*
-                    $fblock;
-                })
-            };
-            ($fblock:tt, $($blocks:tt),*) => {
-                // Reverse the order of the later blocks since Rayon executes them in reverse order
-                // when using a single thread. This ensures the execution order matches that
-                // of a single threaded rustc
-                parallel!(impl $fblock [] [$($blocks),*]);
+                    if let Some(panic) = panic {
+                        ::std::panic::resume_unwind(panic);
+                    }
+                }
             };
         }
 
-        pub use rayon::iter::ParallelIterator;
-        use rayon::iter::IntoParallelIterator;
+        use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
 
-        pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
-            t.into_par_iter()
-        }
-
-        pub fn par_for_each_in<T: IntoParallelIterator>(
+        pub fn par_for_each_in<I, T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>>(
             t: T,
-            for_each: impl Fn(T::Item) + Sync + Send,
+            for_each: impl Fn(I) + DynSync + DynSend
         ) {
-            let ps: Vec<_> = t.into_par_iter().map(|i| catch_unwind(AssertUnwindSafe(|| for_each(i)))).collect();
-            ps.into_iter().for_each(|p| if let Err(panic) = p {
-                resume_unwind(panic)
-            });
+            if mode::is_dyn_thread_safe() {
+                let for_each = FromDyn::from(for_each);
+                let panic: Lock<Option<_>> = Lock::new(None);
+                t.into_par_iter().for_each(|i| if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
+                    let mut l = panic.lock();
+                    if l.is_none() {
+                        *l = Some(p)
+                    }
+                });
+
+                if let Some(panic) = panic.into_inner() {
+                    resume_unwind(panic);
+                }
+            } else {
+                // We catch panics here ensuring that all the loop iterations execute.
+                // This makes behavior consistent with the parallel compiler.
+                let mut panic = None;
+                t.into_iter().for_each(|i| {
+                    if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
+                        if panic.is_none() {
+                            panic = Some(p);
+                        }
+                    }
+                });
+                if let Some(panic) = panic {
+                    resume_unwind(panic);
+                }
+            }
         }
 
-        pub type MetadataRef = OwnedSlice;
+        pub fn par_map<
+            I,
+            T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>,
+            R: std::marker::Send,
+            C: FromIterator<R> + FromParallelIterator<R>
+        >(
+            t: T,
+            map: impl Fn(I) -> R + DynSync + DynSend
+        ) -> C {
+            if mode::is_dyn_thread_safe() {
+                let panic: Lock<Option<_>> = Lock::new(None);
+                let map = FromDyn::from(map);
+                // We catch panics here ensuring that all the loop iterations execute.
+                let r = t.into_par_iter().filter_map(|i| {
+                    match catch_unwind(AssertUnwindSafe(|| map(i))) {
+                        Ok(r) => Some(r),
+                        Err(p) => {
+                            let mut l = panic.lock();
+                            if l.is_none() {
+                                *l = Some(p);
+                            }
+                            None
+                        },
+                    }
+                }).collect();
+
+                if let Some(panic) = panic.into_inner() {
+                    resume_unwind(panic);
+                }
+                r
+            } else {
+                // We catch panics here ensuring that all the loop iterations execute.
+                let mut panic = None;
+                let r = t.into_iter().filter_map(|i| {
+                    match catch_unwind(AssertUnwindSafe(|| map(i))) {
+                        Ok(r) => Some(r),
+                        Err(p) => {
+                            if panic.is_none() {
+                                panic = Some(p);
+                            }
+                            None
+                        }
+                    }
+                }).collect();
+                if let Some(panic) = panic {
+                    resume_unwind(panic);
+                }
+                r
+            }
+        }
 
         /// This makes locks panic if they are already held.
         /// It is only useful when you are running in a single thread
@@ -352,11 +521,6 @@
     }
 }
 
-pub fn assert_sync<T: ?Sized + Sync>() {}
-pub fn assert_send<T: ?Sized + Send>() {}
-pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
-pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
-
 #[derive(Default)]
 #[cfg_attr(parallel_compiler, repr(align(64)))]
 pub struct CacheAligned<T>(pub T);
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index bfb04ba..d61bb55 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -154,13 +154,6 @@
     }
 }
 
-impl<T> WorkerLocal<Vec<T>> {
-    /// Joins the elements of all the worker locals into one Vec
-    pub fn join(self) -> Vec<T> {
-        self.into_inner().into_iter().flat_map(|v| v).collect()
-    }
-}
-
 impl<T> Deref for WorkerLocal<T> {
     type Target = T;
 
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index f19b1ff..22b4ec6 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -1,19 +1,19 @@
-driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
+driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
+driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
+driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
 
-driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
-
+driver_impl_ice_flags = compiler flags: {$flags}
+driver_impl_ice_version = rustc {$version} running on {$triple}
 driver_impl_rlink_empty_version_number = The input does not contain version number
 
 driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
 
-driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
-
 driver_impl_rlink_no_a_file = rlink must be a file
 
-driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
+driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
 
-driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
-driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
-driver_impl_ice_version = rustc {$version} running on {$triple}
-driver_impl_ice_flags = compiler flags: {$flags}
-driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
+driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
+
+driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
+
+driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs
index 42c97cc..a713aff 100644
--- a/compiler/rustc_driver_impl/src/args.rs
+++ b/compiler/rustc_driver_impl/src/args.rs
@@ -25,7 +25,7 @@
             Ok(arg) => args.extend(arg),
             Err(err) => rustc_session::early_error(
                 rustc_session::config::ErrorOutputType::default(),
-                &format!("Failed to load argument file: {err}"),
+                format!("Failed to load argument file: {err}"),
             ),
         }
     }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 9b16f24..40aa69e 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -256,6 +256,9 @@
 
     let sopts = config::build_session_options(&matches);
 
+    // Set parallel mode before thread pool creation, which will create `Lock`s.
+    interface::set_thread_safe_mode(&sopts.unstable_opts);
+
     if let Some(ref code) = matches.opt_str("explain") {
         handle_explain(diagnostics_registry(), code, sopts.error_format);
         return Ok(());
@@ -319,7 +322,7 @@
             1 => panic!("make_input should have provided valid inputs"),
             _ => early_error(
                 config.opts.error_format,
-                &format!(
+                format!(
                     "multiple input filenames provided (first two filenames are `{}` and `{}`)",
                     matches.free[0], matches.free[1],
                 ),
@@ -524,7 +527,7 @@
             }
         }
         Err(InvalidErrorCode) => {
-            early_error(output, &format!("{code} is not a valid error code"));
+            early_error(output, format!("{code} is not a valid error code"));
         }
     }
 }
@@ -569,7 +572,7 @@
             let rlink_data = fs::read(file).unwrap_or_else(|err| {
                 sess.emit_fatal(RlinkUnableToRead { err });
             });
-            let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
+            let codegen_results = match CodegenResults::deserialize_rlink(sess, rlink_data) {
                 Ok(codegen) => codegen,
                 Err(err) => {
                     match err {
@@ -583,10 +586,10 @@
                                 rlink_version,
                             })
                         }
-                        CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
+                        CodegenErrors::RustcVersionMismatch { rustc_version } => {
                             sess.emit_fatal(RLinkRustcVersionMismatch {
                                 rustc_version,
-                                current_version,
+                                current_version: sess.cfg_version,
                             })
                         }
                     };
@@ -1099,7 +1102,7 @@
                 .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
             _ => None,
         };
-        early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
+        early_error(ErrorOutputType::default(), msg.unwrap_or_else(|| e.to_string()));
     });
 
     // For all options we just parsed, we check a few aspects:
@@ -1247,7 +1250,8 @@
         #[cfg(windows)]
         if let Some(msg) = info.payload().downcast_ref::<String>() {
             if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
-                early_error_no_abort(ErrorOutputType::default(), &msg);
+                // the error code is already going to be reported when the panic unwinds up the stack
+                let _ = early_error_no_abort(ErrorOutputType::default(), msg.as_str());
                 return;
             }
         };
@@ -1311,7 +1315,7 @@
     }
 
     // If backtraces are enabled, also print the query stack
-    let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
+    let backtrace = env::var_os("RUST_BACKTRACE").is_some_and(|x| &x != "0");
 
     let num_frames = if backtrace { None } else { Some(2) };
 
@@ -1339,7 +1343,7 @@
 /// other than `RUSTC_LOG`.
 pub fn init_env_logger(env: &str) {
     if let Err(error) = rustc_log::init_env_logger(env) {
-        early_error(ErrorOutputType::default(), &error.to_string());
+        early_error(ErrorOutputType::default(), error.to_string());
     }
 }
 
@@ -1406,7 +1410,7 @@
                 arg.into_string().unwrap_or_else(|arg| {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!("argument {i} is not valid Unicode: {arg:?}"),
+                        format!("argument {i} is not valid Unicode: {arg:?}"),
                     )
                 })
             })
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 6c3f677..0accb4a 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -11,7 +11,7 @@
 use fluent_bundle::FluentResource;
 use fluent_syntax::parser::ParserError;
 use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_fluent_macro::fluent_messages;
 use rustc_macros::{Decodable, Encodable};
 use rustc_span::Span;
@@ -37,16 +37,17 @@
 
 fluent_messages! { "../messages.ftl" }
 
-pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>;
-
-#[cfg(parallel_compiler)]
-fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
-    FluentBundle::new_concurrent(locales)
-}
+pub type FluentBundle =
+    IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;
 
 #[cfg(not(parallel_compiler))]
 fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
-    FluentBundle::new(locales)
+    IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new(locales))
+}
+
+#[cfg(parallel_compiler)]
+fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
+    IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new_concurrent(locales))
 }
 
 #[derive(Debug)]
diff --git a/compiler/rustc_errors/messages.ftl b/compiler/rustc_errors/messages.ftl
index dde1d6c..3370973 100644
--- a/compiler/rustc_errors/messages.ftl
+++ b/compiler/rustc_errors/messages.ftl
@@ -1,19 +1,19 @@
-errors_target_invalid_address_space =
-    invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
-
-errors_target_invalid_bits =
-    invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
-
-errors_target_missing_alignment =
-    missing alignment for `{$cause}` in "data-layout"
-
-errors_target_invalid_alignment =
-    invalid alignment for `{$cause}` in "data-layout": {$err}
-
 errors_target_inconsistent_architecture =
     inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
 
 errors_target_inconsistent_pointer_width =
     inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
 
+errors_target_invalid_address_space =
+    invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
+
+errors_target_invalid_alignment =
+    invalid alignment for `{$cause}` in "data-layout": {$err}
+
+errors_target_invalid_bits =
+    invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
+
 errors_target_invalid_bits_size = {$err}
+
+errors_target_missing_alignment =
+    missing alignment for `{$cause}` in "data-layout"
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 68e57de..e8cd7ea 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -285,15 +285,11 @@
                     format!(
                         "help: {}{}: `{}`",
                         &msg,
-                        if self
-                            .source_map()
-                            .map(|sm| is_case_difference(
-                                sm,
-                                substitution,
-                                sugg.substitutions[0].parts[0].span,
-                            ))
-                            .unwrap_or(false)
-                        {
+                        if self.source_map().is_some_and(|sm| is_case_difference(
+                            sm,
+                            substitution,
+                            sugg.substitutions[0].parts[0].span,
+                        )) {
                             " (notice the capitalization)"
                         } else {
                             ""
@@ -336,7 +332,7 @@
 
                     // Skip past non-macro entries, just in case there
                     // are some which do actually involve macros.
-                    ExpnKind::Inlined | ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
+                    ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
 
                     ExpnKind::Macro(macro_kind, name) => Some((macro_kind, name)),
                 }
@@ -407,7 +403,7 @@
                     continue;
                 }
 
-                if always_backtrace && !matches!(trace.kind, ExpnKind::Inlined) {
+                if always_backtrace {
                     new_labels.push((
                         trace.def_site,
                         format!(
@@ -446,7 +442,6 @@
                             "this derive macro expansion".into()
                         }
                         ExpnKind::Macro(MacroKind::Bang, _) => "this macro invocation".into(),
-                        ExpnKind::Inlined => "this inlined function call".into(),
                         ExpnKind::Root => "the crate root".into(),
                         ExpnKind::AstPass(kind) => kind.descr().into(),
                         ExpnKind::Desugaring(kind) => {
@@ -2303,22 +2298,25 @@
 
         // Colorize addition/replacements with green.
         for &SubstitutionHighlight { start, end } in highlight_parts {
-            // Account for tabs when highlighting (#87972).
-            let tabs: usize = line_to_add
-                .chars()
-                .take(start)
-                .map(|ch| match ch {
-                    '\t' => 3,
-                    _ => 0,
-                })
-                .sum();
-            buffer.set_style_range(
-                *row_num,
-                max_line_num_len + 3 + start + tabs,
-                max_line_num_len + 3 + end + tabs,
-                Style::Addition,
-                true,
-            );
+            // This is a no-op for empty ranges
+            if start != end {
+                // Account for tabs when highlighting (#87972).
+                let tabs: usize = line_to_add
+                    .chars()
+                    .take(start)
+                    .map(|ch| match ch {
+                        '\t' => 3,
+                        _ => 0,
+                    })
+                    .sum();
+                buffer.set_style_range(
+                    *row_num,
+                    max_line_num_len + 3 + start + tabs,
+                    max_line_num_len + 3 + end + tabs,
+                    Style::Addition,
+                    true,
+                );
+            }
         }
         *row_num += 1;
     }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index fcbd9a5..3dec0d9 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -32,7 +32,7 @@
 use registry::Registry;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
-use rustc_data_structures::sync::{self, Lock, Lrc};
+use rustc_data_structures::sync::{self, IntoDynSyncSend, Lock, Lrc};
 use rustc_data_structures::AtomicRef;
 pub use rustc_error_messages::{
     fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
@@ -330,12 +330,11 @@
                     });
                     buf.push_str(&part.snippet);
                     let cur_hi = sm.lookup_char_pos(part.span.hi());
-                    if cur_hi.line == cur_lo.line && !part.snippet.is_empty() {
-                        // Account for the difference between the width of the current code and the
-                        // snippet being suggested, so that the *later* suggestions are correctly
-                        // aligned on the screen.
-                        acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize;
-                    }
+                    // Account for the difference between the width of the current code and the
+                    // snippet being suggested, so that the *later* suggestions are correctly
+                    // aligned on the screen. Note that cur_hi and cur_lo can be on different
+                    // lines, so cur_hi.col can be smaller than cur_lo.col
+                    acc += len - (cur_hi.col.0 as isize - cur_lo.col.0 as isize);
                     prev_hi = cur_hi;
                     prev_line = sf.get_line(prev_hi.line - 1);
                     for line in part.snippet.split('\n').skip(1) {
@@ -409,7 +408,7 @@
     err_count: usize,
     warn_count: usize,
     deduplicated_err_count: usize,
-    emitter: Box<dyn Emitter + sync::Send>,
+    emitter: IntoDynSyncSend<Box<dyn Emitter + sync::Send>>,
     delayed_span_bugs: Vec<DelayedDiagnostic>,
     delayed_good_path_bugs: Vec<DelayedDiagnostic>,
     /// This flag indicates that an expected diagnostic was emitted and suppressed.
@@ -478,6 +477,8 @@
     /// FRU syntax
     MaybeFruTypo,
     CallAssocMethod,
+    TraitMissingMethod,
+    OpaqueHiddenTypeMismatch,
 }
 
 fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
@@ -605,7 +606,7 @@
                 warn_count: 0,
                 deduplicated_err_count: 0,
                 deduplicated_warn_count: 0,
-                emitter,
+                emitter: IntoDynSyncSend(emitter),
                 delayed_span_bugs: Vec::new(),
                 delayed_good_path_bugs: Vec::new(),
                 suppressed_expected_diag: false,
@@ -1436,7 +1437,7 @@
     }
 
     fn treat_err_as_bug(&self) -> bool {
-        self.flags.treat_err_as_bug.map_or(false, |c| {
+        self.flags.treat_err_as_bug.is_some_and(|c| {
             self.err_count() + self.lint_err_count + self.delayed_bug_count() >= c.get()
         })
     }
@@ -1602,7 +1603,7 @@
         // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
         // incrementing `err_count` by one, so we need to +1 the comparing.
         // FIXME: Would be nice to increment err_count in a more coherent way.
-        if self.flags.treat_err_as_bug.map_or(false, |c| {
+        if self.flags.treat_err_as_bug.is_some_and(|c| {
             self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
         }) {
             // FIXME: don't abort here if report_delayed_bugs is off
@@ -1739,7 +1740,7 @@
     }
 
     fn decorate(mut self) -> Diagnostic {
-        self.inner.note(format!("delayed at {}", self.note));
+        self.inner.note(format!("delayed at {}\n{}", self.inner.emitted_at, self.note));
         self.inner
     }
 }
diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs
index 52103e4..0e729b7 100644
--- a/compiler/rustc_errors/src/tests.rs
+++ b/compiler/rustc_errors/src/tests.rs
@@ -2,7 +2,7 @@
 use crate::fluent_bundle::*;
 use crate::translation::Translate;
 use crate::FluentBundle;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
 use rustc_error_messages::langid;
 use rustc_error_messages::DiagnosticMessage;
@@ -27,10 +27,14 @@
     let langid_en = langid!("en-US");
 
     #[cfg(parallel_compiler)]
-    let mut bundle = FluentBundle::new_concurrent(vec![langid_en]);
+    let mut bundle: FluentBundle =
+        IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new_concurrent(vec![
+            langid_en,
+        ]));
 
     #[cfg(not(parallel_compiler))]
-    let mut bundle = FluentBundle::new(vec![langid_en]);
+    let mut bundle: FluentBundle =
+        IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new(vec![langid_en]));
 
     bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle.");
 
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 70d2718..6c7e682 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -1,56 +1,8 @@
-expand_explain_doc_comment_outer =
-    outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
-
-expand_explain_doc_comment_inner =
-    inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
-
-expand_expr_repeat_no_syntax_vars =
-    attempted to repeat an expression containing no syntax variables matched as repeating at this depth
-
-expand_must_repeat_once =
-    this must repeat at least once
-
-expand_count_repetition_misplaced =
-    `count` can not be placed inside the inner-most repetition
-
-expand_meta_var_expr_unrecognized_var =
-    variable `{$key}` is not recognized in meta-variable expression
-
-expand_var_still_repeating =
-    variable '{$ident}' is still repeating at this depth
-
-expand_meta_var_dif_seq_matchers = {$msg}
-
-expand_macro_const_stability =
-    macros cannot have const stability attributes
-    .label = invalid const stability attribute
-    .label2 = const stability attribute affects this macro
-
-expand_macro_body_stability =
-    macros cannot have body stability attributes
-    .label = invalid body stability attribute
-    .label2 = body stability attribute affects this macro
-
-expand_resolve_relative_path =
-    cannot resolve relative path in non-file source `{$path}`
-
-expand_attr_no_arguments =
-    attribute must have either one or two arguments
-
-expand_not_a_meta_item =
-    not a meta item
-
-expand_only_one_word =
-    must only be one word
-
-expand_cannot_be_name_of_macro =
-    `{$trait_ident}` cannot be a name of {$macro_type} macro
-
 expand_arg_not_attributes =
     second argument must be `attributes`
 
-expand_attributes_wrong_form =
-    attribute must be of form: `attributes(foo, bar)`
+expand_attr_no_arguments =
+    attribute must have either one or two arguments
 
 expand_attribute_meta_item =
     attribute must be a meta item, not a literal
@@ -58,51 +10,44 @@
 expand_attribute_single_word =
     attribute must only be a single word
 
-expand_helper_attribute_name_invalid =
-    `{$name}` cannot be a name of derive helper attribute
+expand_attributes_wrong_form =
+    attribute must be of form: `attributes(foo, bar)`
+
+expand_cannot_be_name_of_macro =
+    `{$trait_ident}` cannot be a name of {$macro_type} macro
+
+expand_count_repetition_misplaced =
+    `count` can not be placed inside the inner-most repetition
+
+expand_duplicate_matcher_binding = duplicate matcher binding
+    .label = duplicate binding
+    .label2 = previous binding
 
 expand_expected_comma_in_list =
     expected token: `,`
 
-expand_only_one_argument =
-    {$name} takes 1 argument
+expand_explain_doc_comment_inner =
+    inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
 
-expand_takes_no_arguments =
-    {$name} takes no arguments
+expand_explain_doc_comment_outer =
+    outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
+
+expand_expr_repeat_no_syntax_vars =
+    attempted to repeat an expression containing no syntax variables matched as repeating at this depth
 
 expand_feature_included_in_edition =
     the feature `{$feature}` is included in the Rust {$edition} edition
 
+expand_feature_not_allowed =
+    the feature `{$name}` is not in the list of allowed features
+
 expand_feature_removed =
     feature has been removed
     .label = feature has been removed
     .reason = {$reason}
 
-expand_feature_not_allowed =
-    the feature `{$name}` is not in the list of allowed features
-
-expand_recursion_limit_reached =
-    recursion limit reached while expanding `{$descr}`
-    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
-
-expand_malformed_feature_attribute =
-    malformed `feature` attribute input
-    .expected = expected just one word
-
-expand_remove_expr_not_supported =
-    removing an expression is not supported in this position
-
-expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
-expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
-expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
-expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
-expand_invalid_cfg_expected_syntax = expected syntax is
-
-expand_wrong_fragment_kind =
-    non-{$kind} macro in {$kind} position: {$name}
-
-expand_unsupported_key_value =
-    key-value macro attributes are not supported
+expand_helper_attribute_name_invalid =
+    `{$name}` cannot be a name of derive helper attribute
 
 expand_incomplete_parse =
     macro expansion ignores token `{$token}` and any following
@@ -110,33 +55,88 @@
     .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
     .suggestion_add_semi = you might be missing a semicolon here
 
-expand_remove_node_not_supported =
-    removing {$descr} is not supported in this position
+expand_invalid_cfg_expected_syntax = expected syntax is
+
+expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
+expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
+expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
+expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
+expand_macro_body_stability =
+    macros cannot have body stability attributes
+    .label = invalid body stability attribute
+    .label2 = body stability attribute affects this macro
+
+expand_macro_const_stability =
+    macros cannot have const stability attributes
+    .label = invalid const stability attribute
+    .label2 = const stability attribute affects this macro
+
+expand_malformed_feature_attribute =
+    malformed `feature` attribute input
+    .expected = expected just one word
+
+expand_meta_var_dif_seq_matchers = {$msg}
+
+expand_meta_var_expr_unrecognized_var =
+    variable `{$key}` is not recognized in meta-variable expression
 
 expand_module_circular =
     circular modules: {$modules}
 
-expand_module_in_block =
-    cannot declare a non-inline module inside a block unless it has a path attribute
-    .note = maybe `use` the module `{$name}` instead of redeclaring it
-
 expand_module_file_not_found =
     file not found for module `{$name}`
     .help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
 
+expand_module_in_block =
+    cannot declare a non-inline module inside a block unless it has a path attribute
+    .note = maybe `use` the module `{$name}` instead of redeclaring it
+
 expand_module_multiple_candidates =
     file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
     .help = delete or rename one of them to remove the ambiguity
 
-expand_trace_macro = trace_macro
+expand_must_repeat_once =
+    this must repeat at least once
+
+expand_not_a_meta_item =
+    not a meta item
+
+expand_only_one_argument =
+    {$name} takes 1 argument
+
+expand_only_one_word =
+    must only be one word
+
+expand_proc_macro_derive_tokens =
+    proc-macro derive produced unparsable tokens
 
 expand_proc_macro_panicked =
     proc macro panicked
     .help = message: {$message}
 
-expand_proc_macro_derive_tokens =
-    proc-macro derive produced unparsable tokens
+expand_recursion_limit_reached =
+    recursion limit reached while expanding `{$descr}`
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
 
-expand_duplicate_matcher_binding = duplicate matcher binding
-    .label = duplicate binding
-    .label2 = previous binding
+expand_remove_expr_not_supported =
+    removing an expression is not supported in this position
+
+expand_remove_node_not_supported =
+    removing {$descr} is not supported in this position
+
+expand_resolve_relative_path =
+    cannot resolve relative path in non-file source `{$path}`
+
+expand_takes_no_arguments =
+    {$name} takes no arguments
+
+expand_trace_macro = trace_macro
+
+expand_unsupported_key_value =
+    key-value macro attributes are not supported
+
+expand_var_still_repeating =
+    variable '{$ident}' is still repeating at this depth
+
+expand_wrong_fragment_kind =
+    non-{$kind} macro in {$kind} position: {$name}
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index c1cca89..4671adc 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -15,7 +15,8 @@
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{
-    Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult,
+    Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic,
+    MultiSpan, PResult,
 };
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
@@ -653,13 +654,13 @@
     /// A token-based function-like macro.
     Bang(
         /// An expander with signature TokenStream -> TokenStream.
-        Box<dyn BangProcMacro + sync::Sync + sync::Send>,
+        Box<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
     ),
 
     /// An AST-based function-like macro.
     LegacyBang(
         /// An expander with signature TokenStream -> AST.
-        Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
+        Box<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
     ),
 
     /// A token-based attribute macro.
@@ -667,7 +668,7 @@
         /// An expander with signature (TokenStream, TokenStream) -> TokenStream.
         /// The first TokenSteam is the attribute itself, the second is the annotated item.
         /// The produced TokenSteam replaces the input TokenSteam.
-        Box<dyn AttrProcMacro + sync::Sync + sync::Send>,
+        Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
     ),
 
     /// An AST-based attribute macro.
@@ -675,7 +676,7 @@
         /// An expander with signature (AST, AST) -> AST.
         /// The first AST fragment is the attribute itself, the second is the annotated item.
         /// The produced AST fragment replaces the input AST fragment.
-        Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
+        Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
     ),
 
     /// A trivial attribute "macro" that does nothing,
@@ -692,14 +693,14 @@
         /// is handled identically to `LegacyDerive`. It should be migrated to
         /// a token-based representation like `Bang` and `Attr`, instead of
         /// using `MultiItemModifier`.
-        Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
+        Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
     ),
 
     /// An AST-based derive macro.
     LegacyDerive(
         /// An expander with signature AST -> AST.
         /// The produced AST fragment is appended to the input AST fragment.
-        Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
+        Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
     ),
 }
 
@@ -779,7 +780,7 @@
         let allow_internal_unsafe = attr::contains_name(attrs, sym::allow_internal_unsafe);
         let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
             .and_then(|macro_export| macro_export.meta_item_list())
-            .map_or(false, |l| attr::list_contains_name(&l, sym::local_inner_macros));
+            .is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros));
         let collapse_debuginfo = attr::contains_name(attrs, sym::collapse_debuginfo);
         tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
 
@@ -1110,7 +1111,7 @@
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg)
     }
@@ -1132,14 +1133,14 @@
     /// Compilation will be stopped in the near future (at the end of
     /// the macro expansion phase).
     #[rustc_lint_diagnostics]
-    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
     }
     #[rustc_lint_diagnostics]
-    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
-    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
+    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
         self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
     }
     pub fn trace_macros_diag(&mut self) {
@@ -1448,7 +1449,7 @@
                                     && version
                                         .next()
                                         .and_then(|c| c.parse::<u32>().ok())
-                                        .map_or(false, |v| v < 6)
+                                        .is_some_and(|v| v < 6)
                             };
 
                             if crate_matches {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 7c78970..ce0093c 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -722,7 +722,11 @@
                                     });
                                 }
                             };
-                            if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
+                            if matches!(
+                                fragment_kind,
+                                AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr
+                            ) && items.is_empty()
+                            {
                                 self.cx.emit_err(RemoveExprNotSupported { span });
                                 fragment_kind.dummy(span)
                             } else {
@@ -1595,7 +1599,7 @@
                     cfg_pos = Some(pos); // a cfg attr found, no need to search anymore
                     break;
                 } else if attr_pos.is_none()
-                    && !name.map_or(false, rustc_feature::is_builtin_attr_name)
+                    && !name.is_some_and(rustc_feature::is_builtin_attr_name)
                 {
                     attr_pos = Some(pos); // a non-cfg attr found, still may find a cfg attr
                 }
@@ -1643,7 +1647,7 @@
             let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
             span = Some(current_span);
 
-            if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) {
+            if attrs.peek().is_some_and(|next_attr| next_attr.doc_str().is_some()) {
                 continue;
             }
 
@@ -1664,7 +1668,7 @@
                         &UNUSED_ATTRIBUTES,
                         attr.span,
                         self.cx.current_expansion.lint_node_id,
-                        &format!("unused attribute `{}`", attr_name),
+                        format!("unused attribute `{}`", attr_name),
                         BuiltinLintDiagnostics::UnusedBuiltinAttribute {
                             attr_name,
                             macro_name: pprust::path_to_string(&call.path),
@@ -1946,6 +1950,6 @@
     }
 
     fn proc_macro_hygiene(&self) -> bool {
-        self.features.map_or(false, |features| features.proc_macro_hygiene)
+        self.features.is_some_and(|features| features.proc_macro_hygiene)
     }
 }
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 3557229..cb8b489 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -48,7 +48,7 @@
 
     let span = token.span.substitute_dummy(sp);
 
-    let mut err = cx.struct_span_err(span, &parse_failure_msg(&token));
+    let mut err = cx.struct_span_err(span, parse_failure_msg(&token));
     err.span_label(span, label);
     if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
         err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
@@ -170,7 +170,7 @@
             }
             Error(err_sp, msg) => {
                 let span = err_sp.substitute_dummy(self.root_span);
-                self.cx.struct_span_err(span, msg).emit();
+                self.cx.struct_span_err(span, msg.as_str()).emit();
                 self.result = Some(DummyResult::any(span));
             }
             ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)),
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 75b6396..34f9982 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -110,7 +110,7 @@
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::MultiSpan;
+use rustc_errors::{DiagnosticMessage, MultiSpan};
 use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
@@ -593,7 +593,7 @@
             return;
         }
     }
-    buffer_lint(sess, span.into(), node_id, &format!("unknown macro variable `{}`", name));
+    buffer_lint(sess, span.into(), node_id, format!("unknown macro variable `{}`", name));
 }
 
 /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@@ -626,7 +626,7 @@
         if i >= occurrence_ops.len() {
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
-            let message = &format!("variable '{}' is still repeating at this depth", name);
+            let message = format!("variable '{}' is still repeating at this depth", name);
             buffer_lint(sess, span, node_id, message);
             return;
         }
@@ -642,7 +642,12 @@
     }
 }
 
-fn buffer_lint(sess: &ParseSess, span: MultiSpan, node_id: NodeId, message: &str) {
+fn buffer_lint(
+    sess: &ParseSess,
+    span: MultiSpan,
+    node_id: NodeId,
+    message: impl Into<DiagnosticMessage>,
+) {
     // Macros loaded from other crates have dummy node ids.
     if node_id != DUMMY_NODE_ID {
         sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index a07cb65..d523d3e 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -510,7 +510,7 @@
              must be less than {max}"
         )
     };
-    cx.struct_span_err(span, &msg)
+    cx.struct_span_err(span, msg)
 }
 
 fn transcribe_metavar_expr<'a>(
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index fe8c630..57e5575 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -338,7 +338,7 @@
     /// Allow conditional compilation depending on rust version
     (active, cfg_version, "1.45.0", Some(64796), None),
     /// Allows to use the `#[cfi_encoding = ""]` attribute.
-    (active, cfi_encoding, "1.69.0", Some(89653), None),
+    (active, cfi_encoding, "CURRENT_RUSTC_VERSION", Some(89653), None),
     /// Allows `for<...>` on closures and generators.
     (active, closure_lifetime_binder, "1.64.0", Some(97362), None),
     /// Allows `#[track_caller]` on closures and generators.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 61cfbf5..06f4a0b 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -861,11 +861,11 @@
 /// Whether this builtin attribute is only used in the local crate.
 /// If so, it is not encoded in the crate metadata.
 pub fn is_builtin_only_local(name: Symbol) -> bool {
-    BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
+    BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.only_local)
 }
 
 pub fn is_valid_for_get_attr(name: Symbol) -> bool {
-    BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| match attr.duplicates {
+    BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| match attr.duplicates {
         WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing
         | FutureWarnPreceding => true,
         DuplicatesOk | WarnFollowingWordOnly => false,
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 3ce16e1..beb6307 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -84,14 +84,13 @@
     pub fn from_environment(krate: Option<&str>) -> Self {
         // `true` if this is a feature-staged build, i.e., on the beta or stable channel.
         let disable_unstable_features =
-            option_env!("CFG_DISABLE_UNSTABLE_FEATURES").map(|s| s != "0").unwrap_or(false);
+            option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some_and(|s| s != "0");
         // Returns whether `krate` should be counted as unstable
-        let is_unstable_crate = |var: &str| {
-            krate.map_or(false, |name| var.split(',').any(|new_krate| new_krate == name))
-        };
+        let is_unstable_crate =
+            |var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name));
         // `true` if we should enable unstable features for bootstrapping.
-        let bootstrap = std::env::var("RUSTC_BOOTSTRAP")
-            .map_or(false, |var| var == "1" || is_unstable_crate(&var));
+        let bootstrap =
+            std::env::var("RUSTC_BOOTSTRAP").is_ok_and(|var| var == "1" || is_unstable_crate(&var));
         match (disable_unstable_features, bootstrap) {
             (_, true) => UnstableFeatures::Cheat,
             (true, _) => UnstableFeatures::Disallow,
diff --git a/compiler/rustc_hir/src/errors.rs b/compiler/rustc_hir/src/errors.rs
deleted file mode 100644
index e593ed1..0000000
--- a/compiler/rustc_hir/src/errors.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use crate::LangItem;
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
-pub struct LangItemError(pub LangItem);
-
-impl ToString for LangItemError {
-    fn to_string(&self) -> String {
-        format!("requires `{}` lang_item", self.0.name())
-    }
-}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 932f039..e844731 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -787,7 +787,7 @@
 impl<'hir> WhereBoundPredicate<'hir> {
     /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate.
     pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
-        self.bounded_ty.as_generic_param().map_or(false, |(def_id, _)| def_id == param_def_id)
+        self.bounded_ty.as_generic_param().is_some_and(|(def_id, _)| def_id == param_def_id)
     }
 }
 
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 1f08bef..4b3bc81 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -8,7 +8,6 @@
 //! * Functions called by the compiler itself.
 
 use crate::def_id::DefId;
-use crate::errors::LangItemError;
 use crate::{MethodKind, Target};
 
 use rustc_ast as ast;
@@ -42,13 +41,6 @@
         self.items[item as usize] = Some(def_id);
     }
 
-    /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
-    /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
-    /// returns an error encapsulating the `LangItem`.
-    pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
-        self.get(it).ok_or_else(|| LangItemError(it))
-    }
-
     pub fn iter(&self) -> impl Iterator<Item = (LangItem, DefId)> + '_ {
         self.items
             .iter()
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 98d967c..616de57 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -30,7 +30,6 @@
 pub mod def_path_hash_map;
 pub mod definitions;
 pub mod diagnostic_items;
-pub mod errors;
 pub use rustc_span::def_id;
 mod hir;
 pub mod hir_id;
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index c7ac01b..a40a017 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -10,13 +10,13 @@
     // the crate-id of the defining crate. This is a desirable property
     // because the crate-id can be more easily changed than the DefPath
     // of an item, so, in the case of a crate-local DefPathHash collision,
-    // the user can simply "role the dice again" for all DefPathHashes in
+    // the user can simply "roll the dice again" for all DefPathHashes in
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
     create_session_if_not_set_then(Edition::Edition2024, |_| {
-        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
-        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
+        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
+        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");
 
         let h0 = mk_test_hash(id0);
         let h1 = mk_test_hash(id1);
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 5e5c984..02d1dfc 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -1,17 +1,103 @@
-hir_analysis_unrecognized_atomic_operation =
-    unrecognized atomic operation function: `{$op}`
-    .label = unrecognized atomic operation
+hir_analysis_ambiguous_lifetime_bound =
+    ambiguous lifetime bound, explicit lifetime bound required
 
-hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
-    intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
-    .label = expected {$expected} {$descr} {$expected ->
-        [one] parameter
-        *[other] parameters
-    }
+hir_analysis_assoc_type_binding_not_allowed =
+    associated type bindings are not allowed here
+    .label = associated type not allowed here
 
-hir_analysis_unrecognized_intrinsic_function =
-    unrecognized intrinsic function: `{$name}`
-    .label = unrecognized intrinsic
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+    .suggestion = use a fully qualified path with inferred lifetimes
+
+hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
+
+hir_analysis_async_trait_impl_should_be_async =
+    method `{$method_name}` should be async because the method from the trait is async
+    .trait_item_label = required because the trait method is async
+
+hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+    .label = deref recursion limit reached
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+hir_analysis_cannot_capture_late_bound_const_in_anon_const =
+    cannot capture late-bound const parameter in a constant
+    .label = parameter defined here
+
+hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
+    cannot capture late-bound type parameter in a constant
+    .label = parameter defined here
+
+hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+
+hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
+    .label = `for<...>` is here
+
+hir_analysis_const_bound_for_non_const_trait =
+    ~const can only be applied to `#[const_trait]` traits
+
+hir_analysis_const_impl_for_non_const_trait =
+    const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
+    .suggestion = mark `{$trait_name}` as const
+    .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+    .adding = adding a non-const method body in the future would be a breaking change
+
+hir_analysis_const_param_ty_impl_on_non_adt =
+    the trait `ConstParamTy` may not be implemented for this type
+    .label = type is not a structure or enumeration
+
+hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
+
+hir_analysis_copy_impl_on_non_adt =
+    the trait `Copy` cannot be implemented for this type
+    .label = type is not a structure or enumeration
+
+hir_analysis_copy_impl_on_type_with_dtor =
+    the trait `Copy` cannot be implemented for this type; the type has a destructor
+    .label = `Copy` not allowed on types with destructors
+
+hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+
+hir_analysis_drop_impl_on_wrong_item =
+    the `Drop` trait may only be implemented for local structs, enums, and unions
+    .label = must be a struct, enum, or union in the current crate
+
+hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
+
+hir_analysis_empty_specialization = specialization impl does not specialize any associated items
+    .note = impl is a specialization of this impl
+
+hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
+    .label = overflowed on value after {$discr}
+    .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
+
+hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
+hir_analysis_field_already_declared =
+    field `{$field_name}` is already declared
+    .label = field already declared
+    .previous_decl_label = `{$field_name}` first declared here
+
+hir_analysis_function_not_found_in_trait = function not found in this trait
+
+hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
+    .note = required by this annotation
+
+hir_analysis_functions_names_duplicated = functions names are duplicated
+    .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+
+hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+    .label = cannot specialize default item `{$ident}`
+    .ok_label = parent `impl` is here
+    .note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
+
+hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+    .note = parent implementation is in crate `{$cname}`
+
+hir_analysis_invalid_union_field =
+    field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+    .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+
+hir_analysis_invalid_union_field_sugg =
+    wrap the field type in `ManuallyDrop<...>`
 
 hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
@@ -20,58 +106,39 @@
     .where_label = this `where` clause might not match the one in the trait
     .bounds_label = this bound might be missing in the impl
 
-hir_analysis_async_trait_impl_should_be_async =
-    method `{$method_name}` should be async because the method from the trait is async
-    .trait_item_label = required because the trait method is async
+hir_analysis_linkage_type =
+    invalid type for variable with `#[linkage]` attribute
 
-hir_analysis_drop_impl_on_wrong_item =
-    the `Drop` trait may only be implemented for local structs, enums, and unions
-    .label = must be a struct, enum, or union in the current crate
+hir_analysis_main_function_async = `main` function is not allowed to be `async`
+    .label = `main` function is not allowed to be `async`
 
-hir_analysis_field_already_declared =
-    field `{$field_name}` is already declared
-    .label = field already declared
-    .previous_decl_label = `{$field_name}` first declared here
+hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
+    .label = `main` cannot have generic parameters
 
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
-hir_analysis_const_param_ty_impl_on_non_adt =
-    the trait `ConstParamTy` may not be implemented for this type
-    .label = type is not a structure or enumeration
-
-hir_analysis_ambiguous_lifetime_bound =
-    ambiguous lifetime bound, explicit lifetime bound required
-
-hir_analysis_assoc_type_binding_not_allowed =
-    associated type bindings are not allowed here
-    .label = associated type not allowed here
-
-hir_analysis_parenthesized_fn_trait_expansion =
-    parenthesized trait syntax expands to `{$expanded_type}`
-
-hir_analysis_typeof_reserved_keyword_used =
-    `typeof` is a reserved keyword but unimplemented
-    .suggestion = consider replacing `typeof(...)` with an actual type
-    .label = reserved keyword
-
-hir_analysis_value_of_associated_struct_already_specified =
-    the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
-    .label = re-bound here
-    .previous_bound_label = `{$item_name}` bound here first
-
-hir_analysis_unconstrained_opaque_type = unconstrained opaque type
-    .note = `{$name}` must be used in combination with a concrete type within the same {$what}
+hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
 
 hir_analysis_manual_implementation =
     manual implementations of `{$trait_name}` are experimental
     .label = manual implementations of `{$trait_name}` are experimental
     .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
+    .label = missing one of `{$missing_items_msg}` in implementation
+    .note = required because of this annotation
 
-hir_analysis_trait_object_declared_with_no_traits =
-    at least one trait is required for an object type
-    .alias_span = this alias does not contain a trait
+hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+
+hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
+    .label = missing `{$missing_items_msg}` in implementation
+
+hir_analysis_missing_trait_item_label = `{$item}` from trait
+
+hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
+
+hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
+    .note = default implementation of `{$missing_item_name}` is unstable
+    .some_note = use of unstable library feature '{$feature}': {$r}
+    .none_note = use of unstable library feature '{$feature}'
 
 hir_analysis_missing_type_params =
     the type {$parameterCount ->
@@ -95,98 +162,35 @@
     } to {$parameters}
     .note = because of the default `Self` reference, type parameters must be specified on object types
 
-hir_analysis_copy_impl_on_type_with_dtor =
-    the trait `Copy` cannot be implemented for this type; the type has a destructor
-    .label = `Copy` not allowed on types with destructors
-
 hir_analysis_multiple_relaxed_default_bounds =
     type parameter has more than one relaxed default bound, only one is supported
 
-hir_analysis_copy_impl_on_non_adt =
-    the trait `Copy` cannot be implemented for this type
-    .label = type is not a structure or enumeration
+hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
 
-hir_analysis_const_impl_for_non_const_trait =
-    const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
-    .suggestion = mark `{$trait_name}` as const
-    .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
-    .adding = adding a non-const method body in the future would be a breaking change
+hir_analysis_must_implement_not_function = not a function
 
-hir_analysis_const_bound_for_non_const_trait =
-    ~const can only be applied to `#[const_trait]` traits
+hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
 
-hir_analysis_self_in_impl_self =
-    `Self` is not valid in the self type of an impl block
-    .note = replace `Self` with a different type
+hir_analysis_must_implement_not_function_span_note = required by this annotation
 
-hir_analysis_linkage_type =
-    invalid type for variable with `#[linkage]` attribute
+hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
 
-hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
-    .label = deref recursion limit reached
-    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
+    .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
 
-hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
-    .label = `main` cannot have a `where` clause
-
-hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
-    .suggestion = remove this annotation
-
-hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
-
-hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
-    .label = `start` is not allowed to be `#[track_caller]`
-
-hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
-    .label = `start` is not allowed to have `#[target_feature]`
-
-hir_analysis_start_not_async = `start` is not allowed to be `async`
-    .label = `start` is not allowed to be `async`
-
-hir_analysis_start_function_where = start function is not allowed to have a `where` clause
-    .label = start function cannot have a `where` clause
-
-hir_analysis_start_function_parameters = start function is not allowed to have type parameters
-    .label = start function cannot have type parameters
-
-hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
-
-hir_analysis_main_function_async = `main` function is not allowed to be `async`
-    .label = `main` function is not allowed to be `async`
-
-hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
-    .label = `main` cannot have generic parameters
-
-hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
-    .label = C-variadic function must have a compatible calling convention
-
-hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
-    cannot capture late-bound type parameter in a constant
-    .label = parameter defined here
-
-hir_analysis_cannot_capture_late_bound_const_in_anon_const =
-    cannot capture late-bound const parameter in a constant
-    .label = parameter defined here
-
-hir_analysis_variances_of = {$variances_of}
+hir_analysis_parenthesized_fn_trait_expansion =
+    parenthesized trait syntax expands to `{$expanded_type}`
 
 hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
     .suggestion = cast the value to `{$cast_ty}`
     .help = cast the value to `{$cast_ty}`
 
-hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
+    .label = not allowed in type signatures
 
-hir_analysis_invalid_union_field =
-    field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
-    .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
-
-hir_analysis_invalid_union_field_sugg =
-    wrap the field type in `ManuallyDrop<...>`
-
-hir_analysis_return_type_notation_on_non_rpitit =
-    return type notation used on function that is not `async` and does not return `impl Trait`
-    .note = function returns `{$ty}`, which is not compatible with associated type return bounds
-    .label = this function must be `async` or return `impl Trait`
+hir_analysis_return_type_notation_conflicting_bound =
+    ambiguous associated function `{$assoc_name}` for `{$ty_name}`
+    .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
 
 hir_analysis_return_type_notation_equality_bound =
     return type notation is not allowed to use type equality
@@ -194,100 +198,96 @@
 hir_analysis_return_type_notation_missing_method =
     cannot find associated function `{$assoc_name}` for `{$ty_name}`
 
-hir_analysis_return_type_notation_conflicting_bound =
-    ambiguous associated function `{$assoc_name}` for `{$ty_name}`
-    .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
+hir_analysis_return_type_notation_on_non_rpitit =
+    return type notation used on function that is not `async` and does not return `impl Trait`
+    .note = function returns `{$ty}`, which is not compatible with associated type return bounds
+    .label = this function must be `async` or return `impl Trait`
 
-hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
-    .label = not allowed in type signatures
-
-hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
-    .suggestion = use a fully qualified path with inferred lifetimes
-
-hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
-
-hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
-    .label = overflowed on value after {$discr}
-    .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
-
-hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
-    .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
-
-hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
-
-hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
-
-hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
-    .note = required by this annotation
-
-hir_analysis_must_implement_not_function = not a function
-
-hir_analysis_must_implement_not_function_span_note = required by this annotation
-
-hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
-
-hir_analysis_function_not_found_in_trait = function not found in this trait
-
-hir_analysis_functions_names_duplicated = functions names are duplicated
-    .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+hir_analysis_self_in_impl_self =
+    `Self` is not valid in the self type of an impl block
+    .note = replace `Self` with a different type
 
 hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
     .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
 
-hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
-    .label = cannot specialize default item `{$ident}`
-    .ok_label = parent `impl` is here
-    .note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
+hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
+    .help = add `#![feature(min_specialization)]` to the crate attributes to enable
 
-hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
-    .note = parent implementation is in crate `{$cname}`
+hir_analysis_start_function_parameters = start function is not allowed to have type parameters
+    .label = start function cannot have type parameters
 
-hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
-    .label = missing `{$missing_items_msg}` in implementation
+hir_analysis_start_function_where = start function is not allowed to have a `where` clause
+    .label = start function cannot have a `where` clause
 
-hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
+hir_analysis_start_not_async = `start` is not allowed to be `async`
+    .label = `start` is not allowed to be `async`
 
-hir_analysis_missing_trait_item_label = `{$item}` from trait
+hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
+    .label = `start` is not allowed to have `#[target_feature]`
 
-hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
-    .label = missing one of `{$missing_items_msg}` in implementation
-    .note = required because of this annotation
+hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
+    .label = `start` is not allowed to be `#[track_caller]`
 
-hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
-    .note = default implementation of `{$missing_item_name}` is unstable
-    .some_note = use of unstable library feature '{$feature}': {$r}
-    .none_note = use of unstable library feature '{$feature}'
+hir_analysis_static_specialize = cannot specialize on `'static` lifetime
+
+hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+
+hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
+
+hir_analysis_too_large_static = extern static is too large for the current architecture
+
+hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
+    .suggestion = remove this annotation
+
+hir_analysis_trait_object_declared_with_no_traits =
+    at least one trait is required for an object type
+    .alias_span = this alias does not contain a trait
 
 hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
     .label = needs exactly one variant, but has {$number}
     .many_label = too many variants in `{$path}`
     .multi_label = variant here
 
-hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
-    .label = needs at most one non-zero-sized field, but has {$field_count}
-    .labels = this field is non-zero-sized
-
 hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
     .label = needs at most one non-zero-sized field, but has {$field_count}
     .labels = this field is non-zero-sized
 
-hir_analysis_too_large_static = extern static is too large for the current architecture
+hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
+    .label = needs at most one non-zero-sized field, but has {$field_count}
+    .labels = this field is non-zero-sized
 
-hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
-    .help = add `#![feature(min_specialization)]` to the crate attributes to enable
+hir_analysis_typeof_reserved_keyword_used =
+    `typeof` is a reserved keyword but unimplemented
+    .suggestion = consider replacing `typeof(...)` with an actual type
+    .label = reserved keyword
 
-hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
-    .label = `for<...>` is here
+hir_analysis_unconstrained_opaque_type = unconstrained opaque type
+    .note = `{$name}` must be used in combination with a concrete type within the same {$what}
 
-hir_analysis_empty_specialization = specialization impl does not specialize any associated items
-    .note = impl is a specialization of this impl
+hir_analysis_unrecognized_atomic_operation =
+    unrecognized atomic operation function: `{$op}`
+    .label = unrecognized atomic operation
 
-hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
+hir_analysis_unrecognized_intrinsic_function =
+    unrecognized intrinsic function: `{$name}`
+    .label = unrecognized intrinsic
 
-hir_analysis_static_specialize = cannot specialize on `'static` lifetime
+hir_analysis_value_of_associated_struct_already_specified =
+    the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
+    .label = re-bound here
+    .previous_bound_label = `{$item_name}` bound here first
 
-hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
+    .label = C-variadic function must have a compatible calling convention
 
-hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+hir_analysis_variances_of = {$variances_of}
 
-hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
+hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
+    .label = `main` cannot have a `where` clause
+
+hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
+    intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
+    .label = expected {$expected} {$descr} {$expected ->
+        [one] parameter
+        *[other] parameters
+    }
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index ed011b9..39d1d1f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -24,7 +24,7 @@
     arg: &GenericArg<'_>,
     param: &GenericParamDef,
     possible_ordering_error: bool,
-    help: Option<&str>,
+    help: Option<String>,
 ) -> ErrorGuaranteed {
     let sess = tcx.sess;
     let mut err = struct_span_err!(
@@ -300,7 +300,7 @@
                                     arg,
                                     param,
                                     !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
-                                    Some(&format!(
+                                    Some(format!(
                                         "reorder the arguments: {}: `<{}>`",
                                         param_types_present
                                             .into_iter()
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 6ac1df6..5fb06cf 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -19,7 +19,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
-    MultiSpan,
+    MultiSpan, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -38,7 +38,6 @@
 use rustc_middle::ty::{DynKind, ToPredicate};
 use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
 use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::edition::Edition;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi;
@@ -464,7 +463,7 @@
                             self.astconv.ct_infer(ty, Some(param), inf.span).into()
                         } else {
                             self.inferred_params.push(inf.span);
-                            tcx.const_error(ty).into()
+                            tcx.const_error_misc(ty).into()
                         }
                     }
                     _ => unreachable!(),
@@ -518,7 +517,7 @@
                             .no_bound_vars()
                             .expect("const parameter types cannot be generic");
                         if let Err(guar) = ty.error_reported() {
-                            return tcx.const_error_with_guaranteed(ty, guar).into();
+                            return tcx.const_error(ty, guar).into();
                         }
                         if !infer_args && has_default {
                             tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
@@ -527,7 +526,7 @@
                                 self.astconv.ct_infer(ty, Some(param), self.span).into()
                             } else {
                                 // We've already errored above about the mismatch.
-                                tcx.const_error(ty).into()
+                                tcx.const_error_misc(ty).into()
                             }
                         }
                     }
@@ -1387,7 +1386,7 @@
                         term = match def_kind {
                             hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
                             hir::def::DefKind::AssocConst => tcx
-                                .const_error_with_guaranteed(
+                                .const_error(
                                     tcx.type_of(assoc_item_def_id)
                                         .subst(tcx, projection_ty.skip_binder().substs),
                                     reported,
@@ -2626,7 +2625,7 @@
                     && tcx.all_impls(*trait_def_id)
                         .any(|impl_def_id| {
                             let trait_ref = tcx.impl_trait_ref(impl_def_id);
-                            trait_ref.map_or(false, |trait_ref| {
+                            trait_ref.is_some_and(|trait_ref| {
                                 let impl_ = trait_ref.subst(
                                     tcx,
                                     infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
@@ -3655,7 +3654,7 @@
             ..
         }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id
         {
-            if !of_trait_ref.trait_def_id().map_or(false, |def_id| def_id.is_local()) {
+            if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
                 return;
             }
             let of_trait_span = of_trait_ref.path.span;
@@ -3694,7 +3693,7 @@
                     .source_map()
                     .span_to_prev_source(self_ty.span)
                     .ok()
-                    .map_or(false, |s| s.trim_end().ends_with('<'));
+                    .is_some_and(|s| s.trim_end().ends_with('<'));
 
             let is_global = poly_trait_ref.trait_ref.path.is_global();
 
@@ -3718,7 +3717,7 @@
                 ));
             }
 
-            if self_ty.span.edition() >= Edition::Edition2021 {
+            if self_ty.span.edition().rust_2021() {
                 let msg = "trait objects must include the `dyn` keyword";
                 let label = "add `dyn` keyword before this trait";
                 let mut diag =
@@ -3732,7 +3731,7 @@
                 }
                 // check if the impl trait that we are considering is a impl of a local trait
                 self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
-                diag.emit();
+                diag.stash(self_ty.span, StashKey::TraitMissingMethod);
             } else {
                 let msg = "trait objects without an explicit `dyn` are deprecated";
                 tcx.struct_span_lint_hir(
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 1cf93c8..d6d1498 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -1,6 +1,5 @@
 use crate::errors::AutoDerefReachedRecursionLimit;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::NormalizeExt;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::TypeVisitableExt;
@@ -9,6 +8,7 @@
 use rustc_span::def_id::LocalDefId;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
+use rustc_trait_selection::traits::StructurallyNormalizeExt;
 
 #[derive(Copy, Clone, Debug)]
 pub enum AutoderefKind {
@@ -66,14 +66,27 @@
         }
 
         // Otherwise, deref if type is derefable:
-        let (kind, new_ty) =
-            if let Some(mt) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
-                (AutoderefKind::Builtin, mt.ty)
-            } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
-                (AutoderefKind::Overloaded, ty)
+        let (kind, new_ty) = if let Some(ty::TypeAndMut { ty, .. }) =
+            self.state.cur_ty.builtin_deref(self.include_raw_pointers)
+        {
+            debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
+            // NOTE: we may still need to normalize the built-in deref in case
+            // we have some type like `&<Ty as Trait>::Assoc`, since users of
+            // autoderef expect this type to have been structurally normalized.
+            if self.infcx.tcx.trait_solver_next()
+                && let ty::Alias(ty::Projection, _) = ty.kind()
+            {
+                let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
+                self.state.obligations.extend(obligations);
+                (AutoderefKind::Builtin, normalized_ty)
             } else {
-                return None;
-            };
+                (AutoderefKind::Builtin, ty)
+            }
+        } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
+            (AutoderefKind::Overloaded, ty)
+        } else {
+            return None;
+        };
 
         if new_ty.references_error() {
             return None;
@@ -119,14 +132,11 @@
 
     fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         debug!("overloaded_deref_ty({:?})", ty);
-
         let tcx = self.infcx.tcx;
 
         // <ty as Deref>
         let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
-
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
-
         let obligation = traits::Obligation::new(
             tcx,
             cause.clone(),
@@ -138,28 +148,50 @@
             return None;
         }
 
-        let normalized_ty = self
-            .infcx
-            .at(&cause, self.param_env)
-            .normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
-        let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
-        let normalized_ty =
-            normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
-        let errors = fulfillcx.select_where_possible(&self.infcx);
-        if !errors.is_empty() {
-            // This shouldn't happen, except for evaluate/fulfill mismatches,
-            // but that's not a reason for an ICE (`predicate_may_hold` is conservative
-            // by design).
-            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
-            return None;
-        }
-        let obligations = fulfillcx.pending_obligations();
+        let (normalized_ty, obligations) =
+            self.structurally_normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, [ty]))?;
         debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
         self.state.obligations.extend(obligations);
 
         Some(self.infcx.resolve_vars_if_possible(normalized_ty))
     }
 
+    #[instrument(level = "debug", skip(self), ret)]
+    pub fn structurally_normalize(
+        &self,
+        ty: Ty<'tcx>,
+    ) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
+        let tcx = self.infcx.tcx;
+        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
+
+        let cause = traits::ObligationCause::misc(self.span, self.body_id);
+        let normalized_ty = match self
+            .infcx
+            .at(&cause, self.param_env)
+            .structurally_normalize(ty, &mut *fulfill_cx)
+        {
+            Ok(normalized_ty) => normalized_ty,
+            Err(errors) => {
+                // This shouldn't happen, except for evaluate/fulfill mismatches,
+                // but that's not a reason for an ICE (`predicate_may_hold` is conservative
+                // by design).
+                debug!(?errors, "encountered errors while fulfilling");
+                return None;
+            }
+        };
+
+        let errors = fulfill_cx.select_where_possible(&self.infcx);
+        if !errors.is_empty() {
+            // This shouldn't happen, except for evaluate/fulfill mismatches,
+            // but that's not a reason for an ICE (`predicate_may_hold` is conservative
+            // by design).
+            debug!(?errors, "encountered errors while fulfilling");
+            return None;
+        }
+
+        Some((normalized_ty, fulfill_cx.pending_obligations()))
+    }
+
     /// Returns the final type we ended up with, which may be an inference
     /// variable (we will resolve it first, if we want).
     pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 78ffe59..3b2c052 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -13,11 +13,12 @@
 use rustc_hir::{ItemKind, Node, PathSegment};
 use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
+use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::{Obligation, TraitEngineExt as _};
 use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::stability::EvalResult;
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -800,16 +801,15 @@
 
             let is_implemented = leaf_def
                 .as_ref()
-                .map_or(false, |node_item| node_item.item.defaultness(tcx).has_value());
+                .is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
 
             if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
                 missing_items.push(tcx.associated_item(trait_item_id));
             }
 
             // true if this item is specifically implemented in this impl
-            let is_implemented_here = leaf_def
-                .as_ref()
-                .map_or(false, |node_item| !node_item.defining_node.is_from_trait());
+            let is_implemented_here =
+                leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait());
 
             if !is_implemented_here {
                 let full_impl_span =
@@ -1082,8 +1082,8 @@
         let layout = tcx.layout_of(param_env.and(ty));
         // We are currently checking the type this field came from, so it must be local
         let span = tcx.hir().span_if_local(field.did).unwrap();
-        let zst = layout.map_or(false, |layout| layout.is_zst());
-        let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1);
+        let zst = layout.is_ok_and(|layout| layout.is_zst());
+        let align1 = layout.is_ok_and(|layout| layout.align.abi.bytes() == 1);
         if !zst {
             return (span, zst, align1, None);
         }
@@ -1514,8 +1514,8 @@
                     }
                     if tcx.sess.opts.unstable_opts.drop_tracking_mir
                         && let DefKind::Generator = tcx.def_kind(closure_def_id)
+                        && let Some(generator_layout) = tcx.mir_generator_witnesses(closure_def_id)
                     {
-                        let generator_layout = tcx.mir_generator_witnesses(closure_def_id);
                         for interior_ty in &generator_layout.field_tys {
                             label_match(interior_ty.ty, interior_ty.source_info.span);
                         }
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 08154cd..3971a4c 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -78,7 +78,7 @@
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_session::parse::feature_err;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 862f0a9..b403ee9 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -12,7 +12,7 @@
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
@@ -179,7 +179,7 @@
         hir::ItemKind::Impl(impl_) => {
             let is_auto = tcx
                 .impl_trait_ref(def_id)
-                .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
+                .is_some_and(|trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
             if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
                 let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
                 let mut err =
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index d05d850..a98d8e1 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -298,9 +298,7 @@
 
     let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
 
-    let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
-        tcx.sess.fatal(format!("`CoerceUnsized` implementation {}", err.to_string()));
-    });
+    let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
 
     let source = tcx.type_of(impl_did).subst_identity();
     let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index cd2ec2b..4524b87 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -8,7 +8,7 @@
 use crate::errors;
 use rustc_errors::{error_code, struct_span_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 2f808d4..ca0d550 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -28,7 +28,7 @@
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -73,7 +73,6 @@
         fn_sig,
         impl_trait_ref,
         impl_polarity,
-        is_foreign_item,
         generator_kind,
         collect_mod_item_types,
         is_type_alias_impl_trait,
@@ -820,7 +819,7 @@
         recovered,
         adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
             || variant_did
-                .map_or(false, |variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
+                .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
     )
 }
 
@@ -1026,7 +1025,7 @@
             is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
         }
         Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
-            ty_opt.map_or(false, is_suggestable_infer_ty)
+            ty_opt.is_some_and(is_suggestable_infer_ty)
                 || segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
         }
         _ => false,
@@ -1466,10 +1465,6 @@
     fty
 }
 
-fn is_foreign_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    matches!(tcx.hir().get_by_def_id(def_id), Node::ForeignItem(..))
-}
-
 fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> {
     match tcx.hir().get_by_def_id(def_id) {
         Node::Expr(&rustc_hir::Expr {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index a339908..e5b5dae 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -427,6 +427,8 @@
             //   supertrait).
             if let ty::Alias(ty::Projection, projection) = ty.kind() {
                 projection.substs == trait_identity_substs
+                    // FIXME(return_type_notation): This check should be more robust
+                    && !tcx.is_impl_trait_in_trait(projection.def_id)
                     && tcx.associated_item(projection.def_id).container_id(tcx)
                         == def_id.to_def_id()
             } else {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 92ae93c..794812a 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -17,6 +17,7 @@
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::*;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
@@ -232,8 +233,8 @@
 
 type ScopeRef<'a> = &'a Scope<'a>;
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
         resolve_bound_vars,
 
         named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 6c7c2b9..8e082d3 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -1,10 +1,7 @@
 use rustc_errors::{Applicability, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{HirId, Node};
-use rustc_middle::hir::nested_filter;
+use rustc_hir::HirId;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IntTypeExt;
@@ -14,7 +11,8 @@
 
 use super::ItemCtxt;
 use super::{bad_placeholder, is_suggestable_infer_ty};
-use crate::errors::UnconstrainedOpaqueType;
+
+mod opaque;
 
 fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     use hir::*;
@@ -164,7 +162,7 @@
             let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
                 return tcx.ty_error_with_message(
                     tcx.def_span(def_id),
-                    &format!("unable to find type-dependent def for {:?}", parent_node_id),
+                    format!("unable to find type-dependent def for {:?}", parent_node_id),
                 );
             };
             let idx = segment
@@ -205,14 +203,14 @@
                     } else {
                         return tcx.ty_error_with_message(
                             tcx.def_span(def_id),
-                            &format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
+                            format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
                         );
                     }
                 }
                 _ => {
                     return tcx.ty_error_with_message(
                         tcx.def_span(def_id),
-                        &format!("unexpected const parent path {:?}", parent_node),
+                        format!("unexpected const parent path {:?}", parent_node),
                     );
                 }
             };
@@ -243,7 +241,7 @@
                 None => {
                     return tcx.ty_error_with_message(
                         tcx.def_span(def_id),
-                        &format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
+                        format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
                     );
                 }
             };
@@ -253,7 +251,7 @@
 
         _ => return tcx.ty_error_with_message(
             tcx.def_span(def_id),
-            &format!("unexpected const parent in type_of(): {parent_node:?}"),
+            format!("unexpected const parent in type_of(): {parent_node:?}"),
         ),
     };
 
@@ -279,7 +277,7 @@
     } else {
         return tcx.ty_error_with_message(
             tcx.def_span(def_id),
-            &format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
+            format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
         );
     }
 }
@@ -429,7 +427,7 @@
                 ItemKind::OpaqueTy(OpaqueTy {
                     origin: hir::OpaqueTyOrigin::TyAlias { .. },
                     ..
-                }) => find_opaque_ty_constraints_for_tait(tcx, def_id),
+                }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
                 // Opaque types desugared from `impl Trait`.
                 ItemKind::OpaqueTy(OpaqueTy {
                     origin:
@@ -443,7 +441,7 @@
                             "tried to get type of this RPITIT with no definition"
                         );
                     }
-                    find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+                    opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
                 }
                 ItemKind::Trait(..)
                 | ItemKind::TraitAlias(..)
@@ -502,303 +500,6 @@
     ty::EarlyBinder(output)
 }
 
-#[instrument(skip(tcx), level = "debug")]
-/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
-/// laid for "higher-order pattern unification".
-/// This ensures that inference is tractable.
-/// In particular, definitions of opaque types can only use other generics as arguments,
-/// and they cannot repeat an argument. Example:
-///
-/// ```ignore (illustrative)
-/// type Foo<A, B> = impl Bar<A, B>;
-///
-/// // Okay -- `Foo` is applied to two distinct, generic types.
-/// fn a<T, U>() -> Foo<T, U> { .. }
-///
-/// // Not okay -- `Foo` is applied to `T` twice.
-/// fn b<T>() -> Foo<T, T> { .. }
-///
-/// // Not okay -- `Foo` is applied to a non-generic type.
-/// fn b<T>() -> Foo<T, u32> { .. }
-/// ```
-///
-fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
-    use rustc_hir::{Expr, ImplItem, Item, TraitItem};
-
-    struct ConstraintLocator<'tcx> {
-        tcx: TyCtxt<'tcx>,
-
-        /// def_id of the opaque type whose defining uses are being checked
-        def_id: LocalDefId,
-
-        /// as we walk the defining uses, we are checking that all of them
-        /// define the same hidden type. This variable is set to `Some`
-        /// with the first type that we find, and then later types are
-        /// checked against it (we also carry the span of that first
-        /// type).
-        found: Option<ty::OpaqueHiddenType<'tcx>>,
-
-        /// In the presence of dead code, typeck may figure out a hidden type
-        /// while borrowck will not. We collect these cases here and check at
-        /// the end that we actually found a type that matches (modulo regions).
-        typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
-    }
-
-    impl ConstraintLocator<'_> {
-        #[instrument(skip(self), level = "debug")]
-        fn check(&mut self, item_def_id: LocalDefId) {
-            // Don't try to check items that cannot possibly constrain the type.
-            if !self.tcx.has_typeck_results(item_def_id) {
-                debug!("no constraint: no typeck results");
-                return;
-            }
-            // Calling `mir_borrowck` can lead to cycle errors through
-            // const-checking, avoid calling it if we don't have to.
-            // ```rust
-            // type Foo = impl Fn() -> usize; // when computing type for this
-            // const fn bar() -> Foo {
-            //     || 0usize
-            // }
-            // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
-            // // because we again need to reveal `Foo` so we can check whether the
-            // // constant does not contain interior mutability.
-            // ```
-            let tables = self.tcx.typeck(item_def_id);
-            if let Some(guar) = tables.tainted_by_errors {
-                self.found =
-                    Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
-                return;
-            }
-            let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
-                debug!("no constraints in typeck results");
-                return;
-            };
-            if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
-                self.typeck_types.push(typeck_hidden_ty);
-            }
-
-            // Use borrowck to get the type with unerased regions.
-            let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
-            debug!(?concrete_opaque_types);
-            if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
-                debug!(?concrete_type, "found constraint");
-                if let Some(prev) = &mut self.found {
-                    if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
-                        let guar = prev.report_mismatch(&concrete_type, self.tcx);
-                        prev.ty = self.tcx.ty_error(guar);
-                    }
-                } else {
-                    self.found = Some(concrete_type);
-                }
-            }
-        }
-    }
-
-    impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
-        type NestedFilter = nested_filter::All;
-
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.tcx.hir()
-        }
-        fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-            if let hir::ExprKind::Closure(closure) = ex.kind {
-                self.check(closure.def_id);
-            }
-            intravisit::walk_expr(self, ex);
-        }
-        fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
-            trace!(?it.owner_id);
-            // The opaque type itself or its children are not within its reveal scope.
-            if it.owner_id.def_id != self.def_id {
-                self.check(it.owner_id.def_id);
-                intravisit::walk_item(self, it);
-            }
-        }
-        fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
-            trace!(?it.owner_id);
-            // The opaque type itself or its children are not within its reveal scope.
-            if it.owner_id.def_id != self.def_id {
-                self.check(it.owner_id.def_id);
-                intravisit::walk_impl_item(self, it);
-            }
-        }
-        fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
-            trace!(?it.owner_id);
-            self.check(it.owner_id.def_id);
-            intravisit::walk_trait_item(self, it);
-        }
-    }
-
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let scope = tcx.hir().get_defining_scope(hir_id);
-    let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
-
-    debug!(?scope);
-
-    if scope == hir::CRATE_HIR_ID {
-        tcx.hir().walk_toplevel_module(&mut locator);
-    } else {
-        trace!("scope={:#?}", tcx.hir().get(scope));
-        match tcx.hir().get(scope) {
-            // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
-            // This allows our visitor to process the defining item itself, causing
-            // it to pick up any 'sibling' defining uses.
-            //
-            // For example, this code:
-            // ```
-            // fn foo() {
-            //     type Blah = impl Debug;
-            //     let my_closure = || -> Blah { true };
-            // }
-            // ```
-            //
-            // requires us to explicitly process `foo()` in order
-            // to notice the defining usage of `Blah`.
-            Node::Item(it) => locator.visit_item(it),
-            Node::ImplItem(it) => locator.visit_impl_item(it),
-            Node::TraitItem(it) => locator.visit_trait_item(it),
-            other => bug!("{:?} is not a valid scope for an opaque type item", other),
-        }
-    }
-
-    let Some(hidden) = locator.found else {
-        let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
-            span: tcx.def_span(def_id),
-            name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
-            what: match tcx.hir().get(scope) {
-                _ if scope == hir::CRATE_HIR_ID => "module",
-                Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
-                Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
-                _ => "item",
-            },
-        });
-        return tcx.ty_error(reported);
-    };
-
-    // Only check against typeck if we didn't already error
-    if !hidden.ty.references_error() {
-        for concrete_type in locator.typeck_types {
-            if tcx.erase_regions(concrete_type.ty) != tcx.erase_regions(hidden.ty)
-                && !(concrete_type, hidden).references_error()
-            {
-                hidden.report_mismatch(&concrete_type, tcx);
-            }
-        }
-    }
-
-    hidden.ty
-}
-
-fn find_opaque_ty_constraints_for_rpit(
-    tcx: TyCtxt<'_>,
-    def_id: LocalDefId,
-    owner_def_id: LocalDefId,
-) -> Ty<'_> {
-    use rustc_hir::{Expr, ImplItem, Item, TraitItem};
-
-    struct ConstraintChecker<'tcx> {
-        tcx: TyCtxt<'tcx>,
-
-        /// def_id of the opaque type whose defining uses are being checked
-        def_id: LocalDefId,
-
-        found: ty::OpaqueHiddenType<'tcx>,
-    }
-
-    impl ConstraintChecker<'_> {
-        #[instrument(skip(self), level = "debug")]
-        fn check(&self, def_id: LocalDefId) {
-            // Use borrowck to get the type with unerased regions.
-            let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
-            debug!(?concrete_opaque_types);
-            for (&def_id, &concrete_type) in concrete_opaque_types {
-                if def_id != self.def_id {
-                    // Ignore constraints for other opaque types.
-                    continue;
-                }
-
-                debug!(?concrete_type, "found constraint");
-
-                if concrete_type.ty != self.found.ty
-                    && !(concrete_type, self.found).references_error()
-                {
-                    self.found.report_mismatch(&concrete_type, self.tcx);
-                }
-            }
-        }
-    }
-
-    impl<'tcx> intravisit::Visitor<'tcx> for ConstraintChecker<'tcx> {
-        type NestedFilter = nested_filter::OnlyBodies;
-
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.tcx.hir()
-        }
-        fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-            if let hir::ExprKind::Closure(closure) = ex.kind {
-                self.check(closure.def_id);
-            }
-            intravisit::walk_expr(self, ex);
-        }
-        fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
-            trace!(?it.owner_id);
-            // The opaque type itself or its children are not within its reveal scope.
-            if it.owner_id.def_id != self.def_id {
-                self.check(it.owner_id.def_id);
-                intravisit::walk_item(self, it);
-            }
-        }
-        fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
-            trace!(?it.owner_id);
-            // The opaque type itself or its children are not within its reveal scope.
-            if it.owner_id.def_id != self.def_id {
-                self.check(it.owner_id.def_id);
-                intravisit::walk_impl_item(self, it);
-            }
-        }
-        fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
-            trace!(?it.owner_id);
-            self.check(it.owner_id.def_id);
-            intravisit::walk_trait_item(self, it);
-        }
-    }
-
-    let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
-
-    if let Some(concrete) = concrete {
-        let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
-        debug!(?scope);
-        let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
-
-        match tcx.hir().get(scope) {
-            Node::Item(it) => intravisit::walk_item(&mut locator, it),
-            Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
-            Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
-            other => bug!("{:?} is not a valid scope for an opaque type item", other),
-        }
-    }
-
-    concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
-        let table = tcx.typeck(owner_def_id);
-        if let Some(guar) = table.tainted_by_errors {
-            // Some error in the
-            // owner fn prevented us from populating
-            // the `concrete_opaque_types` table.
-            tcx.ty_error(guar)
-        } else {
-            table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
-                // We failed to resolve the opaque type or it
-                // resolves to itself. We interpret this as the
-                // no values of the hidden type ever being constructed,
-                // so we can just make the hidden type be `!`.
-                // For backwards compatibility reasons, we fall back to
-                // `()` until we the diverging default is changed.
-                tcx.mk_diverging_default()
-            })
-        }
-    })
-}
-
 fn infer_placeholder_type<'a>(
     tcx: TyCtxt<'a>,
     def_id: LocalDefId,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
new file mode 100644
index 0000000..f7c5b44
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -0,0 +1,298 @@
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::DUMMY_SP;
+
+use crate::errors::UnconstrainedOpaqueType;
+
+/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
+/// laid for "higher-order pattern unification".
+/// This ensures that inference is tractable.
+/// In particular, definitions of opaque types can only use other generics as arguments,
+/// and they cannot repeat an argument. Example:
+///
+/// ```ignore (illustrative)
+/// type Foo<A, B> = impl Bar<A, B>;
+///
+/// // Okay -- `Foo` is applied to two distinct, generic types.
+/// fn a<T, U>() -> Foo<T, U> { .. }
+///
+/// // Not okay -- `Foo` is applied to `T` twice.
+/// fn b<T>() -> Foo<T, T> { .. }
+///
+/// // Not okay -- `Foo` is applied to a non-generic type.
+/// fn b<T>() -> Foo<T, u32> { .. }
+/// ```
+#[instrument(skip(tcx), level = "debug")]
+pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+    let scope = tcx.hir().get_defining_scope(hir_id);
+    let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
+
+    debug!(?scope);
+
+    if scope == hir::CRATE_HIR_ID {
+        tcx.hir().walk_toplevel_module(&mut locator);
+    } else {
+        trace!("scope={:#?}", tcx.hir().get(scope));
+        match tcx.hir().get(scope) {
+            // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
+            // This allows our visitor to process the defining item itself, causing
+            // it to pick up any 'sibling' defining uses.
+            //
+            // For example, this code:
+            // ```
+            // fn foo() {
+            //     type Blah = impl Debug;
+            //     let my_closure = || -> Blah { true };
+            // }
+            // ```
+            //
+            // requires us to explicitly process `foo()` in order
+            // to notice the defining usage of `Blah`.
+            Node::Item(it) => locator.visit_item(it),
+            Node::ImplItem(it) => locator.visit_impl_item(it),
+            Node::TraitItem(it) => locator.visit_trait_item(it),
+            other => bug!("{:?} is not a valid scope for an opaque type item", other),
+        }
+    }
+
+    let Some(hidden) = locator.found else {
+        let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
+            span: tcx.def_span(def_id),
+            name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
+            what: match tcx.hir().get(scope) {
+                _ if scope == hir::CRATE_HIR_ID => "module",
+                Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
+                Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
+                _ => "item",
+            },
+        });
+        return tcx.ty_error(reported);
+    };
+
+    // Only check against typeck if we didn't already error
+    if !hidden.ty.references_error() {
+        for concrete_type in locator.typeck_types {
+            if concrete_type.ty != tcx.erase_regions(hidden.ty)
+                && !(concrete_type, hidden).references_error()
+            {
+                hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+            }
+        }
+    }
+
+    hidden.ty
+}
+
+struct TaitConstraintLocator<'tcx> {
+    tcx: TyCtxt<'tcx>,
+
+    /// def_id of the opaque type whose defining uses are being checked
+    def_id: LocalDefId,
+
+    /// as we walk the defining uses, we are checking that all of them
+    /// define the same hidden type. This variable is set to `Some`
+    /// with the first type that we find, and then later types are
+    /// checked against it (we also carry the span of that first
+    /// type).
+    found: Option<ty::OpaqueHiddenType<'tcx>>,
+
+    /// In the presence of dead code, typeck may figure out a hidden type
+    /// while borrowck will not. We collect these cases here and check at
+    /// the end that we actually found a type that matches (modulo regions).
+    typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
+}
+
+impl TaitConstraintLocator<'_> {
+    #[instrument(skip(self), level = "debug")]
+    fn check(&mut self, item_def_id: LocalDefId) {
+        // Don't try to check items that cannot possibly constrain the type.
+        if !self.tcx.has_typeck_results(item_def_id) {
+            debug!("no constraint: no typeck results");
+            return;
+        }
+        // Calling `mir_borrowck` can lead to cycle errors through
+        // const-checking, avoid calling it if we don't have to.
+        // ```rust
+        // type Foo = impl Fn() -> usize; // when computing type for this
+        // const fn bar() -> Foo {
+        //     || 0usize
+        // }
+        // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
+        // // because we again need to reveal `Foo` so we can check whether the
+        // // constant does not contain interior mutability.
+        // ```
+        let tables = self.tcx.typeck(item_def_id);
+        if let Some(guar) = tables.tainted_by_errors {
+            self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
+            return;
+        }
+        let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
+            debug!("no constraints in typeck results");
+            return;
+        };
+        if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
+            self.typeck_types.push(typeck_hidden_ty);
+        }
+
+        // Use borrowck to get the type with unerased regions.
+        let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
+        debug!(?concrete_opaque_types);
+        if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
+            debug!(?concrete_type, "found constraint");
+            if let Some(prev) = &mut self.found {
+                if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
+                    let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+                    prev.ty = self.tcx.ty_error(guar);
+                }
+            } else {
+                self.found = Some(concrete_type);
+            }
+        }
+    }
+}
+
+impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
+    type NestedFilter = nested_filter::All;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.tcx.hir()
+    }
+    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+        if let hir::ExprKind::Closure(closure) = ex.kind {
+            self.check(closure.def_id);
+        }
+        intravisit::walk_expr(self, ex);
+    }
+    fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
+        trace!(?it.owner_id);
+        // The opaque type itself or its children are not within its reveal scope.
+        if it.owner_id.def_id != self.def_id {
+            self.check(it.owner_id.def_id);
+            intravisit::walk_item(self, it);
+        }
+    }
+    fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
+        trace!(?it.owner_id);
+        // The opaque type itself or its children are not within its reveal scope.
+        if it.owner_id.def_id != self.def_id {
+            self.check(it.owner_id.def_id);
+            intravisit::walk_impl_item(self, it);
+        }
+    }
+    fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
+        trace!(?it.owner_id);
+        self.check(it.owner_id.def_id);
+        intravisit::walk_trait_item(self, it);
+    }
+}
+
+pub(super) fn find_opaque_ty_constraints_for_rpit(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+    owner_def_id: LocalDefId,
+) -> Ty<'_> {
+    let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+
+    if let Some(concrete) = concrete {
+        let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
+        debug!(?scope);
+        let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
+
+        match tcx.hir().get(scope) {
+            Node::Item(it) => intravisit::walk_item(&mut locator, it),
+            Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
+            Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
+            other => bug!("{:?} is not a valid scope for an opaque type item", other),
+        }
+    }
+
+    concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
+        let table = tcx.typeck(owner_def_id);
+        if let Some(guar) = table.tainted_by_errors {
+            // Some error in the
+            // owner fn prevented us from populating
+            // the `concrete_opaque_types` table.
+            tcx.ty_error(guar)
+        } else {
+            table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+                // We failed to resolve the opaque type or it
+                // resolves to itself. We interpret this as the
+                // no values of the hidden type ever being constructed,
+                // so we can just make the hidden type be `!`.
+                // For backwards compatibility reasons, we fall back to
+                // `()` until we the diverging default is changed.
+                tcx.mk_diverging_default()
+            })
+        }
+    })
+}
+
+struct RpitConstraintChecker<'tcx> {
+    tcx: TyCtxt<'tcx>,
+
+    /// def_id of the opaque type whose defining uses are being checked
+    def_id: LocalDefId,
+
+    found: ty::OpaqueHiddenType<'tcx>,
+}
+
+impl RpitConstraintChecker<'_> {
+    #[instrument(skip(self), level = "debug")]
+    fn check(&self, def_id: LocalDefId) {
+        // Use borrowck to get the type with unerased regions.
+        let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
+        debug!(?concrete_opaque_types);
+        for (&def_id, &concrete_type) in concrete_opaque_types {
+            if def_id != self.def_id {
+                // Ignore constraints for other opaque types.
+                continue;
+            }
+
+            debug!(?concrete_type, "found constraint");
+
+            if concrete_type.ty != self.found.ty && !(concrete_type, self.found).references_error()
+            {
+                self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+            }
+        }
+    }
+}
+
+impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
+    type NestedFilter = nested_filter::OnlyBodies;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.tcx.hir()
+    }
+    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+        if let hir::ExprKind::Closure(closure) = ex.kind {
+            self.check(closure.def_id);
+        }
+        intravisit::walk_expr(self, ex);
+    }
+    fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
+        trace!(?it.owner_id);
+        // The opaque type itself or its children are not within its reveal scope.
+        if it.owner_id.def_id != self.def_id {
+            self.check(it.owner_id.def_id);
+            intravisit::walk_item(self, it);
+        }
+    }
+    fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
+        trace!(?it.owner_id);
+        // The opaque type itself or its children are not within its reveal scope.
+        if it.owner_id.def_id != self.def_id {
+            self.check(it.owner_id.def_id);
+            intravisit::walk_impl_item(self, it);
+        }
+    }
+    fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
+        trace!(?it.owner_id);
+        self.check(it.owner_id.def_id);
+        intravisit::walk_trait_item(self, it);
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 8269a6d..e4c6e6e 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -4,7 +4,7 @@
 use rustc_hir::{ForeignItem, ForeignItemKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::def_id::LocalDefId;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index f070b4f..612d4ff 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -15,7 +15,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::{Span, Symbol};
 
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 3fe34f2..5cd2cd5 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -104,7 +104,7 @@
 use rustc_hir::Node;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::middle;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::util;
 use rustc_session::{config::EntryFnType, parse::feature_err};
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 42612ee..a8596c7 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -1,7 +1,7 @@
 use hir::Node;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 6d1a163..ee34572 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -395,7 +395,7 @@
     ) -> String {
         let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig);
         let is_used_in_input = |def_id| {
-            fn_sig.map_or(false, |fn_sig| {
+            fn_sig.is_some_and(|fn_sig| {
                 fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
                     hir::TyKind::Path(hir::QPath::Resolved(
                         None,
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index e735b04..3ebd9e1 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -6,7 +6,7 @@
 use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
 use std::ops::ControlFlow;
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index aa66403..9761b1d 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -1,67 +1,20 @@
-hir_typeck_field_multiply_specified_in_initializer =
-    field `{$ident}` specified more than once
-    .label = used more than once
-    .previous_use_label = first use of `{$ident}`
-
-hir_typeck_functional_record_update_on_non_struct =
-    functional record update syntax requires a struct
-
-hir_typeck_return_stmt_outside_of_fn_body =
-    return statement outside of function body
-    .encl_body_label = the return is part of this body...
-    .encl_fn_label = ...not the enclosing function body
-
-hir_typeck_yield_expr_outside_of_generator =
-    yield expression outside of generator literal
-
-hir_typeck_struct_expr_non_exhaustive =
-    cannot create non-exhaustive {$what} using struct expression
-
-hir_typeck_method_call_on_unknown_type =
-    the type of this value must be known to call a method on a raw pointer on it
-
-hir_typeck_address_of_temporary_taken = cannot take address of a temporary
-    .label = temporary value
+hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
 
 hir_typeck_add_return_type_add = try adding a return type
 
 hir_typeck_add_return_type_missing_here = a return type might be missing here
 
-hir_typeck_expected_default_return_type = expected `()` because of default return type
+hir_typeck_address_of_temporary_taken = cannot take address of a temporary
+    .label = temporary value
 
-hir_typeck_expected_return_type = expected `{$expected}` because of return type
+hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
+    .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
 
-hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
-
-hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
-
-hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
-hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
-
-hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
-
-hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
-    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
-
-hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
-    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
-
-hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
-hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
-hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
-
-hir_typeck_convert_to_str = try converting the passed type into a `&str`
-
-hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
-
-hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
-hir_typeck_fru_expr = this expression does not end in a comma...
-hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
-hir_typeck_fru_suggestion =
-    to set the remaining fields{$expr ->
-        [NONE]{""}
-        *[other] {" "}from `{$expr}`
-    }, separate the last named field with a comma
+hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
+    [NONE] {""}
+    [implement] , perhaps you need to implement it
+    *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
+}
 
 hir_typeck_const_select_must_be_const = this argument must be a `const fn`
     .help = consult the documentation on `const_eval_select` for more information
@@ -70,12 +23,70 @@
     .note = expected a function item, found {$ty}
     .help = consult the documentation on `const_eval_select` for more information
 
-hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
-hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
+hir_typeck_convert_to_str = try converting the passed type into a `&str`
 
-hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
-    .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
+hir_typeck_expected_default_return_type = expected `()` because of default return type
+
+hir_typeck_expected_return_type = expected `{$expected}` because of return type
+
+hir_typeck_field_multiply_specified_in_initializer =
+    field `{$ident}` specified more than once
+    .label = used more than once
+    .previous_use_label = first use of `{$ident}`
+
+hir_typeck_fru_expr = this expression does not end in a comma...
+hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
+hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
+hir_typeck_fru_suggestion =
+    to set the remaining fields{$expr ->
+        [NONE]{""}
+        *[other] {" "}from `{$expr}`
+    }, separate the last named field with a comma
+
+hir_typeck_functional_record_update_on_non_struct =
+    functional record update syntax requires a struct
+
+hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+
+hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
+hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
+
+hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
+    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
+
+hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
+    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
+
+hir_typeck_method_call_on_unknown_type =
+    the type of this value must be known to call a method on a raw pointer on it
+
+hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
+
+hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
+    [true] {""}
+    *[other] {" "}in the current scope
+}
+
+hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+
+hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
+
+hir_typeck_return_stmt_outside_of_fn_body =
+    return statement outside of function body
+    .encl_body_label = the return is part of this body...
+    .encl_fn_label = ...not the enclosing function body
+
+hir_typeck_struct_expr_non_exhaustive =
+    cannot create non-exhaustive {$what} using struct expression
 
 hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
 
 hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
+
+hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
+
+hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
+hir_typeck_yield_expr_outside_of_generator =
+    yield expression outside of generator literal
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index a92f368..98c683f 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -465,7 +465,7 @@
                         .sess
                         .source_map()
                         .span_to_snippet(self.expr_span)
-                        .map_or(false, |snip| snip.starts_with('('));
+                        .is_ok_and(|snip| snip.starts_with('('));
 
                     // Very crude check to see whether the expression must be wrapped
                     // in parentheses for the suggestion to work (issue #89497).
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index bf8259f..bfabd44 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -32,6 +32,7 @@
     fn_def_id: LocalDefId,
     body: &'tcx hir::Body<'tcx>,
     can_be_generator: Option<hir::Movability>,
+    params_can_be_unsized: bool,
 ) -> Option<GeneratorTypes<'tcx>> {
     let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
 
@@ -94,7 +95,7 @@
         // The check for a non-trivial pattern is a hack to avoid duplicate warnings
         // for simple cases like `fn foo(x: Trait)`,
         // where we would error once on the parameter as a whole, and once on the binding `x`.
-        if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params {
+        if param.pat.simple_ident().is_none() && !params_can_be_unsized {
             fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
         }
 
@@ -103,24 +104,8 @@
 
     fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
 
-    if let ty::Dynamic(_, _, ty::Dyn) = declared_ret_ty.kind() {
-        // FIXME: We need to verify that the return type is `Sized` after the return expression has
-        // been evaluated so that we have types available for all the nodes being returned, but that
-        // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
-        // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
-        // while keeping the current ordering we will ignore the tail expression's type because we
-        // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
-        // because we will trigger "unreachable expression" lints unconditionally.
-        // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
-        // case that a newcomer might make, returning a bare trait, and in that case we populate
-        // the tail expression's type so that the suggestion will be correct, but ignore all other
-        // possible cases.
-        fcx.check_expr(&body.value);
-        fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
-    } else {
-        fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
-        fcx.check_return_expr(&body.value, false);
-    }
+    fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
+    fcx.check_return_expr(&body.value, false);
 
     // We insert the deferred_generator_interiors entry after visiting the body.
     // This ensures that all nested generators appear before the entry of this generator.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 7046269..9659a0e 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -89,6 +89,8 @@
             expr_def_id,
             body,
             closure.movability,
+            // Closure "rust-call" ABI doesn't support unsized params
+            false,
         );
 
         let parent_substs = InternalSubsts::identity_for_item(
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index cfe8d59..08c4082 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1814,7 +1814,7 @@
             .span_to_snippet(return_sp)
             .unwrap_or_else(|_| "dyn Trait".to_string());
         let mut snippet_iter = snippet.split_whitespace();
-        let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
+        let has_impl = snippet_iter.next().is_some_and(|s| s == "impl");
         // Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
         let mut is_object_safe = false;
         if let hir::FnRetTy::Return(ty) = fn_output
@@ -1834,7 +1834,7 @@
                     bound
                         .trait_ref()
                         .and_then(|t| t.trait_def_id())
-                        .map_or(false, |def_id| {
+                        .is_some_and(|def_id| {
                             fcx.tcx.check_is_object_safe(def_id)
                         })
                 })
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 2defca5..b50630e 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1748,8 +1748,7 @@
             |err: &mut Diagnostic,
              found_to_exp_is_fallible: bool,
              exp_to_found_is_fallible: bool| {
-                let exp_is_lhs =
-                    expected_ty_expr.map(|e| self.tcx.hir().is_lhs(e.hir_id)).unwrap_or(false);
+                let exp_is_lhs = expected_ty_expr.is_some_and(|e| self.tcx.hir().is_lhs(e.hir_id));
 
                 if exp_is_lhs {
                     return;
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index ce30bbe..102a313 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -1,4 +1,6 @@
 //! Errors emitted by `rustc_hir_typeck`.
+use std::borrow::Cow;
+
 use crate::fluent_generated as fluent;
 use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage};
 use rustc_macros::{Diagnostic, Subdiagnostic};
@@ -295,3 +297,25 @@
         end: Span,
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_no_associated_item, code = "E0599")]
+pub struct NoAssociatedItem {
+    #[primary_span]
+    pub span: Span,
+    pub item_kind: &'static str,
+    pub item_name: Ident,
+    pub ty_prefix: Cow<'static, str>,
+    pub ty_str: String,
+    pub trait_missing_method: bool,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_typeck_candidate_trait_note)]
+pub struct CandidateTraitNote {
+    #[primary_span]
+    pub span: Span,
+    pub trait_name: String,
+    pub item_name: Ident,
+    pub action_or_ty: String,
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index bba049c..19ff77d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -497,7 +497,7 @@
                 .borrow()
                 .adjustments()
                 .get(base.hir_id)
-                .map_or(false, |x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
+                .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
         });
         if !is_named {
             self.tcx.sess.emit_err(AddressOfTemporaryTaken { span: oprnd.span });
@@ -721,7 +721,7 @@
                 // ICE this expression in particular (see #43162).
                 if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind {
                     if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust {
-                        fatally_break_rust(self.tcx.sess);
+                        fatally_break_rust(self.tcx);
                     }
                 }
             }
@@ -1245,6 +1245,7 @@
                         error,
                         Some((rcvr, args)),
                         expected,
+                        false,
                     ) {
                         err.emit();
                     }
@@ -2468,7 +2469,7 @@
         {
             self.suggest_method_call(
                 &mut err,
-                &format!("a method `{field}` also exists, call it with parentheses"),
+                format!("a method `{field}` also exists, call it with parentheses"),
                 field,
                 expr_t,
                 expr,
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 94b6a0f..e14e8ac 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -438,12 +438,19 @@
                         // to borrow discr.
                         needs_to_be_read = true;
                     }
-                    PatKind::Or(_)
-                    | PatKind::Box(_)
-                    | PatKind::Slice(..)
-                    | PatKind::Ref(..)
-                    | PatKind::Wild => {
-                        // If the PatKind is Or, Box, Slice or Ref, the decision is made later
+                    PatKind::Slice(lhs, wild, rhs) => {
+                        // We don't need to test the length if the pattern is `[..]`
+                        if matches!((lhs, wild, rhs), (&[], Some(_), &[]))
+                            // Arrays have a statically known size, so
+                            // there is no need to read their length
+                            || discr_place.place.base_ty.is_array()
+                        {
+                        } else {
+                            needs_to_be_read = true;
+                        }
+                    }
+                    PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => {
+                        // If the PatKind is Or, Box, or Ref, the decision is made later
                         // as these patterns contains subpatterns
                         // If the PatKind is Wild, the decision is made based on the other patterns being
                         // examined
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 9e78e6a..2fdcd09 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -4,7 +4,7 @@
 use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -35,7 +35,9 @@
 use rustc_span::Span;
 use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCauseCode, ObligationCtxt};
+use rustc_trait_selection::traits::{
+    self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt,
+};
 
 use std::collections::hash_map::Entry;
 use std::slice;
@@ -853,6 +855,13 @@
         let item_name = item_segment.ident;
         let result = self
             .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
+            .and_then(|r| {
+                // lint bare trait if the method is found in the trait
+                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                    diag.emit();
+                }
+                Ok(r)
+            })
             .or_else(|error| {
                 let guar = self
                     .tcx
@@ -863,17 +872,30 @@
                     _ => Err(guar),
                 };
 
+                let trait_missing_method =
+                    matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
                 // If we have a path like `MyTrait::missing_method`, then don't register
                 // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
                 // register a WF obligation so that we can detect any additional
                 // errors in the self type.
-                if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
+                if !trait_missing_method {
                     self.register_wf_obligation(
                         ty.raw.into(),
                         qself.span,
                         traits::WellFormed(None),
                     );
                 }
+
+                // emit or cancel the diagnostic for bare traits
+                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                    if trait_missing_method {
+                        // cancel the diag for bare traits when meeting `MyTrait::missing_method`
+                        diag.cancel();
+                    } else {
+                        diag.emit();
+                    }
+                }
+
                 if item_name.name != kw::Empty {
                     if let Some(mut e) = self.report_method_error(
                         span,
@@ -883,10 +905,12 @@
                         error,
                         None,
                         Expectation::NoExpectation,
+                        trait_missing_method && span.edition().rust_2021(), // emits missing method for trait only after edition 2021
                     ) {
                         e.emit();
                     }
                 }
+
                 result
             });
 
@@ -993,8 +1017,8 @@
             .typeck_results
             .borrow()
             .expr_ty_adjusted_opt(rcvr)
-            .and_then(|ty| expected.map(|expected_ty| expected_ty.peel_refs() == ty.peel_refs()))
-            .unwrap_or(false);
+            .zip(expected)
+            .is_some_and(|(ty, expected_ty)| expected_ty.peel_refs() == ty.peel_refs());
 
         let prev_call_mutates_and_returns_unit = || {
             self.typeck_results
@@ -1002,14 +1026,13 @@
                 .type_dependent_def_id(expr.hir_id)
                 .map(|def_id| self.tcx.fn_sig(def_id).skip_binder().skip_binder())
                 .and_then(|sig| sig.inputs_and_output.split_last())
-                .map(|(output, inputs)| {
+                .is_some_and(|(output, inputs)| {
                     output.is_unit()
                         && inputs
                             .get(0)
                             .and_then(|self_ty| self_ty.ref_mutability())
-                            .map_or(false, rustc_ast::Mutability::is_mut)
+                            .is_some_and(rustc_ast::Mutability::is_mut)
                 })
-                .unwrap_or(false)
         };
 
         if !(rcvr_has_the_expected_type || prev_call_mutates_and_returns_unit()) {
@@ -1176,10 +1199,8 @@
             }
         }
 
-        let has_self = path_segs
-            .last()
-            .map(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self)
-            .unwrap_or(false);
+        let has_self =
+            path_segs.last().is_some_and(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self);
 
         let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
             let ty = self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id).subst_identity());
@@ -1438,10 +1459,33 @@
     }
 
     /// Resolves `typ` by a single level if `typ` is a type variable.
+    ///
+    /// When the new solver is enabled, this will also attempt to normalize
+    /// the type if it's a projection (note that it will not deeply normalize
+    /// projections within the type, just the outermost layer of the type).
+    ///
     /// If no resolution is possible, then an error is reported.
     /// Numeric inference variables may be left unresolved.
     pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let ty = self.resolve_vars_with_obligations(ty);
+        let mut ty = self.resolve_vars_with_obligations(ty);
+
+        if self.tcx.trait_solver_next()
+            && let ty::Alias(ty::Projection, _) = ty.kind()
+        {
+            match self
+                .at(&self.misc(sp), self.param_env)
+                .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut())
+            {
+                Ok(normalized_ty) => {
+                    ty = normalized_ty;
+                },
+                Err(errors) => {
+                    let guar = self.err_ctxt().report_fulfillment_errors(&errors);
+                    return self.tcx.ty_error(guar);
+                }
+            }
+        }
+
         if !ty.is_ty_var() {
             ty
         } else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index c7011b2..72c42f8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -876,7 +876,7 @@
         let mut errors = errors.into_iter().peekable();
         let mut only_extras_so_far = errors
             .peek()
-            .map_or(false, |first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
+            .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
         let mut suggestions = vec![];
         while let Some(error) = errors.next() {
             only_extras_so_far &= matches!(error, Error::Extra(_));
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
index cd3966a..ecafbd6 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
@@ -193,7 +193,7 @@
             .get(&TrackedValue::Temporary(hir_id))
             .or(self.tracked_value_map.get(&TrackedValue::Variable(hir_id)))
             .cloned()
-            .map_or(false, |tracked_value_id| {
+            .is_some_and(|tracked_value_id| {
                 self.expect_node(location.into()).drop_state.contains(tracked_value_id)
             })
     }
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index 4110b17..294c3bb 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -4,7 +4,8 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::HirIdMap;
-use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefIdMap;
@@ -130,7 +131,7 @@
         // (*) binder skipped
         if let ty::PredicateKind::Clause(ty::Clause::Trait(tpred)) = obligation.predicate.kind().skip_binder()
             && let Some(ty) = self.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| self.root_var(t))
-            && self.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
+            && self.tcx.lang_items().sized_trait().is_some_and(|st| st != tpred.trait_ref.def_id)
         {
             let new_self_ty = self.tcx.types.unit;
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index dcc3234..b97b55d 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -68,11 +68,10 @@
 use rustc_hir_analysis::astconv::AstConv;
 use rustc_hir_analysis::check::check_abi;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_middle::query::Providers;
 use rustc_middle::traits;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config;
-use rustc_session::Session;
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::{sym, Span};
 
@@ -213,7 +212,7 @@
         let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
         let fn_sig = fcx.normalize(body.value.span, fn_sig);
 
-        check_fn(&mut fcx, fn_sig, decl, def_id, body, None);
+        check_fn(&mut fcx, fn_sig, decl, def_id, body, None, tcx.features().unsized_fn_params);
     } else {
         let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty {
             Some(fcx.next_ty_var(TypeVariableOrigin {
@@ -438,8 +437,8 @@
     TupleArguments,
 }
 
-fn fatally_break_rust(sess: &Session) {
-    let handler = sess.diagnostic();
+fn fatally_break_rust(tcx: TyCtxt<'_>) {
+    let handler = tcx.sess.diagnostic();
     handler.span_bug_no_panic(
         MultiSpan::new(),
         "It looks like you're trying to break rust; would you like some ICE?",
@@ -451,7 +450,7 @@
     );
     handler.note_without_error(format!(
         "rustc {} running on {}",
-        option_env!("CFG_VERSION").unwrap_or("unknown_version"),
+        tcx.sess.cfg_version,
         config::host_triple(),
     ));
 }
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index f5fca14..78171e0 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -411,7 +411,7 @@
             }
 
             Res::Local(var_id) => {
-                if self.upvars.map_or(false, |upvars| upvars.contains_key(&var_id)) {
+                if self.upvars.is_some_and(|upvars| upvars.contains_key(&var_id)) {
                     self.cat_upvar(hir_id, var_id)
                 } else {
                     Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Local(var_id), Vec::new()))
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 9155a3d..98529b6 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -158,7 +158,7 @@
         let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
             return self.tcx.ty_error_with_message(
                 rustc_span::DUMMY_SP,
-                &format!("failed autoderef {}", pick.autoderefs),
+                format!("failed autoderef {}", pick.autoderefs),
             );
         };
         assert_eq!(n, pick.autoderefs);
@@ -471,7 +471,7 @@
             self_ty, method_self_ty, self.span, pick
         );
         let cause = self.cause(
-            self.span,
+            self.self_expr.span,
             ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext {
                 assoc_item: pick.item,
                 param_env: self.param_env,
@@ -482,13 +482,22 @@
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
             }
-            Err(_) => {
-                span_bug!(
-                    self.span,
-                    "{} was a subtype of {} but now is not?",
-                    self_ty,
-                    method_self_ty
-                );
+            Err(terr) => {
+                // FIXME(arbitrary_self_types): We probably should limit the
+                // situations where this can occur by adding additional restrictions
+                // to the feature, like the self type can't reference method substs.
+                if self.tcx.features().arbitrary_self_types {
+                    self.err_ctxt()
+                        .report_mismatched_types(&cause, method_self_ty, self_ty, terr)
+                        .emit();
+                } else {
+                    span_bug!(
+                        self.span,
+                        "{} was a subtype of {} but now is not?",
+                        self_ty,
+                        method_self_ty
+                    );
+                }
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 5963a16..6f4d674 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -13,11 +13,12 @@
 use crate::errors::OpMethodGenericParams;
 use crate::FnCtxt;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{Applicability, Diagnostic, SubdiagnosticMessage};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
+use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
@@ -28,7 +29,7 @@
 
 use self::probe::{IsSuggestion, ProbeScope};
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     probe::provide(providers);
 }
 
@@ -129,7 +130,7 @@
     pub(crate) fn suggest_method_call(
         &self,
         err: &mut Diagnostic,
-        msg: &str,
+        msg: impl Into<SubdiagnosticMessage> + std::fmt::Debug,
         method_name: Ident,
         self_ty: Ty<'tcx>,
         call_expr: &hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 483e174..ba21ede 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -16,6 +16,7 @@
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_middle::middle::stability;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::AssocItem;
 use rustc_middle::ty::GenericParamDefKind;
@@ -495,7 +496,7 @@
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.method_autoderef_steps = method_autoderef_steps;
 }
 
@@ -1193,7 +1194,7 @@
                     pick.autoderefs += 1;
                     pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
                         mutbl,
-                        unsize: pick.autoref_or_ptr_adjustment.map_or(false, |a| a.get_unsize()),
+                        unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()),
                     })
                 }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 486c217..8555c20 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2,6 +2,8 @@
 //! found or is otherwise invalid.
 
 use crate::errors;
+use crate::errors::CandidateTraitNote;
+use crate::errors::NoAssociatedItem;
 use crate::Expectation;
 use crate::FnCtxt;
 use rustc_ast::ast::Mutability;
@@ -38,6 +40,7 @@
 use rustc_trait_selection::traits::{
     FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
 };
+use std::borrow::Cow;
 
 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
@@ -112,6 +115,7 @@
         error: MethodError<'tcx>,
         args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
         expected: Expectation<'tcx>,
+        trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
@@ -136,6 +140,7 @@
                     sugg_span,
                     &mut no_match_data,
                     expected,
+                    trait_missing_method,
                 );
             }
 
@@ -278,12 +283,17 @@
         sugg_span: Span,
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
+        trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
         let mode = no_match_data.mode;
         let tcx = self.tcx;
         let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
-        let (ty_str, ty_file) = tcx.short_ty_string(rcvr_ty);
-        let short_ty_str = with_forced_trimmed_paths!(rcvr_ty.to_string());
+        let ((mut ty_str, ty_file), short_ty_str) = if trait_missing_method
+            && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
+                ((predicates.to_string(), None), with_forced_trimmed_paths!(predicates.to_string()))
+            } else {
+                (tcx.short_ty_string(rcvr_ty), with_forced_trimmed_paths!(rcvr_ty.to_string()))
+            };
         let is_method = mode == Mode::MethodCall;
         let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
         let similar_candidate = no_match_data.similar_candidate;
@@ -346,7 +356,7 @@
             }
         }
 
-        let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.map_or(false, |def_id| {
+        let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
             tcx.is_diagnostic_item(sym::write_macro, def_id)
                 || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
         }) && item_name.name == Symbol::intern("write_fmt");
@@ -355,25 +365,28 @@
         {
             self.suggest_missing_writer(rcvr_ty, args)
         } else {
-            struct_span_err!(
-                tcx.sess,
+            tcx.sess.create_err(NoAssociatedItem {
                 span,
-                E0599,
-                "no {} named `{}` found for {} `{}` in the current scope",
                 item_kind,
                 item_name,
-                rcvr_ty.prefix_string(self.tcx),
-                ty_str_reported,
-            )
+                ty_prefix: if trait_missing_method {
+                    // FIXME(mu001999) E0599 maybe not suitable here because it is for types
+                    Cow::from("trait")
+                } else {
+                    rcvr_ty.prefix_string(self.tcx)
+                },
+                ty_str: ty_str_reported,
+                trait_missing_method,
+            })
         };
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
         }
-        let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
-            short_ty_str
-        } else {
-            ty_str
-        };
+
+        if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
+            ty_str = short_ty_str;
+        }
+
         if let Some(file) = ty_file {
             err.note(format!("the full type name has been written to '{}'", file.display(),));
         }
@@ -1067,6 +1080,7 @@
                 &static_candidates,
                 unsatisfied_bounds,
                 expected.only_has_type(self),
+                trait_missing_method,
             );
         }
 
@@ -1508,7 +1522,7 @@
 
                     let span_included = match parent_expr.kind {
                         hir::ExprKind::Struct(_, eps, _) => {
-                            eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
+                            eps.len() > 0 && eps.last().is_some_and(|ep| ep.span.contains(span))
                         }
                         // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
                         hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
@@ -1767,7 +1781,7 @@
                                 ProbeScope::TraitsInScope,
                                 return_type,
                             )
-                            .map_or(false, |pick| {
+                            .is_ok_and(|pick| {
                                 !never_mention_traits
                                     .iter()
                                     .flatten()
@@ -2375,6 +2389,7 @@
         static_candidates: &[CandidateSource],
         unsatisfied_bounds: bool,
         return_type: Option<Ty<'tcx>>,
+        trait_missing_method: bool,
     ) {
         let mut alt_rcvr_sugg = false;
         if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
@@ -2453,7 +2468,7 @@
                         // implement the `AsRef` trait.
                         let skip = skippable.contains(&did)
                             || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
-                            || inputs_len.map_or(false, |inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
+                            || inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
                         // Make sure the method is defined for the *actual* receiver: we don't
                         // want to treat `Box<Self>` as a receiver if it only works because of
                         // an autoderef to `&self`
@@ -2598,11 +2613,14 @@
                 },
                 _ => None,
             };
-            err.help(if param_type.is_some() {
-                "items from traits can only be used if the type parameter is bounded by the trait"
-            } else {
-                "items from traits can only be used if the trait is implemented and in scope"
-            });
+            if !trait_missing_method {
+                err.help(if param_type.is_some() {
+                    "items from traits can only be used if the type parameter is bounded by the trait"
+                } else {
+                    "items from traits can only be used if the trait is implemented and in scope"
+                });
+            }
+
             let candidates_len = candidates.len();
             let message = |action| {
                 format!(
@@ -2633,47 +2651,62 @@
                                 Nothing,
                             }
                             let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
-                            let (sp, mut introducer) = if let Some(span) =
-                                ast_generics.bounds_span_for_suggestions(def_id)
-                            {
-                                (span, Introducer::Plus)
-                            } else if let Some(colon_span) = param.colon_span {
-                                (colon_span.shrink_to_hi(), Introducer::Nothing)
-                            } else {
-                                (param.span.shrink_to_hi(), Introducer::Colon)
-                            };
-                            if matches!(
-                                param.kind,
-                                hir::GenericParamKind::Type { synthetic: true, .. },
-                            ) {
-                                introducer = Introducer::Plus
-                            }
                             let trait_def_ids: FxHashSet<DefId> = ast_generics
                                 .bounds_for_param(def_id)
                                 .flat_map(|bp| bp.bounds.iter())
                                 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
                                 .collect();
-                            if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
-                                err.span_suggestions(
-                                    sp,
-                                    message(format!(
-                                        "restrict type parameter `{}` with",
-                                        param.name.ident(),
-                                    )),
+                            if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
+                                return;
+                            }
+                            let msg = message(format!(
+                                "restrict type parameter `{}` with",
+                                param.name.ident(),
+                            ));
+                            let bounds_span = ast_generics.bounds_span_for_suggestions(def_id);
+                            if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
+                                err.multipart_suggestions(
+                                    msg,
                                     candidates.iter().map(|t| {
-                                        format!(
-                                            "{} {}",
-                                            match introducer {
-                                                Introducer::Plus => " +",
-                                                Introducer::Colon => ":",
-                                                Introducer::Nothing => "",
-                                            },
-                                            self.tcx.def_path_str(t.def_id),
-                                        )
+                                        vec![
+                                            (param.span.shrink_to_lo(), "(".to_string()),
+                                            (
+                                                bounds_span.unwrap(),
+                                                format!(" + {})", self.tcx.def_path_str(t.def_id)),
+                                            ),
+                                        ]
                                     }),
                                     Applicability::MaybeIncorrect,
                                 );
+                                return;
                             }
+
+                            let (sp, introducer) = if let Some(span) = bounds_span {
+                                (span, Introducer::Plus)
+                            } else if let Some(colon_span) = param.colon_span {
+                                (colon_span.shrink_to_hi(), Introducer::Nothing)
+                            } else if param.is_impl_trait() {
+                                (param.span.shrink_to_hi(), Introducer::Plus)
+                            } else {
+                                (param.span.shrink_to_hi(), Introducer::Colon)
+                            };
+
+                            err.span_suggestions(
+                                sp,
+                                msg,
+                                candidates.iter().map(|t| {
+                                    format!(
+                                        "{} {}",
+                                        match introducer {
+                                            Introducer::Plus => " +",
+                                            Introducer::Colon => ":",
+                                            Introducer::Nothing => "",
+                                        },
+                                        self.tcx.def_path_str(t.def_id)
+                                    )
+                                }),
+                                Applicability::MaybeIncorrect,
+                            );
                             return;
                         }
                         Node::Item(hir::Item {
@@ -2722,7 +2755,7 @@
                             let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
                             let imp_simp =
                                 simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
-                            imp_simp.map_or(false, |s| s == simp_rcvr_ty)
+                            imp_simp.is_some_and(|s| s == simp_rcvr_ty)
                         })
                     {
                         explicitly_negative.push(candidate);
@@ -2736,27 +2769,28 @@
                 (candidates, Vec::new())
             };
 
-            let action = if let Some(param) = param_type {
-                format!("restrict type parameter `{}` with", param)
-            } else {
-                // FIXME: it might only need to be imported into scope, not implemented.
-                "implement".to_string()
-            };
             match &potential_candidates[..] {
                 [] => {}
                 [trait_info] if trait_info.def_id.is_local() => {
-                    err.span_note(
-                        self.tcx.def_span(trait_info.def_id),
-                        format!(
-                            "`{}` defines an item `{}`, perhaps you need to {} it",
-                            self.tcx.def_path_str(trait_info.def_id),
-                            item_name,
-                            action
-                        ),
-                    );
+                    err.subdiagnostic(CandidateTraitNote {
+                        span: self.tcx.def_span(trait_info.def_id),
+                        trait_name: self.tcx.def_path_str(trait_info.def_id),
+                        item_name,
+                        action_or_ty: if trait_missing_method {
+                            "NONE".to_string()
+                        } else {
+                            param_type.map_or_else(
+                                || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
+                                ToString::to_string,
+                            )
+                        },
+                    });
                 }
                 trait_infos => {
-                    let mut msg = message(action);
+                    let mut msg = message(param_type.map_or_else(
+                        || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
+                        |param| format!("restrict type parameter `{}` with", param),
+                    ));
                     for (i, trait_info) in trait_infos.iter().enumerate() {
                         msg.push_str(&format!(
                             "\ncandidate #{}: `{}`",
@@ -2859,7 +2893,7 @@
             match ty.kind() {
                 ty::Adt(def, _) => def.did().is_local(),
                 ty::Foreign(did) => did.is_local(),
-                ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
+                ty::Dynamic(tr, ..) => tr.principal().is_some_and(|d| d.def_id().is_local()),
                 ty::Param(_) => true,
 
                 // Everything else (primitive types, etc.) is effectively
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index af351a3..b8bf2b6 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -549,9 +549,8 @@
         let to_owned_msg = "create an owned `String` from a string reference";
 
         let string_type = self.tcx.lang_items().string();
-        let is_std_string = |ty: Ty<'tcx>| {
-            ty.ty_adt_def().map_or(false, |ty_def| Some(ty_def.did()) == string_type)
-        };
+        let is_std_string =
+            |ty: Ty<'tcx>| ty.ty_adt_def().is_some_and(|ty_def| Some(ty_def.did()) == string_type);
 
         match (lhs_ty.kind(), rhs_ty.kind()) {
             (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str
@@ -760,8 +759,7 @@
             span,
             traits::BinOp {
                 rhs_span: opt_rhs_expr.map(|expr| expr.span),
-                is_lit: opt_rhs_expr
-                    .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
+                is_lit: opt_rhs_expr.is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
                 output_ty: expected.only_has_type(self),
             },
         );
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index f217c5c..e2b1dc0 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -329,7 +329,7 @@
                         // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
                         // This helps avoid accidental drops.
                         if inside_union
-                            && source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop())
+                            && source.ty_adt_def().is_some_and(|adt| adt.is_manually_drop())
                         {
                             let mut err = self.tcx.sess.struct_span_err(
                                 expr.span,
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 543194a..9458099 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -972,15 +972,11 @@
         let mut obligations_should_hold = Vec::new();
         // Checks if a root variable implements any of the auto traits
         for check_trait in auto_traits_def_id.iter() {
-            obligations_should_hold.push(
-                check_trait
-                    .map(|check_trait| {
-                        self.infcx
-                            .type_implements_trait(check_trait, [ty], self.param_env)
-                            .must_apply_modulo_regions()
-                    })
-                    .unwrap_or(false),
-            );
+            obligations_should_hold.push(check_trait.is_some_and(|check_trait| {
+                self.infcx
+                    .type_implements_trait(check_trait, [ty], self.param_env)
+                    .must_apply_modulo_regions()
+            }));
         }
 
         let mut problematic_captures = FxHashMap::default();
@@ -996,15 +992,11 @@
             // Checks if a capture implements any of the auto traits
             let mut obligations_holds_for_capture = Vec::new();
             for check_trait in auto_traits_def_id.iter() {
-                obligations_holds_for_capture.push(
-                    check_trait
-                        .map(|check_trait| {
-                            self.infcx
-                                .type_implements_trait(check_trait, [ty], self.param_env)
-                                .must_apply_modulo_regions()
-                        })
-                        .unwrap_or(false),
-                );
+                obligations_holds_for_capture.push(check_trait.is_some_and(|check_trait| {
+                    self.infcx
+                        .type_implements_trait(check_trait, [ty], self.param_env)
+                        .must_apply_modulo_regions()
+                }));
             }
 
             let mut capture_problems = FxHashSet::default();
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index cf95d4f..0f21fc1 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -5,11 +5,10 @@
 use crate::FnCtxt;
 use hir::def_id::LocalDefId;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
-use rustc_infer::infer::InferCtxt;
 use rustc_middle::hir::place::Place as HirPlace;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
@@ -83,10 +82,6 @@
         wbcx.typeck_results.treat_byte_string_as_slice =
             mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
 
-        if let Some(e) = self.tainted_by_errors() {
-            wbcx.typeck_results.tainted_by_errors = Some(e);
-        }
-
         debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
 
         self.tcx.arena.alloc(wbcx.typeck_results)
@@ -119,12 +114,21 @@
     ) -> WritebackCx<'cx, 'tcx> {
         let owner = body.id().hir_id.owner;
 
-        WritebackCx {
+        let mut wbcx = WritebackCx {
             fcx,
             typeck_results: ty::TypeckResults::new(owner),
             body,
             rustc_dump_user_substs,
+        };
+
+        // HACK: We specifically don't want the (opaque) error from tainting our
+        // inference context. That'll prevent us from doing opaque type inference
+        // later on in borrowck, which affects diagnostic spans pretty negatively.
+        if let Some(e) = fcx.tainted_by_errors() {
+            wbcx.typeck_results.tainted_by_errors = Some(e);
         }
+
+        wbcx
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -237,7 +241,7 @@
                     // error has been emitted. (#64638)
                     self.fcx.tcx.ty_error_with_message(
                         e.span,
-                        &format!("bad index {:?} for base: `{:?}`", index, base),
+                        format!("bad index {:?} for base: `{:?}`", index, base),
                     )
                 });
                 let index_ty = self.fcx.resolve_vars_if_possible(index_ty);
@@ -579,13 +583,26 @@
                 continue;
             }
 
-            let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
-                opaque_type_key,
-                self.fcx.infcx.tcx,
-                true,
-            );
+            let hidden_type =
+                self.tcx().erase_regions(hidden_type.remap_generic_params_to_declaration_params(
+                    opaque_type_key,
+                    self.tcx(),
+                    true,
+                ));
 
-            self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type);
+            if let Some(last_opaque_ty) = self
+                .typeck_results
+                .concrete_opaque_types
+                .insert(opaque_type_key.def_id, hidden_type)
+                && last_opaque_ty.ty != hidden_type.ty
+            {
+                hidden_type
+                    .report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
+                    .stash(
+                        self.tcx().def_span(opaque_type_key.def_id),
+                        StashKey::OpaqueHiddenTypeMismatch,
+                    );
+            }
         }
     }
 
@@ -692,15 +709,7 @@
             fcx_typeck_results.offset_of_data().items_in_stable_order()
         {
             let hir_id = hir::HirId { owner: common_hir_owner, local_id };
-
-            if cfg!(debug_assertions) && container.has_infer() {
-                span_bug!(
-                    hir_id.to_span(self.fcx.tcx),
-                    "writeback: `{:?}` has inference variables",
-                    container
-                );
-            };
-
+            let container = self.resolve(container, &hir_id);
             self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
         }
     }
@@ -745,8 +754,7 @@
 /// The Resolver. This is the type folding engine that detects
 /// unresolved types and so forth.
 struct Resolver<'cx, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    infcx: &'cx InferCtxt<'tcx>,
+    fcx: &'cx FnCtxt<'cx, 'tcx>,
     span: &'cx dyn Locatable,
     body: &'tcx hir::Body<'tcx>,
 
@@ -760,18 +768,18 @@
         span: &'cx dyn Locatable,
         body: &'tcx hir::Body<'tcx>,
     ) -> Resolver<'cx, 'tcx> {
-        Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: None }
+        Resolver { fcx, span, body, replaced_with_error: None }
     }
 
     fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
-        match self.tcx.sess.has_errors() {
+        match self.fcx.tcx.sess.has_errors() {
             Some(e) => e,
             None => self
-                .infcx
+                .fcx
                 .err_ctxt()
                 .emit_inference_failure_err(
-                    self.tcx.hir().body_owner_def_id(self.body.id()),
-                    self.span.to_span(self.tcx),
+                    self.fcx.tcx.hir().body_owner_def_id(self.body.id()),
+                    self.span.to_span(self.fcx.tcx),
                     p.into(),
                     E0282,
                     false,
@@ -803,40 +811,46 @@
 
 impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
     fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
+        self.fcx.tcx
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        match self.infcx.fully_resolve(t) {
+        match self.fcx.fully_resolve(t) {
+            Ok(t) if self.fcx.tcx.trait_solver_next() => {
+                // We must normalize erasing regions here, since later lints
+                // expect that types that show up in the typeck are fully
+                // normalized.
+                self.fcx.tcx.try_normalize_erasing_regions(self.fcx.param_env, t).unwrap_or(t)
+            }
             Ok(t) => {
                 // Do not anonymize late-bound regions
                 // (e.g. keep `for<'a>` named `for<'a>`).
                 // This allows NLL to generate error messages that
                 // refer to the higher-ranked lifetime names written by the user.
-                EraseEarlyRegions { tcx: self.tcx }.fold_ty(t)
+                EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t)
             }
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 let e = self.report_error(t);
                 self.replaced_with_error = Some(e);
-                self.interner().ty_error(e)
+                self.fcx.tcx.ty_error(e)
             }
         }
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
-        self.tcx.lifetimes.re_erased
+        self.fcx.tcx.lifetimes.re_erased
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match self.infcx.fully_resolve(ct) {
-            Ok(ct) => self.tcx.erase_regions(ct),
+        match self.fcx.fully_resolve(ct) {
+            Ok(ct) => self.fcx.tcx.erase_regions(ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 let e = self.report_error(ct);
                 self.replaced_with_error = Some(e);
-                self.interner().const_error_with_guaranteed(ct.ty(), e)
+                self.fcx.tcx.const_error(ct.ty(), e)
             }
         }
     }
diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl
index b760620..9fa4e0f 100644
--- a/compiler/rustc_incremental/messages.ftl
+++ b/compiler/rustc_incremental/messages.ftl
@@ -1,118 +1,118 @@
-incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
+incremental_assert_loaded =
+    we asserted that an existing incremental cache directory should be successfully loaded, but it was not
 
-incremental_missing_depnode = missing `DepNode` variant
-
-incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
-
-incremental_no_path = no path from `{$source}` to `{$target}`
-
-incremental_ok = OK
-
-incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
-
-incremental_missing_query_depgraph =
-    found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
-
-incremental_malformed_cgu_name =
-    found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
-
-incremental_no_module_named =
-    no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
-
-incremental_field_associated_value_expected = associated value expected for `{$name}`
-
-incremental_no_field = no field `{$name}`
+incremental_assert_not_loaded =
+    we asserted that the incremental cache should not be loaded, but it was loaded
 
 incremental_assertion_auto =
     `except` specified DepNodes that can not be affected for "{$name}": "{$e}"
 
-incremental_undefined_clean_dirty_assertions_item =
-    clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
-
-incremental_undefined_clean_dirty_assertions =
-    clean/dirty auto-assertions not yet defined for {$kind}
-
-incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
-
-incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
-
-incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
-
-incremental_not_clean = `{$dep_node_str}` should be clean but is not
-
-incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
-
-incremental_unknown_item = unknown item `{$name}`
-
-incremental_no_cfg = no cfg attribute
+incremental_associated_value_expected = expected an associated value
 
 incremental_associated_value_expected_for = associated value expected for `{$ident}`
 
-incremental_associated_value_expected = expected an associated value
-
-incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
-
-incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
-
-incremental_create_new = failed to create {$name} at `{$path}`: {$err}
-
-incremental_write_new = failed to write {$name} to `{$path}`: {$err}
-
 incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
 
+incremental_cargo_help_1 =
+    incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
+incremental_cargo_help_2 =
+    the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
+
+incremental_copy_workproduct_to_cache =
+    error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
+
+incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
+
 incremental_create_incr_comp_dir =
     could not create incremental compilation {$tag} directory `{$path}`: {$err}
 
 incremental_create_lock =
     incremental compilation: could not create session directory lock file: {$lock_err}
-incremental_lock_unsupported =
-    the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
-incremental_cargo_help_1 =
-    incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
-incremental_cargo_help_2 =
-    the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
+incremental_create_new = failed to create {$name} at `{$path}`: {$err}
 
-incremental_delete_lock =
-    error deleting lock file for incremental compilation session directory `{$path}`: {$err}
-
-incremental_hard_link_failed =
-    hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
-
-incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
+incremental_decode_incr_cache = could not decode incremental cache: {$err}
 
 incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
 
-incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
-
-incremental_invalid_gc_failed =
-    failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
-
-incremental_finalized_gc_failed =
-    failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
-
-incremental_session_gc_failed =
-    failed to garbage collect incremental compilation session directory `{$path}`: {$err}
-
-incremental_assert_not_loaded =
-    we asserted that the incremental cache should not be loaded, but it was loaded
-
-incremental_assert_loaded =
-    we asserted that an existing incremental cache directory should be successfully loaded, but it was not
-
 incremental_delete_incompatible =
     failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
 
+incremental_delete_lock =
+    error deleting lock file for incremental compilation session directory `{$path}`: {$err}
+
+incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
+
+incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
+
+incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
+
+incremental_field_associated_value_expected = associated value expected for `{$name}`
+
+incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
+
+incremental_finalized_gc_failed =
+    failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
+
+incremental_hard_link_failed =
+    hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
+
+incremental_invalid_gc_failed =
+    failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
+
 incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
 
-incremental_decode_incr_cache = could not decode incremental cache: {$err}
+incremental_lock_unsupported =
+    the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
+incremental_malformed_cgu_name =
+    found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
 
-incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
+incremental_missing_depnode = missing `DepNode` variant
+
+incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
+
+incremental_missing_query_depgraph =
+    found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
 
 incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
 
-incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
+incremental_no_cfg = no cfg attribute
 
-incremental_copy_workproduct_to_cache =
-    error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
+incremental_no_field = no field `{$name}`
 
-incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
+incremental_no_module_named =
+    no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
+
+incremental_no_path = no path from `{$source}` to `{$target}`
+
+incremental_not_clean = `{$dep_node_str}` should be clean but is not
+
+incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
+
+incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
+
+incremental_ok = OK
+
+incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
+
+incremental_session_gc_failed =
+    failed to garbage collect incremental compilation session directory `{$path}`: {$err}
+
+incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
+
+incremental_undefined_clean_dirty_assertions =
+    clean/dirty auto-assertions not yet defined for {$kind}
+
+incremental_undefined_clean_dirty_assertions_item =
+    clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
+
+incremental_unknown_item = unknown item `{$name}`
+
+incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
+
+incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
+
+incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
+
+incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
+
+incremental_write_new = failed to write {$name} to `{$path}`: {$err}
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index dc981c6..25bf83f 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -14,6 +14,7 @@
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_serialize::Encoder;
 use rustc_session::Session;
+use std::borrow::Cow;
 use std::env;
 use std::fs;
 use std::io::{self, Read};
@@ -25,17 +26,12 @@
 /// Change this if the header format changes.
 const HEADER_FORMAT_VERSION: u16 = 0;
 
-/// A version string that hopefully is always different for compiler versions
-/// with different encodings of incremental compilation artifacts. Contains
-/// the Git commit hash.
-const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
-
-pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) {
+pub(crate) fn write_file_header(stream: &mut FileEncoder, sess: &Session) {
     stream.emit_raw_bytes(FILE_MAGIC);
     stream
         .emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
 
-    let rustc_version = rustc_version(nightly_build);
+    let rustc_version = rustc_version(sess.is_nightly_build(), sess.cfg_version);
     assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
     stream.emit_raw_bytes(&[rustc_version.len() as u8]);
     stream.emit_raw_bytes(rustc_version.as_bytes());
@@ -73,7 +69,7 @@
         }
     };
 
-    write_file_header(&mut encoder, sess.is_nightly_build());
+    write_file_header(&mut encoder, sess);
 
     match encode(encoder) {
         Ok(position) => {
@@ -100,9 +96,10 @@
 /// - Returns `Err(..)` if some kind of IO error occurred while reading the
 ///   file.
 pub fn read_file(
-    report_incremental_info: bool,
     path: &Path,
-    nightly_build: bool,
+    report_incremental_info: bool,
+    is_nightly_build: bool,
+    cfg_version: &'static str,
 ) -> io::Result<Option<(Mmap, usize)>> {
     let file = match fs::File::open(path) {
         Ok(file) => file,
@@ -152,7 +149,7 @@
         let mut buffer = vec![0; rustc_version_str_len];
         file.read_exact(&mut buffer)?;
 
-        if buffer != rustc_version(nightly_build).as_bytes() {
+        if buffer != rustc_version(is_nightly_build, cfg_version).as_bytes() {
             report_format_mismatch(report_incremental_info, path, "Different compiler version");
             return Ok(None);
         }
@@ -174,17 +171,15 @@
     }
 }
 
-fn rustc_version(nightly_build: bool) -> String {
+/// A version string that hopefully is always different for compiler versions
+/// with different encodings of incremental compilation artifacts. Contains
+/// the Git commit hash.
+fn rustc_version(nightly_build: bool, cfg_version: &'static str) -> Cow<'static, str> {
     if nightly_build {
-        if let Some(val) = env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
-            return val.to_string_lossy().into_owned();
+        if let Ok(val) = env::var("RUSTC_FORCE_RUSTC_VERSION") {
+            return val.into();
         }
     }
 
-    RUSTC_VERSION
-        .expect(
-            "Cannot use rustc without explicit version for \
-                          incremental compilation",
-        )
-        .to_string()
+    cfg_version.into()
 }
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index ec7fcbd..a4407a9 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -73,12 +73,22 @@
     }
 }
 
-fn load_data(
-    report_incremental_info: bool,
+fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> {
+    load_data_no_sess(
+        path,
+        sess.opts.unstable_opts.incremental_info,
+        sess.is_nightly_build(),
+        sess.cfg_version,
+    )
+}
+
+fn load_data_no_sess(
     path: &Path,
-    nightly_build: bool,
+    report_incremental_info: bool,
+    is_nightly_build: bool,
+    cfg_version: &'static str,
 ) -> LoadResult<(Mmap, usize)> {
-    match file_format::read_file(report_incremental_info, path, nightly_build) {
+    match file_format::read_file(path, report_incremental_info, is_nightly_build, cfg_version) {
         Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
         Ok(None) => {
             // The file either didn't exist or was produced by an incompatible
@@ -138,14 +148,13 @@
     let expected_hash = sess.opts.dep_tracking_hash(false);
 
     let mut prev_work_products = FxHashMap::default();
-    let nightly_build = sess.is_nightly_build();
 
     // If we are only building with -Zquery-dep-graph but without an actual
     // incr. comp. session directory, we skip this. Otherwise we'd fail
     // when trying to load work products.
     if sess.incr_comp_session_dir_opt().is_some() {
         let work_products_path = work_products_path(sess);
-        let load_result = load_data(report_incremental_info, &work_products_path, nightly_build);
+        let load_result = load_data(&work_products_path, sess);
 
         if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
             // Decode the list of work_products
@@ -173,10 +182,13 @@
         }
     }
 
+    let is_nightly_build = sess.is_nightly_build();
+    let cfg_version = sess.cfg_version;
+
     MaybeAsync::Async(std::thread::spawn(move || {
         let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
 
-        match load_data(report_incremental_info, &path, nightly_build) {
+        match load_data_no_sess(&path, report_incremental_info, is_nightly_build, cfg_version) {
             LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
             LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
             LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
@@ -218,11 +230,7 @@
 
     let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache");
 
-    match load_data(
-        sess.opts.unstable_opts.incremental_info,
-        &query_cache_path(sess),
-        sess.is_nightly_build(),
-    ) {
+    match load_data(&query_cache_path(sess), sess) {
         LoadResult::Ok { data: (bytes, start_pos) } => {
             Some(OnDiskCache::new(sess, bytes, start_pos))
         }
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 1441e64..7376be6 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -164,7 +164,7 @@
         }
     };
 
-    file_format::write_file_header(&mut encoder, sess.is_nightly_build());
+    file_format::write_file_header(&mut encoder, sess);
 
     // First encode the commandline arguments hash
     sess.opts.dep_tracking_hash(false).encode(&mut encoder);
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index a1ab9c8..15bc3b4 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1544,7 +1544,7 @@
     #[inline]
     pub fn contains(&self, elem: T) -> bool {
         let (word_index, mask) = word_index_and_mask(elem);
-        self.bit_set.words.get(word_index).map_or(false, |word| (word & mask) != 0)
+        self.bit_set.words.get(word_index).is_some_and(|word| (word & mask) != 0)
     }
 
     #[inline]
@@ -1818,7 +1818,7 @@
     /// if the matrix represents (transitive) reachability, can
     /// `row` reach `column`?
     pub fn contains(&self, row: R, column: C) -> bool {
-        self.row(row).map_or(false, |r| r.contains(column))
+        self.row(row).is_some_and(|r| r.contains(column))
     }
 
     /// Adds the bits from row `read` to the bits from row `write`, and
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index 7ed4860..d3cf267 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -181,6 +181,30 @@
         self.map.is_empty()
     }
 
+    /// Equivalent to `range.iter().find(|i| !self.contains(i))`.
+    pub fn first_unset_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
+        let start = inclusive_start(range.clone());
+        let Some(end) = inclusive_end(self.domain, range) else {
+            // empty range
+            return None;
+        };
+        if start > end {
+            return None;
+        }
+        let Some(last) = self.map.partition_point(|r| r.0 <= start).checked_sub(1) else {
+            // All ranges in the map start after the new range's end
+            return Some(I::new(start as usize));
+        };
+        let (_, prev_end) = self.map[last];
+        if start > prev_end {
+            Some(I::new(start as usize))
+        } else if prev_end < end {
+            Some(I::new(prev_end as usize + 1))
+        } else {
+            None
+        }
+    }
+
     /// Returns the maximum (last) element present in the set from `range`.
     pub fn last_set_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
         let start = inclusive_start(range.clone());
@@ -224,7 +248,7 @@
     fn check_invariants(&self) -> bool {
         let mut current: Option<u32> = None;
         for (start, end) in &self.map {
-            if start > end || current.map_or(false, |x| x + 1 >= *start) {
+            if start > end || current.is_some_and(|x| x + 1 >= *start) {
                 return false;
             }
             current = Some(*end);
@@ -297,6 +321,6 @@
     }
 
     pub fn contains(&self, row: R, point: C) -> bool {
-        self.row(row).map_or(false, |r| r.contains(point))
+        self.row(row).is_some_and(|r| r.contains(point))
     }
 }
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index fdc4ff0..f44c4a7 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -1,257 +1,8 @@
-infer_opaque_hidden_type =
-    opaque type's hidden type cannot be another opaque type from the same scope
-    .label = one of the two opaque types used here has to be outside its defining scope
-    .opaque_type = opaque type whose hidden type is being assigned
-    .hidden_type = opaque type being used as hidden type
-
-infer_type_annotations_needed = {$source_kind ->
-    [closure] type annotations needed for the closure `{$source_name}`
-    [normal] type annotations needed for `{$source_name}`
-    *[other] type annotations needed
-}
-    .label = type must be known at this point
-
-infer_label_bad = {$bad_kind ->
-    *[other] cannot infer type
-    [more_info] cannot infer {$prefix_kind ->
-        *[type] type for {$prefix}
-        [const_with_param] the value of const parameter
-        [const] the value of the constant
-    } `{$name}`{$has_parent ->
-        [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
-        *[false] {""}
-    }
-}
-
-infer_source_kind_subdiag_let = {$kind ->
-    [with_pattern] consider giving `{$name}` an explicit type
-    [closure] consider giving this closure parameter an explicit type
-    *[other] consider giving this pattern a type
-}{$x_kind ->
-    [has_name] , where the {$prefix_kind ->
-        *[type] type for {$prefix}
-        [const_with_param] value of const parameter
-        [const] value of the constant
-    } `{$arg_name}` is specified
-    [underscore] , where the placeholders `_` are specified
-    *[empty] {""}
-}
-
-infer_source_kind_subdiag_generic_label =
-    cannot infer {$is_type ->
-    [true] type
-    *[false] the value
-    } of the {$is_type ->
-    [true] type
-    *[false] const
-    } {$parent_exists ->
-    [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
-    *[false] parameter {$param_name}
-    }
-
-infer_source_kind_subdiag_generic_suggestion =
-    consider specifying the generic {$arg_count ->
-    [one] argument
-    *[other] arguments
-    }
-
-infer_source_kind_fully_qualified =
-    try using a fully qualified path to specify the expected types
-
-infer_source_kind_closure_return =
-    try giving this closure an explicit return type
-
-# generator_kind  may need to be translated
-infer_need_type_info_in_generator =
-    type inside {$generator_kind ->
-    [async_block] `async` block
-    [async_closure] `async` closure
-    [async_fn] `async fn` body
-    *[generator] generator
-    } must be known in this context
-
-
-infer_subtype = ...so that the {$requirement ->
-    [method_compat] method type is compatible with trait
-    [type_compat] associated type is compatible with trait
-    [const_compat] const is compatible with trait
-    [expr_assignable] expression is assignable
-    [if_else_different] `if` and `else` have incompatible types
-    [no_else] `if` missing an `else` returns `()`
-    [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] `#[start]` function has the correct type
-    [intrinsic_correct_type] intrinsic has the correct type
-    [method_correct_type] method receiver has the correct type
-    *[other] types are compatible
-}
-infer_subtype_2 = ...so that {$requirement ->
-    [method_compat] method type is compatible with trait
-    [type_compat] associated type is compatible with trait
-    [const_compat] const is compatible with trait
-    [expr_assignable] expression is assignable
-    [if_else_different] `if` and `else` have incompatible types
-    [no_else] `if` missing an `else` returns `()`
-    [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] `#[start]` function has the correct type
-    [intrinsic_correct_type] intrinsic has the correct type
-    [method_correct_type] method receiver has the correct type
-    *[other] types are compatible
-}
-
-infer_reborrow = ...so that reference does not outlive borrowed content
-infer_reborrow_upvar = ...so that closure can access `{$name}`
-infer_relate_object_bound = ...so that it can be closed over into an object
-infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
-infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
-    [true] ...
-    *[false] {""}
-}
-infer_relate_param_bound_2 = ...that is required by this bound
-infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
-infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
-infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
-
-infer_nothing = {""}
-
-infer_lifetime_mismatch = lifetime mismatch
-
-infer_declared_different = this parameter and the return type are declared with different lifetimes...
-infer_data_returned = ...but data{$label_var1_exists ->
-    [true] {" "}from `{$label_var1}`
-    *[false] {""}
-} is returned here
-
-infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
-infer_declared_multiple = this type is declared with multiple lifetimes...
-infer_types_declared_different = these two types are declared with different lifetimes...
-infer_data_flows = ...but data{$label_var1_exists ->
-    [true] {" "}from `{$label_var1}`
-    *[false] -> {""}
-} flows{$label_var2_exists ->
-    [true] {" "}into `{$label_var2}`
-    *[false] -> {""}
-} here
-
-infer_lifetime_param_suggestion = consider introducing a named lifetime parameter{$is_impl ->
-    [true] {" "}and update trait if needed
-    *[false] {""}
-}
-infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
-
-infer_region_explanation = {$pref_kind ->
-    *[should_not_happen] [{$pref_kind}]
-    [ref_valid_for] ...the reference is valid for
-    [content_valid_for] ...but the borrowed content is only valid for
-    [type_obj_valid_for] object type is valid for
-    [source_pointer_valid_for] source pointer is only valid for
-    [type_satisfy] type must satisfy
-    [type_outlive] type must outlive
-    [lf_param_instantiated_with] lifetime parameter instantiated with
-    [lf_param_must_outlive] but lifetime parameter must outlive
-    [lf_instantiated_with] lifetime instantiated with
-    [lf_must_outlive] but lifetime must outlive
-    [pointer_valid_for] the pointer is valid for
-    [data_valid_for] but the referenced data is only valid for
-    [empty] {""}
-}{$pref_kind ->
-    [empty] {""}
-    *[other] {" "}
-}{$desc_kind ->
-    *[should_not_happen] [{$desc_kind}]
-    [restatic] the static lifetime
-    [revar] lifetime {$desc_arg}
-    [as_defined] the lifetime `{$desc_arg}` as defined here
-    [as_defined_anon] the anonymous lifetime as defined here
-    [defined_here] the anonymous lifetime defined here
-    [defined_here_reg] the lifetime `{$desc_arg}` as defined here
-}{$suff_kind ->
-    *[should_not_happen] [{$suff_kind}]
-    [empty]{""}
-    [continues] ...
-    [req_by_binding] {" "}as required by this binding
-}
-
-infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
-infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
-infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
-infer_lf_bound_not_satisfied = lifetime bound not satisfied
-infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
-infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
-
-infer_mismatched_static_lifetime = incompatible lifetime on type
-infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
-infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
-infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
-infer_msl_introduces_static = introduces a `'static` lifetime requirement
-infer_msl_unmet_req = because this has an unmet lifetime requirement
-infer_msl_trait_note = this has an implicit `'static` lifetime requirement
-infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
-infer_suggest_add_let_for_letchains = consider adding `let`
-
-infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
-    .label = lifetime `{$named}` required
-
-infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
-    .label = lifetime `{$named}` required
-
-infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
-
-infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
-
-infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
-infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
-infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`
-
-infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
+infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
     [true] , for some specific lifetime `'{$lifetime}`
     *[false] {""}
 }
-infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
+infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
     [true] , for some specific lifetime `'{$lifetime}`
     *[false] {""}
 }
@@ -260,26 +11,62 @@
     *[false] {""}
 }
 
-infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
-    .label_satisfy = doesn't satisfy where-clause
-    .label_where = due to a where-clause on `{$def_id}`...
-    .label_dup = implementation of `{$trait_def_id}` is not general enough
+infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`
 
-infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
-    .found = found `{$found}`
-    .expected = expected `{$expected}`
-    .expected_found = expected signature `{$expected}`
-               {"   "}found signature `{$found}`
+infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
+infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
+infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
 
-infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
-infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
-infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+infer_await_both_futures = consider `await`ing on both `Future`s
+infer_await_future = consider `await`ing on the `Future`
+infer_await_note = calling an async function returns a future
 
-infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
-infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
-infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
-infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
-
+infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
 infer_but_calling_introduces = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
@@ -314,6 +101,77 @@
     .used_here = ...is used here...
     .introduced_by_bound = `'static` lifetime requirement introduced by this bound
 
+infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
+infer_consider_specifying_length = consider specifying the actual array length
+infer_data_flows = ...but data{$label_var1_exists ->
+    [true] {" "}from `{$label_var1}`
+    *[false] -> {""}
+} flows{$label_var2_exists ->
+    [true] {" "}into `{$label_var2}`
+    *[false] -> {""}
+} here
+
+infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
+infer_data_returned = ...but data{$label_var1_exists ->
+    [true] {" "}from `{$label_var1}`
+    *[false] {""}
+} is returned here
+
+infer_declared_different = this parameter and the return type are declared with different lifetimes...
+infer_declared_multiple = this type is declared with multiple lifetimes...
+infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
+infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
+infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
+infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
+
+infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
+
+infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
+
+infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
+    .label = lifetime `{$named}` required
+
+infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
+    .label = lifetime `{$named}` required
+
+infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+
+infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
+infer_fps_cast = consider casting to a fn pointer
+infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+
+infer_fps_items_are_distinct = fn items are distinct from fn pointers
+infer_fps_remove_ref = consider removing the reference
+infer_fps_use_ref = consider using a reference
+infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
+infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
+infer_label_bad = {$bad_kind ->
+    *[other] cannot infer type
+    [more_info] cannot infer {$prefix_kind ->
+        *[type] type for {$prefix}
+        [const_with_param] the value of const parameter
+        [const] the value of the constant
+    } `{$name}`{$has_parent ->
+        [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
+        *[false] {""}
+    }
+}
+
+infer_lf_bound_not_satisfied = lifetime bound not satisfied
+infer_lifetime_mismatch = lifetime mismatch
+
+infer_lifetime_param_suggestion = consider introducing a named lifetime parameter{$is_impl ->
+    [true] {" "}and update trait if needed
+    *[false] {""}
+}
+infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
+
+infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
+infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
+infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
+infer_mismatched_static_lifetime = incompatible lifetime on type
 infer_more_targeted = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
@@ -322,72 +180,215 @@
     *[false] an anonymous lifetime `'_`
 } but calling `{$ident}` introduces an implicit `'static` lifetime requirement
 
-infer_ril_introduced_here = `'static` requirement introduced here
-infer_ril_introduced_by = requirement introduced by this return type
-infer_ril_because_of = because of this returned expression
-infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
+infer_msl_introduces_static = introduces a `'static` lifetime requirement
+infer_msl_trait_note = this has an implicit `'static` lifetime requirement
+infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
+infer_msl_unmet_req = because this has an unmet lifetime requirement
+infer_need_type_info_in_generator =
+    type inside {$generator_kind ->
+    [async_block] `async` block
+    [async_closure] `async` closure
+    [async_fn] `async fn` body
+    *[generator] generator
+    } must be known in this context
 
-infer_where_remove = remove the `where` clause
-infer_where_copy_predicates = copy the `where` clause predicates from the trait
 
-infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
-infer_srs_remove = consider removing this semicolon
-infer_srs_add = consider returning the local binding `{$ident}`
-infer_srs_add_one = consider returning one of these bindings
+infer_nothing = {""}
 
-infer_await_both_futures = consider `await`ing on both `Future`s
-infer_await_future = consider `await`ing on the `Future`
-infer_await_note = calling an async function returns a future
+infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
+infer_oc_closure_selfref = closure/generator type that references itself
+infer_oc_const_compat = const not compatible with trait
+infer_oc_fn_main_correct_type = `main` function has wrong type
+infer_oc_fn_start_correct_type = `#[start]` function has wrong type
+infer_oc_generic = mismatched types
 
-infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
-infer_prlf_defined_without_sub = the lifetime defined here...
-infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
-infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
-infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
-
+infer_oc_if_else_different = `if` and `else` have incompatible types
+infer_oc_intrinsic_correct_type = intrinsic has wrong type
+infer_oc_match_compat = `match` arms have incompatible types
+infer_oc_method_compat = method not compatible with trait
+infer_oc_method_correct_type = mismatched `self` parameter type
+infer_oc_no_diverge = `else` clause of `let...else` does not diverge
+infer_oc_no_else = `if` may be missing an `else` clause
+infer_oc_try_compat = `?` operator has incompatible types
+infer_oc_type_compat = type not compatible with trait
 infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
     .label = opaque type defined here
 
-infer_fps_use_ref = consider using a reference
-infer_fps_remove_ref = consider removing the reference
-infer_fps_cast = consider casting to a fn pointer
-infer_fps_items_are_distinct = fn items are distinct from fn pointers
-infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+infer_opaque_hidden_type =
+    opaque type's hidden type cannot be another opaque type from the same scope
+    .label = one of the two opaque types used here has to be outside its defining scope
+    .opaque_type = opaque type whose hidden type is being assigned
+    .hidden_type = opaque type being used as hidden type
 
-infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
-infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
+infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
+infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
+infer_prlf_defined_without_sub = the lifetime defined here...
+infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
+infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
+infer_reborrow = ...so that reference does not outlive borrowed content
+infer_reborrow_upvar = ...so that closure can access `{$name}`
+infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
+
+infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
+infer_region_explanation = {$pref_kind ->
+    *[should_not_happen] [{$pref_kind}]
+    [ref_valid_for] ...the reference is valid for
+    [content_valid_for] ...but the borrowed content is only valid for
+    [type_obj_valid_for] object type is valid for
+    [source_pointer_valid_for] source pointer is only valid for
+    [type_satisfy] type must satisfy
+    [type_outlive] type must outlive
+    [lf_param_instantiated_with] lifetime parameter instantiated with
+    [lf_param_must_outlive] but lifetime parameter must outlive
+    [lf_instantiated_with] lifetime instantiated with
+    [lf_must_outlive] but lifetime must outlive
+    [pointer_valid_for] the pointer is valid for
+    [data_valid_for] but the referenced data is only valid for
+    [empty] {""}
+}{$pref_kind ->
+    [empty] {""}
+    *[other] {" "}
+}{$desc_kind ->
+    *[should_not_happen] [{$desc_kind}]
+    [restatic] the static lifetime
+    [revar] lifetime {$desc_arg}
+    [as_defined] the lifetime `{$desc_arg}` as defined here
+    [as_defined_anon] the anonymous lifetime as defined here
+    [defined_here] the anonymous lifetime defined here
+    [defined_here_reg] the lifetime `{$desc_arg}` as defined here
+}{$suff_kind ->
+    *[should_not_happen] [{$suff_kind}]
+    [empty]{""}
+    [continues] ...
+    [req_by_binding] {" "}as required by this binding
+}
+
+infer_relate_object_bound = ...so that it can be closed over into an object
+infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
+    [true] ...
+    *[false] {""}
+}
+infer_relate_param_bound_2 = ...that is required by this bound
+infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
+infer_ril_because_of = because of this returned expression
+infer_ril_introduced_by = requirement introduced by this return type
+infer_ril_introduced_here = `'static` requirement introduced here
+infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
 
 infer_sarwa_option = you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`
 infer_sarwa_result = you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()`
 
-infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
-
-infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
 infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
 
-infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
+infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
+infer_source_kind_closure_return =
+    try giving this closure an explicit return type
+
+# generator_kind  may need to be translated
+infer_source_kind_fully_qualified =
+    try using a fully qualified path to specify the expected types
+
+infer_source_kind_subdiag_generic_label =
+    cannot infer {$is_type ->
+    [true] type
+    *[false] the value
+    } of the {$is_type ->
+    [true] type
+    *[false] const
+    } {$parent_exists ->
+    [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
+    *[false] parameter {$param_name}
+    }
+
+infer_source_kind_subdiag_generic_suggestion =
+    consider specifying the generic {$arg_count ->
+    [one] argument
+    *[other] arguments
+    }
+
+infer_source_kind_subdiag_let = {$kind ->
+    [with_pattern] consider giving `{$name}` an explicit type
+    [closure] consider giving this closure parameter an explicit type
+    *[other] consider giving this pattern a type
+}{$x_kind ->
+    [has_name] , where the {$prefix_kind ->
+        *[type] type for {$prefix}
+        [const_with_param] value of const parameter
+        [const] value of the constant
+    } `{$arg_name}` is specified
+    [underscore] , where the placeholders `_` are specified
+    *[empty] {""}
+}
+
+infer_srs_add = consider returning the local binding `{$ident}`
+infer_srs_add_one = consider returning one of these bindings
+
+infer_srs_remove = consider removing this semicolon
+infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
 infer_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
 
+infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
+infer_subtype = ...so that the {$requirement ->
+    [method_compat] method type is compatible with trait
+    [type_compat] associated type is compatible with trait
+    [const_compat] const is compatible with trait
+    [expr_assignable] expression is assignable
+    [if_else_different] `if` and `else` have incompatible types
+    [no_else] `if` missing an `else` returns `()`
+    [fn_main_correct_type] `main` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
+    [method_correct_type] method receiver has the correct type
+    *[other] types are compatible
+}
+infer_subtype_2 = ...so that {$requirement ->
+    [method_compat] method type is compatible with trait
+    [type_compat] associated type is compatible with trait
+    [const_compat] const is compatible with trait
+    [expr_assignable] expression is assignable
+    [if_else_different] `if` and `else` have incompatible types
+    [no_else] `if` missing an `else` returns `()`
+    [fn_main_correct_type] `main` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
+    [method_correct_type] method receiver has the correct type
+    *[other] types are compatible
+}
+
+infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
+
+infer_suggest_add_let_for_letchains = consider adding `let`
+
+infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
+infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+
+infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
+infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
+    .found = found `{$found}`
+    .expected = expected `{$expected}`
+    .expected_found = expected signature `{$expected}`
+               {"   "}found signature `{$found}`
+
+infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
+    .label_satisfy = doesn't satisfy where-clause
+    .label_where = due to a where-clause on `{$def_id}`...
+    .label_dup = implementation of `{$trait_def_id}` is not general enough
+
+infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
+
 infer_tuple_trailing_comma = use a trailing comma to create a tuple with one element
 
-infer_oc_method_compat = method not compatible with trait
-infer_oc_type_compat = type not compatible with trait
-infer_oc_const_compat = const not compatible with trait
-infer_oc_try_compat = `?` operator has incompatible types
-infer_oc_match_compat = `match` arms have incompatible types
-infer_oc_if_else_different = `if` and `else` have incompatible types
-infer_oc_no_else = `if` may be missing an `else` clause
-infer_oc_no_diverge = `else` clause of `let...else` does not diverge
-infer_oc_fn_main_correct_type = `main` function has wrong type
-infer_oc_fn_start_correct_type = `#[start]` function has wrong type
-infer_oc_intrinsic_correct_type = intrinsic has wrong type
-infer_oc_method_correct_type = mismatched `self` parameter type
-infer_oc_closure_selfref = closure/generator type that references itself
-infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
-infer_oc_generic = mismatched types
+infer_type_annotations_needed = {$source_kind ->
+    [closure] type annotations needed for the closure `{$source_name}`
+    [normal] type annotations needed for `{$source_name}`
+    *[other] type annotations needed
+}
+    .label = type must be known at this point
 
-infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
-infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
-infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
-infer_consider_specifying_length = consider specifying the actual array length
-infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
+infer_types_declared_different = these two types are declared with different lifetimes...
+infer_where_copy_predicates = copy the `where` clause predicates from the trait
+
+infer_where_remove = remove the `where` clause
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 3605e10..88256c8 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -15,7 +15,7 @@
 use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
-use crate::traits::query::{Fallible, NoSolution};
+use crate::traits::query::NoSolution;
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
 use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt};
 use rustc_data_structures::captures::Captures;
@@ -57,7 +57,7 @@
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
         fulfill_cx: &mut dyn TraitEngine<'tcx>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, T>>
+    ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
         Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
@@ -153,20 +153,22 @@
 
     /// Used by the new solver as that one takes the opaque types at the end of a probe
     /// to deal with multiple candidates without having to recompute them.
-    pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    pub fn clone_opaque_types_for_query_response(
+        &self,
+    ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
         self.inner
             .borrow()
             .opaque_type_storage
             .opaque_types
             .iter()
-            .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+            .map(|(k, v)| (*k, v.hidden_type.ty))
             .collect()
     }
 
-    fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
         std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
             .into_iter()
-            .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+            .map(|(k, v)| (k, v.hidden_type.ty))
             .collect()
     }
 
@@ -507,8 +509,22 @@
             let a = substitute_value(self.tcx, &result_subst, a);
             let b = substitute_value(self.tcx, &result_subst, b);
             debug!(?a, ?b, "constrain opaque type");
-            obligations
-                .extend(self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, a, b)?.obligations);
+            // We use equate here instead of, for example, just registering the
+            // opaque type's hidden value directly, because we may be instantiating
+            // a query response that was canonicalized in an InferCtxt that had
+            // a different defining anchor. In that case, we may have inferred
+            // `NonLocalOpaque := LocalOpaque` but can only instantiate it in
+            // the other direction as `LocalOpaque := NonLocalOpaque`. Using eq
+            // here allows us to try both directions (in `InferCtxt::handle_opaque_type`).
+            obligations.extend(
+                self.at(cause, param_env)
+                    .eq(
+                        DefineOpaqueTypes::Yes,
+                        self.tcx.mk_opaque(a.def_id.to_def_id(), a.substs),
+                        b,
+                    )?
+                    .obligations,
+            );
         }
 
         Ok(InferOk { value: result_subst, obligations })
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 08eec07..b6b935d 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -26,24 +26,17 @@
 use super::glb::Glb;
 use super::lub::Lub;
 use super::sub::Sub;
-use super::type_variable::TypeVariableValue;
-use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace};
+use super::{DefineOpaqueTypes, InferCtxt, TypeTrace};
+use crate::infer::generalize::{self, CombineDelegate, Generalization};
 use crate::traits::{Obligation, PredicateObligations};
-use rustc_data_structures::sso::SsoHashMap;
-use rustc_hir::def_id::DefId;
 use rustc_middle::infer::canonical::OriginalQueryValues;
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{
-    self, AliasKind, FallibleTypeFolder, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable,
-    TypeSuperFoldable, TypeVisitableExt,
-};
+use rustc_middle::ty::relate::{RelateResult, TypeRelation};
+use rustc_middle::ty::{self, AliasKind, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{IntType, UintType};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::DUMMY_SP;
 
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'tcx> {
@@ -55,13 +48,6 @@
     pub define_opaque_types: DefineOpaqueTypes,
 }
 
-#[derive(Copy, Clone, Debug)]
-pub enum RelationDir {
-    SubtypeOf,
-    SupertypeOf,
-    EqTo,
-}
-
 impl<'tcx> InferCtxt<'tcx> {
     pub fn super_combine_tys<R>(
         &self,
@@ -127,10 +113,7 @@
                 bug!()
             }
 
-            (_, ty::Alias(AliasKind::Projection | AliasKind::Inherent, _))
-            | (ty::Alias(AliasKind::Projection | AliasKind::Inherent, _), _)
-                if self.tcx.trait_solver_next() =>
-            {
+            (_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
                 relation.register_type_relate_obligation(a, b);
                 Ok(a)
             }
@@ -152,7 +135,7 @@
                 Ok(a)
             }
 
-            _ => ty::relate::super_relate_tys(relation, a, b),
+            _ => ty::relate::structurally_relate_tys(relation, a, b),
         }
     }
 
@@ -209,13 +192,13 @@
             // HACK: equating both sides with `[const error]` eagerly prevents us
             // from leaving unconstrained inference vars during things like impl
             // matching in the solver.
-            let a_error = self.tcx.const_error_with_guaranteed(a.ty(), guar);
+            let a_error = self.tcx.const_error(a.ty(), guar);
             if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
-                return self.unify_const_variable(vid, a_error);
+                return self.unify_const_variable(vid, a_error, relation.param_env());
             }
-            let b_error = self.tcx.const_error_with_guaranteed(b.ty(), guar);
+            let b_error = self.tcx.const_error(b.ty(), guar);
             if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
-                return self.unify_const_variable(vid, b_error);
+                return self.unify_const_variable(vid, b_error, relation.param_env());
             }
 
             return Ok(if relation.a_is_expected() { a_error } else { b_error });
@@ -237,11 +220,11 @@
             }
 
             (ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
-                return self.unify_const_variable(vid, b);
+                return self.unify_const_variable(vid, b, relation.param_env());
             }
 
             (_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
-                return self.unify_const_variable(vid, a);
+                return self.unify_const_variable(vid, a, relation.param_env());
             }
             (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
                 if self.tcx.lazy_normalization() =>
@@ -252,7 +235,7 @@
             _ => {}
         }
 
-        ty::relate::super_relate_consts(relation, a, b)
+        ty::relate::structurally_relate_consts(relation, a, b)
     }
 
     /// Unifies the const variable `target_vid` with the given constant.
@@ -294,24 +277,17 @@
         &self,
         target_vid: ty::ConstVid<'tcx>,
         ct: ty::Const<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        let (for_universe, span) = {
-            let mut inner = self.inner.borrow_mut();
-            let variable_table = &mut inner.const_unification_table();
-            let var_value = variable_table.probe_value(target_vid);
-            match var_value.val {
-                ConstVariableValue::Known { value } => {
-                    bug!("instantiating {:?} which has a known value {:?}", target_vid, value)
-                }
-                ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span),
-            }
-        };
-        let value = ct.try_fold_with(&mut ConstInferUnifier {
-            infcx: self,
-            span,
-            for_universe,
+        let span =
+            self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
+        let Generalization { value, needs_wf: _ } = generalize::generalize(
+            self,
+            &mut CombineDelegate { infcx: self, span, param_env },
+            ct,
             target_vid,
-        })?;
+            ty::Variance::Invariant,
+        )?;
 
         self.inner.borrow_mut().const_unification_table().union_value(
             target_vid,
@@ -392,12 +368,10 @@
     pub fn instantiate(
         &mut self,
         a_ty: Ty<'tcx>,
-        dir: RelationDir,
+        ambient_variance: ty::Variance,
         b_vid: ty::TyVid,
         a_is_expected: bool,
     ) -> RelateResult<'tcx, ()> {
-        use self::RelationDir::*;
-
         // Get the actual variable that b_vid has been inferred to
         debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
 
@@ -412,7 +386,18 @@
         // `'?2` and `?3` are fresh region/type inference
         // variables. (Down below, we will relate `a_ty <: b_ty`,
         // adding constraints like `'x: '?2` and `?1 <: ?3`.)
-        let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
+        let Generalization { value: b_ty, needs_wf } = generalize::generalize(
+            self.infcx,
+            &mut CombineDelegate {
+                infcx: self.infcx,
+                param_env: self.param_env,
+                span: self.trace.span(),
+            },
+            a_ty,
+            b_vid,
+            ambient_variance,
+        )?;
+
         debug!(?b_ty);
         self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
 
@@ -431,78 +416,23 @@
         // relations wind up attributed to the same spans. We need
         // to associate causes/spans with each of the relations in
         // the stack to get this right.
-        match dir {
-            EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
-            SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
-            SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+        match ambient_variance {
+            ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
+            ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
+            ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
                 ty::Contravariant,
                 ty::VarianceDiagInfo::default(),
                 a_ty,
                 b_ty,
             ),
+            ty::Variance::Bivariant => {
+                unreachable!("no code should be generalizing bivariantly (currently)")
+            }
         }?;
 
         Ok(())
     }
 
-    /// Attempts to generalize `ty` for the type variable `for_vid`.
-    /// This checks for cycle -- that is, whether the type `ty`
-    /// references `for_vid`. The `dir` is the "direction" for which we
-    /// a performing the generalization (i.e., are we producing a type
-    /// that can be used as a supertype etc).
-    ///
-    /// Preconditions:
-    ///
-    /// - `for_vid` is a "root vid"
-    #[instrument(skip(self), level = "trace", ret)]
-    fn generalize(
-        &self,
-        ty: Ty<'tcx>,
-        for_vid: ty::TyVid,
-        dir: RelationDir,
-    ) -> RelateResult<'tcx, Generalization<'tcx>> {
-        // Determine the ambient variance within which `ty` appears.
-        // The surrounding equation is:
-        //
-        //     ty [op] ty2
-        //
-        // where `op` is either `==`, `<:`, or `:>`. This maps quite
-        // naturally.
-        let ambient_variance = match dir {
-            RelationDir::EqTo => ty::Invariant,
-            RelationDir::SubtypeOf => ty::Covariant,
-            RelationDir::SupertypeOf => ty::Contravariant,
-        };
-
-        trace!(?ambient_variance);
-
-        let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) {
-            v @ TypeVariableValue::Known { .. } => {
-                bug!("instantiating {:?} which has a known value {:?}", for_vid, v,)
-            }
-            TypeVariableValue::Unknown { universe } => universe,
-        };
-
-        trace!(?for_universe);
-        trace!(?self.trace);
-
-        let mut generalize = Generalizer {
-            infcx: self.infcx,
-            cause: &self.trace.cause,
-            for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
-            for_universe,
-            ambient_variance,
-            needs_wf: false,
-            root_ty: ty,
-            param_env: self.param_env,
-            cache: SsoHashMap::new(),
-        };
-
-        let ty = generalize.relate(ty, ty)?;
-        let needs_wf = generalize.needs_wf;
-        Ok(Generalization { ty, needs_wf })
-    }
-
     pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
         self.obligations.extend(obligations.into_iter());
     }
@@ -514,313 +444,6 @@
     }
 }
 
-struct Generalizer<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'tcx>,
-
-    /// The span, used when creating new type variables and things.
-    cause: &'cx ObligationCause<'tcx>,
-
-    /// The vid of the type variable that is in the process of being
-    /// instantiated; if we find this within the type we are folding,
-    /// that means we would have created a cyclic type.
-    for_vid_sub_root: ty::TyVid,
-
-    /// The universe of the type variable that is in the process of
-    /// being instantiated. Any fresh variables that we create in this
-    /// process should be in that same universe.
-    for_universe: ty::UniverseIndex,
-
-    /// Track the variance as we descend into the type.
-    ambient_variance: ty::Variance,
-
-    /// See the field `needs_wf` in `Generalization`.
-    needs_wf: bool,
-
-    /// The root type that we are generalizing. Used when reporting cycles.
-    root_ty: Ty<'tcx>,
-
-    param_env: ty::ParamEnv<'tcx>,
-
-    cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
-}
-
-/// Result from a generalization operation. This includes
-/// not only the generalized type, but also a bool flag
-/// indicating whether further WF checks are needed.
-#[derive(Debug)]
-struct Generalization<'tcx> {
-    ty: Ty<'tcx>,
-
-    /// If true, then the generalized type may not be well-formed,
-    /// even if the source type is well-formed, so we should add an
-    /// additional check to enforce that it is. This arises in
-    /// particular around 'bivariant' type parameters that are only
-    /// constrained by a where-clause. As an example, imagine a type:
-    ///
-    ///     struct Foo<A, B> where A: Iterator<Item = B> {
-    ///         data: A
-    ///     }
-    ///
-    /// here, `A` will be covariant, but `B` is
-    /// unconstrained. However, whatever it is, for `Foo` to be WF, it
-    /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
-    /// then after generalization we will wind up with a type like
-    /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
-    /// ?D>` (or `>:`), we will wind up with the requirement that `?A
-    /// <: ?C`, but no particular relationship between `?B` and `?D`
-    /// (after all, we do not know the variance of the normalized form
-    /// of `A::Item` with respect to `A`). If we do nothing else, this
-    /// may mean that `?D` goes unconstrained (as in #41677). So, in
-    /// this scenario where we create a new type variable in a
-    /// bivariant context, we set the `needs_wf` flag to true. This
-    /// will force the calling code to check that `WF(Foo<?C, ?D>)`
-    /// holds, which in turn implies that `?C::Item == ?D`. So once
-    /// `?C` is constrained, that should suffice to restrict `?D`.
-    needs_wf: bool,
-}
-
-impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
-    }
-
-    fn tag(&self) -> &'static str {
-        "Generalizer"
-    }
-
-    fn a_is_expected(&self) -> bool {
-        true
-    }
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<'tcx>,
-    {
-        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
-    }
-
-    fn relate_item_substs(
-        &mut self,
-        item_def_id: DefId,
-        a_subst: SubstsRef<'tcx>,
-        b_subst: SubstsRef<'tcx>,
-    ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
-        if self.ambient_variance == ty::Variance::Invariant {
-            // Avoid fetching the variance if we are in an invariant
-            // context; no need, and it can induce dependency cycles
-            // (e.g., #41849).
-            relate::relate_substs(self, a_subst, b_subst)
-        } else {
-            let tcx = self.tcx();
-            let opt_variances = tcx.variances_of(item_def_id);
-            relate::relate_substs_with_variances(
-                self,
-                item_def_id,
-                &opt_variances,
-                a_subst,
-                b_subst,
-                true,
-            )
-        }
-    }
-
-    fn relate_with_variance<T: Relate<'tcx>>(
-        &mut self,
-        variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T> {
-        let old_ambient_variance = self.ambient_variance;
-        self.ambient_variance = self.ambient_variance.xform(variance);
-
-        let result = self.relate(a, b);
-        self.ambient_variance = old_ambient_variance;
-        result
-    }
-
-    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
-        if let Some(&result) = self.cache.get(&t) {
-            return Ok(result);
-        }
-        debug!("generalize: t={:?}", t);
-
-        // Check to see whether the type we are generalizing references
-        // any other type variable related to `vid` via
-        // subtyping. This is basically our "occurs check", preventing
-        // us from creating infinitely sized types.
-        let result = match *t.kind() {
-            ty::Infer(ty::TyVar(vid)) => {
-                let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
-                let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
-                if sub_vid == self.for_vid_sub_root {
-                    // If sub-roots are equal, then `for_vid` and
-                    // `vid` are related via subtyping.
-                    Err(TypeError::CyclicTy(self.root_ty))
-                } else {
-                    let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
-                    match probe {
-                        TypeVariableValue::Known { value: u } => {
-                            debug!("generalize: known value {:?}", u);
-                            self.relate(u, u)
-                        }
-                        TypeVariableValue::Unknown { universe } => {
-                            match self.ambient_variance {
-                                // Invariant: no need to make a fresh type variable.
-                                ty::Invariant => {
-                                    if self.for_universe.can_name(universe) {
-                                        return Ok(t);
-                                    }
-                                }
-
-                                // Bivariant: make a fresh var, but we
-                                // may need a WF predicate. See
-                                // comment on `needs_wf` field for
-                                // more info.
-                                ty::Bivariant => self.needs_wf = true,
-
-                                // Co/contravariant: this will be
-                                // sufficiently constrained later on.
-                                ty::Covariant | ty::Contravariant => (),
-                            }
-
-                            let origin =
-                                *self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
-                            let new_var_id = self
-                                .infcx
-                                .inner
-                                .borrow_mut()
-                                .type_variables()
-                                .new_var(self.for_universe, origin);
-                            let u = self.tcx().mk_ty_var(new_var_id);
-
-                            // Record that we replaced `vid` with `new_var_id` as part of a generalization
-                            // operation. This is needed to detect cyclic types. To see why, see the
-                            // docs in the `type_variables` module.
-                            self.infcx.inner.borrow_mut().type_variables().sub(vid, new_var_id);
-                            debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
-                            Ok(u)
-                        }
-                    }
-                }
-            }
-            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
-                // No matter what mode we are in,
-                // integer/floating-point types must be equal to be
-                // relatable.
-                Ok(t)
-            }
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                let s = self.relate(substs, substs)?;
-                Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
-            }
-            _ => relate::super_relate_tys(self, t, t),
-        }?;
-
-        self.cache.insert(t, result);
-        Ok(result)
-    }
-
-    fn regions(
-        &mut self,
-        r: ty::Region<'tcx>,
-        r2: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
-        debug!("generalize: regions r={:?}", r);
-
-        match *r {
-            // Never make variables for regions bound within the type itself,
-            // nor for erased regions.
-            ty::ReLateBound(..) | ty::ReErased => {
-                return Ok(r);
-            }
-
-            ty::ReError(_) => {
-                return Ok(r);
-            }
-
-            ty::RePlaceholder(..)
-            | ty::ReVar(..)
-            | ty::ReStatic
-            | ty::ReEarlyBound(..)
-            | ty::ReFree(..) => {
-                // see common code below
-            }
-        }
-
-        // If we are in an invariant context, we can re-use the region
-        // as is, unless it happens to be in some universe that we
-        // can't name. (In the case of a region *variable*, we could
-        // use it if we promoted it into our universe, but we don't
-        // bother.)
-        if let ty::Invariant = self.ambient_variance {
-            let r_universe = self.infcx.universe_of_region(r);
-            if self.for_universe.can_name(r_universe) {
-                return Ok(r);
-            }
-        }
-
-        // FIXME: This is non-ideal because we don't give a
-        // very descriptive origin for this region variable.
-        Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
-    }
-
-    fn consts(
-        &mut self,
-        c: ty::Const<'tcx>,
-        c2: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
-        match c.kind() {
-            ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let variable_table = &mut inner.const_unification_table();
-                let var_value = variable_table.probe_value(vid);
-                match var_value.val {
-                    ConstVariableValue::Known { value: u } => {
-                        drop(inner);
-                        self.relate(u, u)
-                    }
-                    ConstVariableValue::Unknown { universe } => {
-                        if self.for_universe.can_name(universe) {
-                            Ok(c)
-                        } else {
-                            let new_var_id = variable_table.new_key(ConstVarValue {
-                                origin: var_value.origin,
-                                val: ConstVariableValue::Unknown { universe: self.for_universe },
-                            });
-                            Ok(self.tcx().mk_const(new_var_id, c.ty()))
-                        }
-                    }
-                }
-            }
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
-                let substs = self.relate_with_variance(
-                    ty::Variance::Invariant,
-                    ty::VarianceDiagInfo::default(),
-                    substs,
-                    substs,
-                )?;
-                Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
-            }
-            _ => relate::super_relate_consts(self, c, c),
-        }
-    }
-}
-
 pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
     /// Register obligations that must hold in order for this relation to hold
     fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
@@ -873,135 +496,3 @@
     let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
     TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b))
 }
-
-struct ConstInferUnifier<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'tcx>,
-
-    span: Span,
-
-    for_universe: ty::UniverseIndex,
-
-    /// The vid of the const variable that is in the process of being
-    /// instantiated; if we find this within the const we are folding,
-    /// that means we would have created a cyclic const.
-    target_vid: ty::ConstVid<'tcx>,
-}
-
-impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for ConstInferUnifier<'_, 'tcx> {
-    type Error = TypeError<'tcx>;
-
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, TypeError<'tcx>> {
-        match t.kind() {
-            &ty::Infer(ty::TyVar(vid)) => {
-                let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
-                let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
-                match probe {
-                    TypeVariableValue::Known { value: u } => {
-                        debug!("ConstOccursChecker: known value {:?}", u);
-                        u.try_fold_with(self)
-                    }
-                    TypeVariableValue::Unknown { universe } => {
-                        if self.for_universe.can_name(universe) {
-                            return Ok(t);
-                        }
-
-                        let origin =
-                            *self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
-                        let new_var_id = self
-                            .infcx
-                            .inner
-                            .borrow_mut()
-                            .type_variables()
-                            .new_var(self.for_universe, origin);
-                        Ok(self.interner().mk_ty_var(new_var_id))
-                    }
-                }
-            }
-            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t),
-            _ => t.try_super_fold_with(self),
-        }
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    fn try_fold_region(
-        &mut self,
-        r: ty::Region<'tcx>,
-    ) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
-        debug!("ConstInferUnifier: r={:?}", r);
-
-        match *r {
-            // Never make variables for regions bound within the type itself,
-            // nor for erased regions.
-            ty::ReLateBound(..) | ty::ReErased | ty::ReError(_) => {
-                return Ok(r);
-            }
-
-            ty::RePlaceholder(..)
-            | ty::ReVar(..)
-            | ty::ReStatic
-            | ty::ReEarlyBound(..)
-            | ty::ReFree(..) => {
-                // see common code below
-            }
-        }
-
-        let r_universe = self.infcx.universe_of_region(r);
-        if self.for_universe.can_name(r_universe) {
-            return Ok(r);
-        } else {
-            // FIXME: This is non-ideal because we don't give a
-            // very descriptive origin for this region variable.
-            Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
-        }
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, TypeError<'tcx>> {
-        match c.kind() {
-            ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                // Check if the current unification would end up
-                // unifying `target_vid` with a const which contains
-                // an inference variable which is unioned with `target_vid`.
-                //
-                // Not doing so can easily result in stack overflows.
-                if self
-                    .infcx
-                    .inner
-                    .borrow_mut()
-                    .const_unification_table()
-                    .unioned(self.target_vid, vid)
-                {
-                    return Err(TypeError::CyclicConst(c));
-                }
-
-                let var_value =
-                    self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
-                match var_value.val {
-                    ConstVariableValue::Known { value: u } => u.try_fold_with(self),
-                    ConstVariableValue::Unknown { universe } => {
-                        if self.for_universe.can_name(universe) {
-                            Ok(c)
-                        } else {
-                            let new_var_id =
-                                self.infcx.inner.borrow_mut().const_unification_table().new_key(
-                                    ConstVarValue {
-                                        origin: var_value.origin,
-                                        val: ConstVariableValue::Unknown {
-                                            universe: self.for_universe,
-                                        },
-                                    },
-                                );
-                            Ok(self.interner().mk_const(new_var_id, c.ty()))
-                        }
-                    }
-                }
-            }
-            _ => c.try_super_fold_with(self),
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index f90f767..42dfe4f6 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -1,7 +1,7 @@
 use crate::infer::DefineOpaqueTypes;
 use crate::traits::PredicateObligations;
 
-use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
+use super::combine::{CombineFields, ObligationEmittingRelation};
 use super::Subtype;
 
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -88,11 +88,11 @@
             }
 
             (&ty::Infer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
+                self.fields.instantiate(b, ty::Invariant, a_id, self.a_is_expected)?;
             }
 
             (_, &ty::Infer(TyVar(b_id))) => {
-                self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, ty::Invariant, b_id, self.a_is_expected)?;
             }
 
             (
@@ -104,7 +104,8 @@
             (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
             | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
                 if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
-                    && def_id.is_local() =>
+                    && def_id.is_local()
+                    && !self.tcx().trait_solver_next() =>
             {
                 self.fields.obligations.extend(
                     infcx
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ce70f39..35c05e8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1825,7 +1825,7 @@
                         s
                     };
                     if !(values.expected.is_simple_text() && values.found.is_simple_text())
-                        || (exp_found.map_or(false, |ef| {
+                        || (exp_found.is_some_and(|ef| {
                             // This happens when the type error is a subset of the expectation,
                             // like when you have two references but one is `usize` and the other
                             // is `f32`. In those cases we still want to show the `note`. If the
@@ -1877,7 +1877,7 @@
         let exp_found = match terr {
             // `terr` has more accurate type information than `exp_found` in match expressions.
             ty::error::TypeError::Sorts(terr)
-                if exp_found.map_or(false, |ef| terr.found == ef.found) =>
+                if exp_found.is_some_and(|ef| terr.found == ef.found) =>
             {
                 Some(terr)
             }
@@ -1961,7 +1961,7 @@
                     if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
                         && let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
                         && !code.starts_with("\\u") // forbid all Unicode escapes
-                        && code.chars().next().map_or(false, |c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
+                        && code.chars().next().is_some_and(|c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
                     {
                         suggestions.push(TypeErrorAdditionalDiags::MeantByteLiteral { span, code: escape_literal(code) })
                     }
@@ -2329,7 +2329,7 @@
                         .source_map()
                         .span_to_prev_source(p.span.shrink_to_hi())
                         .ok()
-                        .map_or(false, |s| *s.as_bytes().last().unwrap() == b'&')
+                        .is_some_and(|s| *s.as_bytes().last().unwrap() == b'&')
                     {
                         add_lt_suggs
                             .push(Some(
@@ -2723,7 +2723,7 @@
             | (ty::Infer(ty::InferTy::TyVar(_)), _)
             | (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a),
             (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch),
-            _ => relate::super_relate_tys(self, a, b),
+            _ => relate::structurally_relate_tys(self, a, b),
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 5000b01..f3b2ec4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -671,7 +671,7 @@
                 receiver.span.from_expansion()
             }
             InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
-                data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion)
+                data.span().from_expansion() || should_wrap_expr.is_some_and(Span::from_expansion)
             }
         };
         source_from_expansion || self.span.from_expansion()
@@ -984,7 +984,7 @@
     ) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a {
         let tcx = self.infcx.tcx;
         let have_turbofish = path.segments.iter().any(|segment| {
-            segment.args.map_or(false, |args| args.args.iter().any(|arg| arg.is_ty_or_const()))
+            segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
         });
         // The last segment of a path often has `Res::Err` and the
         // correct `Res` is the one of the whole path.
diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs
new file mode 100644
index 0000000..d4a1dacd
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/generalize.rs
@@ -0,0 +1,479 @@
+use rustc_data_structures::sso::SsoHashMap;
+use rustc_hir::def_id::DefId;
+use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::Span;
+
+use crate::infer::nll_relate::TypeRelatingDelegate;
+use crate::infer::type_variable::TypeVariableValue;
+use crate::infer::{InferCtxt, RegionVariableOrigin};
+
+/// Attempts to generalize `term` for the type variable `for_vid`.
+/// This checks for cycles -- that is, whether the type `term`
+/// references `for_vid`.
+pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Relate<'tcx>>(
+    infcx: &InferCtxt<'tcx>,
+    delegate: &mut D,
+    term: T,
+    for_vid: impl Into<ty::TermVid<'tcx>>,
+    ambient_variance: ty::Variance,
+) -> RelateResult<'tcx, Generalization<T>> {
+    let (for_universe, root_vid) = match for_vid.into() {
+        ty::TermVid::Ty(ty_vid) => (
+            infcx.probe_ty_var(ty_vid).unwrap_err(),
+            ty::TermVid::Ty(infcx.inner.borrow_mut().type_variables().sub_root_var(ty_vid)),
+        ),
+        ty::TermVid::Const(ct_vid) => (
+            infcx.probe_const_var(ct_vid).unwrap_err(),
+            ty::TermVid::Const(infcx.inner.borrow_mut().const_unification_table().find(ct_vid)),
+        ),
+    };
+
+    let mut generalizer = Generalizer {
+        infcx,
+        delegate,
+        ambient_variance,
+        root_vid,
+        for_universe,
+        root_term: term.into(),
+        needs_wf: false,
+        cache: Default::default(),
+    };
+
+    assert!(!term.has_escaping_bound_vars());
+    let value = generalizer.relate(term, term)?;
+    let needs_wf = generalizer.needs_wf;
+    Ok(Generalization { value, needs_wf })
+}
+
+/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
+/// in the generalizer code.
+pub trait GeneralizerDelegate<'tcx> {
+    fn param_env(&self) -> ty::ParamEnv<'tcx>;
+
+    fn forbid_inference_vars() -> bool;
+
+    fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
+}
+
+pub struct CombineDelegate<'cx, 'tcx> {
+    pub infcx: &'cx InferCtxt<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub span: Span,
+}
+
+impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+
+    fn forbid_inference_vars() -> bool {
+        false
+    }
+
+    fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
+        // FIXME: This is non-ideal because we don't give a
+        // very descriptive origin for this region variable.
+        self.infcx
+            .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe)
+    }
+}
+
+impl<'tcx, T> GeneralizerDelegate<'tcx> for T
+where
+    T: TypeRelatingDelegate<'tcx>,
+{
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        <Self as TypeRelatingDelegate<'tcx>>::param_env(self)
+    }
+
+    fn forbid_inference_vars() -> bool {
+        <Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
+    }
+
+    fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
+        <Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
+    }
+}
+
+/// The "generalizer" is used when handling inference variables.
+///
+/// The basic strategy for handling a constraint like `?A <: B` is to
+/// apply a "generalization strategy" to the term `B` -- this replaces
+/// all the lifetimes in the term `B` with fresh inference variables.
+/// (You can read more about the strategy in this [blog post].)
+///
+/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
+/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
+/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
+/// establishes `'0: 'x` as a constraint.
+///
+/// [blog post]: https://is.gd/0hKvIr
+struct Generalizer<'me, 'tcx, D> {
+    infcx: &'me InferCtxt<'tcx>,
+
+    /// This is used to abstract the behaviors of the three previous
+    /// generalizer-like implementations (`Generalizer`, `TypeGeneralizer`,
+    /// and `ConstInferUnifier`). See [`GeneralizerDelegate`] for more
+    /// information.
+    delegate: &'me mut D,
+
+    /// After we generalize this type, we are going to relate it to
+    /// some other type. What will be the variance at this point?
+    ambient_variance: ty::Variance,
+
+    /// The vid of the type variable that is in the process of being
+    /// instantiated. If we find this within the value we are folding,
+    /// that means we would have created a cyclic value.
+    root_vid: ty::TermVid<'tcx>,
+
+    /// The universe of the type variable that is in the process of being
+    /// instantiated. If we find anything that this universe cannot name,
+    /// we reject the relation.
+    for_universe: ty::UniverseIndex,
+
+    /// The root term (const or type) we're generalizing. Used for cycle errors.
+    root_term: Term<'tcx>,
+
+    cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
+
+    /// See the field `needs_wf` in `Generalization`.
+    needs_wf: bool,
+}
+
+impl<'tcx, D> Generalizer<'_, 'tcx, D> {
+    /// Create an error that corresponds to the term kind in `root_term`
+    fn cyclic_term_error(&self) -> TypeError<'tcx> {
+        match self.root_term.unpack() {
+            ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
+            ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
+        }
+    }
+}
+
+impl<'tcx, D> TypeRelation<'tcx> for Generalizer<'_, 'tcx, D>
+where
+    D: GeneralizerDelegate<'tcx>,
+{
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.delegate.param_env()
+    }
+
+    fn tag(&self) -> &'static str {
+        "Generalizer"
+    }
+
+    fn a_is_expected(&self) -> bool {
+        true
+    }
+
+    fn relate_item_substs(
+        &mut self,
+        item_def_id: DefId,
+        a_subst: ty::SubstsRef<'tcx>,
+        b_subst: ty::SubstsRef<'tcx>,
+    ) -> RelateResult<'tcx, ty::SubstsRef<'tcx>> {
+        if self.ambient_variance == ty::Variance::Invariant {
+            // Avoid fetching the variance if we are in an invariant
+            // context; no need, and it can induce dependency cycles
+            // (e.g., #41849).
+            relate::relate_substs(self, a_subst, b_subst)
+        } else {
+            let tcx = self.tcx();
+            let opt_variances = tcx.variances_of(item_def_id);
+            relate::relate_substs_with_variances(
+                self,
+                item_def_id,
+                opt_variances,
+                a_subst,
+                b_subst,
+                true,
+            )
+        }
+    }
+
+    #[instrument(level = "debug", skip(self, variance, b), ret)]
+    fn relate_with_variance<T: Relate<'tcx>>(
+        &mut self,
+        variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        let old_ambient_variance = self.ambient_variance;
+        self.ambient_variance = self.ambient_variance.xform(variance);
+        debug!(?self.ambient_variance, "new ambient variance");
+        let r = self.relate(a, b)?;
+        self.ambient_variance = old_ambient_variance;
+        Ok(r)
+    }
+
+    #[instrument(level = "debug", skip(self, t2), ret)]
+    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+        if let Some(&result) = self.cache.get(&t) {
+            return Ok(result);
+        }
+
+        // Check to see whether the type we are generalizing references
+        // any other type variable related to `vid` via
+        // subtyping. This is basically our "occurs check", preventing
+        // us from creating infinitely sized types.
+        let g = match *t.kind() {
+            ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
+                if D::forbid_inference_vars() =>
+            {
+                bug!("unexpected inference variable encountered in NLL generalization: {t}");
+            }
+
+            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                bug!("unexpected infer type: {t}")
+            }
+
+            ty::Infer(ty::TyVar(vid)) => {
+                let mut inner = self.infcx.inner.borrow_mut();
+                let vid = inner.type_variables().root_var(vid);
+                let sub_vid = inner.type_variables().sub_root_var(vid);
+
+                if ty::TermVid::Ty(sub_vid) == self.root_vid {
+                    // If sub-roots are equal, then `root_vid` and
+                    // `vid` are related via subtyping.
+                    Err(self.cyclic_term_error())
+                } else {
+                    let probe = inner.type_variables().probe(vid);
+                    match probe {
+                        TypeVariableValue::Known { value: u } => {
+                            drop(inner);
+                            self.relate(u, u)
+                        }
+                        TypeVariableValue::Unknown { universe } => {
+                            match self.ambient_variance {
+                                // Invariant: no need to make a fresh type variable
+                                // if we can name the universe.
+                                ty::Invariant => {
+                                    if self.for_universe.can_name(universe) {
+                                        return Ok(t);
+                                    }
+                                }
+
+                                // Bivariant: make a fresh var, but we
+                                // may need a WF predicate. See
+                                // comment on `needs_wf` field for
+                                // more info.
+                                ty::Bivariant => self.needs_wf = true,
+
+                                // Co/contravariant: this will be
+                                // sufficiently constrained later on.
+                                ty::Covariant | ty::Contravariant => (),
+                            }
+
+                            let origin = *inner.type_variables().var_origin(vid);
+                            let new_var_id =
+                                inner.type_variables().new_var(self.for_universe, origin);
+                            let u = self.tcx().mk_ty_var(new_var_id);
+
+                            // Record that we replaced `vid` with `new_var_id` as part of a generalization
+                            // operation. This is needed to detect cyclic types. To see why, see the
+                            // docs in the `type_variables` module.
+                            inner.type_variables().sub(vid, new_var_id);
+                            debug!("replacing original vid={:?} with new={:?}", vid, u);
+                            Ok(u)
+                        }
+                    }
+                }
+            }
+
+            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
+                // No matter what mode we are in,
+                // integer/floating-point types must be equal to be
+                // relatable.
+                Ok(t)
+            }
+
+            ty::Placeholder(placeholder) => {
+                if self.for_universe.can_name(placeholder.universe) {
+                    Ok(t)
+                } else {
+                    debug!(
+                        "root universe {:?} cannot name placeholder in universe {:?}",
+                        self.for_universe, placeholder.universe
+                    );
+                    Err(TypeError::Mismatch)
+                }
+            }
+
+            _ => relate::structurally_relate_tys(self, t, t),
+        }?;
+
+        self.cache.insert(t, g);
+        Ok(g)
+    }
+
+    #[instrument(level = "debug", skip(self, r2), ret)]
+    fn regions(
+        &mut self,
+        r: ty::Region<'tcx>,
+        r2: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+        match *r {
+            // Never make variables for regions bound within the type itself,
+            // nor for erased regions.
+            ty::ReLateBound(..) | ty::ReErased => {
+                return Ok(r);
+            }
+
+            // It doesn't really matter for correctness if we generalize ReError,
+            // since we're already on a doomed compilation path.
+            ty::ReError(_) => {
+                return Ok(r);
+            }
+
+            ty::RePlaceholder(..)
+            | ty::ReVar(..)
+            | ty::ReStatic
+            | ty::ReEarlyBound(..)
+            | ty::ReFree(..) => {
+                // see common code below
+            }
+        }
+
+        // If we are in an invariant context, we can re-use the region
+        // as is, unless it happens to be in some universe that we
+        // can't name.
+        if let ty::Invariant = self.ambient_variance {
+            let r_universe = self.infcx.universe_of_region(r);
+            if self.for_universe.can_name(r_universe) {
+                return Ok(r);
+            }
+        }
+
+        Ok(self.delegate.generalize_region(self.for_universe))
+    }
+
+    #[instrument(level = "debug", skip(self, c2), ret)]
+    fn consts(
+        &mut self,
+        c: ty::Const<'tcx>,
+        c2: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+        match c.kind() {
+            ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
+                bug!("unexpected inference variable encountered in NLL generalization: {:?}", c);
+            }
+            ty::ConstKind::Infer(InferConst::Var(vid)) => {
+                // If root const vids are equal, then `root_vid` and
+                // `vid` are related and we'd be inferring an infinitely
+                // deep const.
+                if ty::TermVid::Const(
+                    self.infcx.inner.borrow_mut().const_unification_table().find(vid),
+                ) == self.root_vid
+                {
+                    return Err(self.cyclic_term_error());
+                }
+
+                let mut inner = self.infcx.inner.borrow_mut();
+                let variable_table = &mut inner.const_unification_table();
+                let var_value = variable_table.probe_value(vid);
+                match var_value.val {
+                    ConstVariableValue::Known { value: u } => {
+                        drop(inner);
+                        self.relate(u, u)
+                    }
+                    ConstVariableValue::Unknown { universe } => {
+                        if self.for_universe.can_name(universe) {
+                            Ok(c)
+                        } else {
+                            let new_var_id = variable_table.new_key(ConstVarValue {
+                                origin: var_value.origin,
+                                val: ConstVariableValue::Unknown { universe: self.for_universe },
+                            });
+                            Ok(self.tcx().mk_const(new_var_id, c.ty()))
+                        }
+                    }
+                }
+            }
+            // FIXME: remove this branch once `structurally_relate_consts` is fully
+            // structural.
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
+                let substs = self.relate_with_variance(
+                    ty::Variance::Invariant,
+                    ty::VarianceDiagInfo::default(),
+                    substs,
+                    substs,
+                )?;
+                Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
+            }
+            ty::ConstKind::Placeholder(placeholder) => {
+                if self.for_universe.can_name(placeholder.universe) {
+                    Ok(c)
+                } else {
+                    debug!(
+                        "root universe {:?} cannot name placeholder in universe {:?}",
+                        self.for_universe, placeholder.universe
+                    );
+                    Err(TypeError::Mismatch)
+                }
+            }
+            _ => relate::structurally_relate_consts(self, c, c),
+        }
+    }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    fn binders<T>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        _: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
+    where
+        T: Relate<'tcx>,
+    {
+        let result = self.relate(a.skip_binder(), a.skip_binder())?;
+        Ok(a.rebind(result))
+    }
+}
+
+/// Result from a generalization operation. This includes
+/// not only the generalized type, but also a bool flag
+/// indicating whether further WF checks are needed.
+#[derive(Debug)]
+pub struct Generalization<T> {
+    pub value: T,
+
+    /// If true, then the generalized type may not be well-formed,
+    /// even if the source type is well-formed, so we should add an
+    /// additional check to enforce that it is. This arises in
+    /// particular around 'bivariant' type parameters that are only
+    /// constrained by a where-clause. As an example, imagine a type:
+    ///
+    ///     struct Foo<A, B> where A: Iterator<Item = B> {
+    ///         data: A
+    ///     }
+    ///
+    /// here, `A` will be covariant, but `B` is
+    /// unconstrained. However, whatever it is, for `Foo` to be WF, it
+    /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
+    /// then after generalization we will wind up with a type like
+    /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
+    /// ?D>` (or `>:`), we will wind up with the requirement that `?A
+    /// <: ?C`, but no particular relationship between `?B` and `?D`
+    /// (after all, we do not know the variance of the normalized form
+    /// of `A::Item` with respect to `A`). If we do nothing else, this
+    /// may mean that `?D` goes unconstrained (as in #41677). So, in
+    /// this scenario where we create a new type variable in a
+    /// bivariant context, we set the `needs_wf` flag to true. This
+    /// will force the calling code to check that `WF(Foo<?C, ?D>)`
+    /// holds, which in turn implies that `?C::Item == ?D`. So once
+    /// `?C` is constrained, that should suffice to restrict `?D`.
+    pub needs_wf: bool,
+}
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs
index 7f4c141..7190d33 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/lattice.rs
@@ -108,9 +108,12 @@
             &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
             &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
         ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
+
         (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
         | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
-            if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() =>
+            if this.define_opaque_types() == DefineOpaqueTypes::Yes
+                && def_id.is_local()
+                && !this.tcx().trait_solver_next() =>
         {
             this.register_obligations(
                 infcx
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 9a95a9c..cd99fc3 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -24,7 +24,7 @@
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::traits::select;
+use rustc_middle::traits::{select, DefiningAnchor};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BoundVarReplacerDelegate;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -58,6 +58,7 @@
 pub mod free_regions;
 mod freshen;
 mod fudge;
+mod generalize;
 mod glb;
 mod higher_ranked;
 pub mod lattice;
@@ -230,17 +231,6 @@
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum DefiningAnchor {
-    /// `DefId` of the item.
-    Bind(LocalDefId),
-    /// When opaque types are not resolved, we `Bubble` up, meaning
-    /// return the opaque/hidden type pair from query, for caller of query to handle it.
-    Bubble,
-    /// Used to catch type mismatch errors when handling opaque types.
-    Error,
-}
-
 pub struct InferCtxt<'tcx> {
     pub tcx: TyCtxt<'tcx>,
 
@@ -1533,7 +1523,7 @@
             if let Some(ct) = tcx.thir_abstract_const(unevaluated.def)? {
                 let ct = tcx.expand_abstract_consts(ct.subst(tcx, substs));
                 if let Err(e) = ct.error_reported() {
-                    return Err(ErrorHandled::Reported(e));
+                    return Err(ErrorHandled::Reported(e.into()));
                 } else if ct.has_non_region_infer() || ct.has_non_region_param() {
                     return Err(ErrorHandled::TooGeneric);
                 } else {
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 9c139d1..d3fd01b 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -21,21 +21,20 @@
 //!   thing we relate in chalk are basically domain goals and their
 //!   constituents)
 
-use crate::infer::InferCtxt;
-use crate::infer::{ConstVarValue, ConstVariableValue};
-use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::traits::{Obligation, PredicateObligations};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
 use rustc_span::{Span, Symbol};
 use std::fmt::Debug;
 
-use super::combine::ObligationEmittingRelation;
+use crate::infer::combine::ObligationEmittingRelation;
+use crate::infer::generalize::{self, Generalization};
+use crate::infer::InferCtxt;
+use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::traits::{Obligation, PredicateObligations};
 
 pub struct TypeRelating<'me, 'tcx, D>
 where
@@ -198,7 +197,7 @@
             _ => (),
         }
 
-        let generalized_ty = self.generalize_value(value_ty, vid)?;
+        let generalized_ty = self.generalize(value_ty, vid)?;
         debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty);
 
         if D::forbid_inference_vars() {
@@ -217,26 +216,15 @@
         result
     }
 
-    fn generalize_value<T: Relate<'tcx>>(
-        &mut self,
-        value: T,
-        for_vid: ty::TyVid,
-    ) -> RelateResult<'tcx, T> {
-        let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
-
-        if value.has_escaping_bound_vars() {
-            bug!("trying to instantiate {for_vid:?} with escaping bound vars: {value:?}");
-        }
-
-        let mut generalizer = TypeGeneralizer {
-            infcx: self.infcx,
-            delegate: &mut self.delegate,
-            ambient_variance: self.ambient_variance,
-            for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
-            universe,
-        };
-
-        generalizer.relate(value, value)
+    fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
+        let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
+            self.infcx,
+            &mut self.delegate,
+            ty,
+            for_vid,
+            self.ambient_variance,
+        )?;
+        Ok(ty)
     }
 
     fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
@@ -503,16 +491,22 @@
             (
                 &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
                 &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
-            ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
-                self.tcx().sess.delay_span_bug(
-                    self.delegate.span(),
-                    "failure to relate an opaque to itself should result in an error later on",
-                );
-                if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
-            }),
+            ) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
+                infcx.super_combine_tys(self, a, b).or_else(|err| {
+                    // This behavior is only there for the old solver, the new solver
+                    // shouldn't ever fail. Instead, it unconditionally emits an
+                    // alias-relate goal.
+                    assert!(!self.tcx().trait_solver_next());
+                    self.tcx().sess.delay_span_bug(
+                        self.delegate.span(),
+                        "failure to relate an opaque to itself should result in an error later on",
+                    );
+                    if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+                })
+            }
             (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
             | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
-                if def_id.is_local() =>
+                if def_id.is_local() && !self.tcx().trait_solver_next() =>
             {
                 self.relate_opaques(a, b)
             }
@@ -716,235 +710,3 @@
         })]);
     }
 }
-
-/// The "type generalizer" is used when handling inference variables.
-///
-/// The basic strategy for handling a constraint like `?A <: B` is to
-/// apply a "generalization strategy" to the type `B` -- this replaces
-/// all the lifetimes in the type `B` with fresh inference
-/// variables. (You can read more about the strategy in this [blog
-/// post].)
-///
-/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
-/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
-/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
-/// establishes `'0: 'x` as a constraint.
-///
-/// [blog post]: https://is.gd/0hKvIr
-struct TypeGeneralizer<'me, 'tcx, D>
-where
-    D: TypeRelatingDelegate<'tcx>,
-{
-    infcx: &'me InferCtxt<'tcx>,
-
-    delegate: &'me mut D,
-
-    /// After we generalize this type, we are going to relate it to
-    /// some other type. What will be the variance at this point?
-    ambient_variance: ty::Variance,
-
-    /// The vid of the type variable that is in the process of being
-    /// instantiated. If we find this within the value we are folding,
-    /// that means we would have created a cyclic value.
-    for_vid_sub_root: ty::TyVid,
-
-    /// The universe of the type variable that is in the process of being
-    /// instantiated. If we find anything that this universe cannot name,
-    /// we reject the relation.
-    universe: ty::UniverseIndex,
-}
-
-impl<'tcx, D> TypeRelation<'tcx> for TypeGeneralizer<'_, 'tcx, D>
-where
-    D: TypeRelatingDelegate<'tcx>,
-{
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.delegate.param_env()
-    }
-
-    fn tag(&self) -> &'static str {
-        "nll::generalizer"
-    }
-
-    fn a_is_expected(&self) -> bool {
-        true
-    }
-
-    fn relate_with_variance<T: Relate<'tcx>>(
-        &mut self,
-        variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T> {
-        debug!(
-            "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
-            variance, a, b
-        );
-
-        let old_ambient_variance = self.ambient_variance;
-        self.ambient_variance = self.ambient_variance.xform(variance);
-
-        debug!(
-            "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}",
-            self.ambient_variance
-        );
-
-        let r = self.relate(a, b)?;
-
-        self.ambient_variance = old_ambient_variance;
-
-        debug!("TypeGeneralizer::relate_with_variance: r={:?}", r);
-
-        Ok(r)
-    }
-
-    fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        use crate::infer::type_variable::TypeVariableValue;
-
-        debug!("TypeGeneralizer::tys(a={:?})", a);
-
-        match *a.kind() {
-            ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
-                if D::forbid_inference_vars() =>
-            {
-                bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
-            }
-
-            ty::Infer(ty::TyVar(vid)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let variables = &mut inner.type_variables();
-                let vid = variables.root_var(vid);
-                let sub_vid = variables.sub_root_var(vid);
-                if sub_vid == self.for_vid_sub_root {
-                    // If sub-roots are equal, then `for_vid` and
-                    // `vid` are related via subtyping.
-                    debug!("TypeGeneralizer::tys: occurs check failed");
-                    Err(TypeError::Mismatch)
-                } else {
-                    match variables.probe(vid) {
-                        TypeVariableValue::Known { value: u } => {
-                            drop(inner);
-                            self.relate(u, u)
-                        }
-                        TypeVariableValue::Unknown { universe: _universe } => {
-                            if self.ambient_variance == ty::Bivariant {
-                                // FIXME: we may need a WF predicate (related to #54105).
-                            }
-
-                            let origin = *variables.var_origin(vid);
-
-                            // Replacing with a new variable in the universe `self.universe`,
-                            // it will be unified later with the original type variable in
-                            // the universe `_universe`.
-                            let new_var_id = variables.new_var(self.universe, origin);
-
-                            let u = self.tcx().mk_ty_var(new_var_id);
-                            debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
-                            Ok(u)
-                        }
-                    }
-                }
-            }
-
-            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
-                // No matter what mode we are in,
-                // integer/floating-point types must be equal to be
-                // relatable.
-                Ok(a)
-            }
-
-            ty::Placeholder(placeholder) => {
-                if self.universe.cannot_name(placeholder.universe) {
-                    debug!(
-                        "TypeGeneralizer::tys: root universe {:?} cannot name\
-                         placeholder in universe {:?}",
-                        self.universe, placeholder.universe
-                    );
-                    Err(TypeError::Mismatch)
-                } else {
-                    Ok(a)
-                }
-            }
-
-            _ => relate::super_relate_tys(self, a, a),
-        }
-    }
-
-    fn regions(
-        &mut self,
-        a: ty::Region<'tcx>,
-        _: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug!("TypeGeneralizer::regions(a={:?})", a);
-
-        if let ty::ReLateBound(..) = *a {
-            return Ok(a);
-        }
-
-        // For now, we just always create a fresh region variable to
-        // replace all the regions in the source type. In the main
-        // type checker, we special case the case where the ambient
-        // variance is `Invariant` and try to avoid creating a fresh
-        // region variable, but since this comes up so much less in
-        // NLL (only when users use `_` etc) it is much less
-        // important.
-        //
-        // As an aside, since these new variables are created in
-        // `self.universe` universe, this also serves to enforce the
-        // universe scoping rules.
-        //
-        // FIXME(#54105) -- if the ambient variance is bivariant,
-        // though, we may however need to check well-formedness or
-        // risk a problem like #41677 again.
-        let replacement_region_vid = self.delegate.generalize_existential(self.universe);
-
-        Ok(replacement_region_vid)
-    }
-
-    fn consts(
-        &mut self,
-        a: ty::Const<'tcx>,
-        _: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        match a.kind() {
-            ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
-                bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
-            }
-            ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let variable_table = &mut inner.const_unification_table();
-                let var_value = variable_table.probe_value(vid);
-                match var_value.val.known() {
-                    Some(u) => self.relate(u, u),
-                    None => {
-                        let new_var_id = variable_table.new_key(ConstVarValue {
-                            origin: var_value.origin,
-                            val: ConstVariableValue::Unknown { universe: self.universe },
-                        });
-                        Ok(self.tcx().mk_const(new_var_id, a.ty()))
-                    }
-                }
-            }
-            ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a),
-            _ => relate::super_relate_consts(self, a, a),
-        }
-    }
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        _: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<'tcx>,
-    {
-        debug!("TypeGeneralizer::binders(a={:?})", a);
-        let result = self.relate(a.skip_binder(), a.skip_binder())?;
-        Ok(a.rebind(result))
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 545310a..9d5ec22 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -1,14 +1,14 @@
 use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use super::{DefineOpaqueTypes, InferResult};
 use crate::errors::OpaqueHiddenTypeDiag;
-use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
-use crate::traits;
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::{self, PredicateObligation};
 use hir::def_id::{DefId, LocalDefId};
 use hir::OpaqueTyOrigin;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
-use rustc_middle::traits::ObligationCause;
+use rustc_middle::traits::{DefiningAnchor, ObligationCause};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::GenericArgKind;
@@ -48,12 +48,18 @@
         span: Span,
         param_env: ty::ParamEnv<'tcx>,
     ) -> InferOk<'tcx, T> {
+        // We handle opaque types differently in the new solver.
+        if self.tcx.trait_solver_next() {
+            return InferOk { value, obligations: vec![] };
+        }
+
         if !value.has_opaque_types() {
             return InferOk { value, obligations: vec![] };
         }
+
         let mut obligations = vec![];
         let replace_opaque_type = |def_id: DefId| {
-            def_id.as_local().map_or(false, |def_id| self.opaque_type_origin(def_id).is_some())
+            def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
         };
         let value = value.fold_with(&mut BottomUpFolder {
             tcx: self.tcx,
@@ -521,29 +527,68 @@
         origin: hir::OpaqueTyOrigin,
         a_is_expected: bool,
     ) -> InferResult<'tcx, ()> {
-        let tcx = self.tcx;
-        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
         // Ideally, we'd get the span where *this specific `ty` came
         // from*, but right now we just use the span from the overall
         // value being folded. In simple cases like `-> impl Foo`,
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
         let span = cause.span;
-
-        let mut obligations = vec![];
         let prev = self.inner.borrow_mut().opaque_types().register(
-            OpaqueTypeKey { def_id, substs },
+            opaque_type_key,
             OpaqueHiddenType { ty: hidden_ty, span },
             origin,
         );
-        if let Some(prev) = prev {
-            obligations = self
-                .at(&cause, param_env)
+        let mut obligations = if let Some(prev) = prev {
+            self.at(&cause, param_env)
                 .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
-                .obligations;
-        }
+                .obligations
+        } else {
+            Vec::new()
+        };
 
+        self.add_item_bounds_for_hidden_type(
+            opaque_type_key,
+            cause,
+            param_env,
+            hidden_ty,
+            &mut obligations,
+        );
+
+        Ok(InferOk { value: (), obligations })
+    }
+
+    /// Registers an opaque's hidden type -- only should be used when the opaque
+    /// can be defined. For something more fallible -- checks the anchors, tries
+    /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`.
+    pub fn register_hidden_type_in_new_solver(
+        &self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        hidden_ty: Ty<'tcx>,
+    ) -> InferResult<'tcx, ()> {
+        assert!(self.tcx.trait_solver_next());
+        let origin = self
+            .opaque_type_origin(opaque_type_key.def_id)
+            .expect("should be called for defining usages only");
+        self.register_hidden_type(
+            opaque_type_key,
+            ObligationCause::dummy(),
+            param_env,
+            hidden_ty,
+            origin,
+            true,
+        )
+    }
+
+    pub fn add_item_bounds_for_hidden_type(
+        &self,
+        OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        hidden_ty: Ty<'tcx>,
+        obligations: &mut Vec<PredicateObligation<'tcx>>,
+    ) {
+        let tcx = self.tcx;
         let item_bounds = tcx.explicit_item_bounds(def_id);
 
         for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
@@ -556,14 +601,15 @@
                     // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
                     ty::Alias(ty::Projection, projection_ty)
                         if !projection_ty.has_escaping_bound_vars()
-                            && !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
+                            && !tcx.is_impl_trait_in_trait(projection_ty.def_id)
+                            && !tcx.trait_solver_next() =>
                     {
                         self.infer_projection(
                             param_env,
                             projection_ty,
                             cause.clone(),
                             0,
-                            &mut obligations,
+                            obligations,
                         )
                     }
                     // Replace all other mentions of the same opaque type with the hidden type,
@@ -589,10 +635,10 @@
                 predicate.kind().skip_binder()
             {
                 if projection.term.references_error() {
-                    // No point on adding these obligations since there's a type error involved.
-                    return Ok(InferOk { value: (), obligations: vec![] });
+                    // No point on adding any obligations since there's a type error involved.
+                    obligations.clear();
+                    return;
                 }
-                trace!("{:#?}", projection.term);
             }
             // Require that the predicate holds for the concrete type.
             debug!(?predicate);
@@ -603,7 +649,6 @@
                 predicate,
             ));
         }
-        Ok(InferOk { value: (), obligations })
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 75ce0f8..cd2462d 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -187,7 +187,7 @@
         } else if pattern == value {
             Ok(pattern)
         } else {
-            relate::super_relate_tys(self, pattern, value)
+            relate::structurally_relate_tys(self, pattern, value)
         }
     }
 
@@ -201,7 +201,7 @@
         if pattern == value {
             Ok(pattern)
         } else {
-            relate::super_relate_consts(self, pattern, value)
+            relate::structurally_relate_consts(self, pattern, value)
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 3766c25..ceafafb 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -1,4 +1,4 @@
-use super::combine::{CombineFields, RelationDir};
+use super::combine::CombineFields;
 use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin};
 
 use crate::traits::{Obligation, PredicateObligations};
@@ -108,11 +108,11 @@
                 Ok(a)
             }
             (&ty::Infer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
+                self.fields.instantiate(b, ty::Contravariant, a_id, !self.a_is_expected)?;
                 Ok(a)
             }
             (_, &ty::Infer(TyVar(b_id))) => {
-                self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, ty::Covariant, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
@@ -131,7 +131,8 @@
             (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
             | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
                 if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
-                    && def_id.is_local() =>
+                    && def_id.is_local()
+                    && !self.tcx().trait_solver_next() =>
             {
                 self.fields.obligations.extend(
                     infcx
diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index 3799489..be1a75f 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -1,9 +1,28 @@
+interface_cant_emit_mir =
+    could not emit MIR: {$error}
+
+interface_emoji_identifier =
+    identifiers cannot contain emoji: `{$ident}`
+
+interface_error_writing_dependencies =
+    error writing dependencies to `{$path}`: {$error}
+
+interface_failed_writing_file =
+    failed to write file {$path}: {$error}"
+
 interface_ferris_identifier =
     Ferris cannot be used as an identifier
     .suggestion = try using their name instead
 
-interface_emoji_identifier =
-    identifiers cannot contain emoji: `{$ident}`
+interface_generated_file_conflicts_with_directory =
+    the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}"
+
+interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
+
+interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
+
+interface_input_file_would_be_overwritten =
+    the input file "{$path}" would be overwritten by the generated executable
 
 interface_mixed_bin_crate =
     cannot mix `bin` crate type with others
@@ -11,23 +30,14 @@
 interface_mixed_proc_macro_crate =
     cannot mix `proc-macro` crate type with others
 
-interface_error_writing_dependencies =
-    error writing dependencies to `{$path}`: {$error}
-
-interface_input_file_would_be_overwritten =
-    the input file "{$path}" would be overwritten by the generated executable
-
-interface_generated_file_conflicts_with_directory =
-    the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}"
-
-interface_temps_dir_error =
-    failed to find or create the directory specified by `--temps-dir`
+interface_multiple_output_types_adaption =
+    due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
 
 interface_out_dir_error =
     failed to find or create the directory specified by `--out-dir`
 
-interface_cant_emit_mir =
-    could not emit MIR: {$error}
+interface_proc_macro_crate_panic_abort =
+    building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
 
 interface_rustc_error_fatal =
     fatal error triggered by #[rustc_error]
@@ -35,18 +45,8 @@
 interface_rustc_error_unexpected_annotation =
     unexpected annotation used with `#[rustc_error(...)]`!
 
-interface_failed_writing_file =
-    failed to write file {$path}: {$error}"
-
-interface_proc_macro_crate_panic_abort =
-    building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+interface_temps_dir_error =
+    failed to find or create the directory specified by `--temps-dir`
 
 interface_unsupported_crate_type_for_target =
     dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
-
-interface_multiple_output_types_adaption =
-    due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
-
-interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
-
-interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 51354c2..39d5689 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -3,12 +3,13 @@
 use rustc_ast::token;
 use rustc_ast::{self as ast, LitKind, MetaItemKind};
 use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_data_structures::defer;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::OnDrop;
 use rustc_errors::registry::Registry;
 use rustc_errors::{ErrorGuaranteed, Handler};
 use rustc_lint::LintStore;
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::{bug, ty};
 use rustc_parse::maybe_new_parser_from_source_str;
 use rustc_query_impl::QueryCtxt;
@@ -37,8 +38,7 @@
     pub(crate) sess: Lrc<Session>,
     codegen_backend: Lrc<Box<dyn CodegenBackend>>,
     pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
-    pub(crate) override_queries:
-        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
+    pub(crate) override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>,
 }
 
 impl Compiler {
@@ -60,6 +60,11 @@
     }
 }
 
+#[allow(rustc::bad_opt_access)]
+pub fn set_thread_safe_mode(sopts: &config::UnstableOptions) {
+    rustc_data_structures::sync::set_dyn_thread_safe_mode(sopts.threads > 1);
+}
+
 /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
 pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
     rustc_span::create_default_session_if_not_set_then(move |_| {
@@ -75,7 +80,7 @@
                     ($reason: expr) => {
                         early_error(
                             ErrorOutputType::default(),
-                            &format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s),
+                            format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s),
                         );
                     };
                 }
@@ -134,10 +139,7 @@
                 ($reason: expr) => {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!(
-                            concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
-                            s
-                        ),
+                        format!(concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s),
                     )
                 };
             }
@@ -270,8 +272,7 @@
     /// the list of queries.
     ///
     /// The second parameter is local providers and the third parameter is external providers.
-    pub override_queries:
-        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
+    pub override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>,
 
     /// This is a callback from the driver that is called to create a codegen backend.
     pub make_codegen_backend:
@@ -324,7 +325,7 @@
 
             rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
                 let r = {
-                    let _sess_abort_error = OnDrop(|| {
+                    let _sess_abort_error = defer(|| {
                         compiler.sess.finish_diagnostics(registry);
                     });
 
@@ -347,7 +348,7 @@
     // state if it was responsible for triggering the panic.
     let i = ty::tls::with_context_opt(|icx| {
         if let Some(icx) = icx {
-            print_query_stack(QueryCtxt { tcx: icx.tcx }, icx.query, handler, num_frames)
+            print_query_stack(QueryCtxt::new(icx.tcx), icx.query, handler, num_frames)
         } else {
             0
         }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 48401eab..42d8d22 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -17,7 +17,7 @@
 use rustc_metadata::creader::CStore;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
 use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
@@ -89,6 +89,7 @@
         crate_name,
         sess.crate_types().contains(&CrateType::Executable),
         sess.opts.cg.metadata.clone(),
+        sess.cfg_version,
     );
     sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
     rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
@@ -486,6 +487,11 @@
             files.push(normalize_path(profile_sample.as_path().to_path_buf()));
         }
 
+        // Debugger visualizer files
+        for debugger_visualizer in tcx.debugger_visualizers(LOCAL_CRATE) {
+            files.push(normalize_path(debugger_visualizer.path.clone().unwrap()));
+        }
+
         if sess.binary_dep_depinfo() {
             if let Some(ref backend) = sess.opts.unstable_opts.codegen_backend {
                 if backend.contains('.') {
@@ -691,6 +697,8 @@
         callback(sess, &mut local_providers, &mut extern_providers);
     }
 
+    let incremental = dep_graph.is_fully_enabled();
+
     sess.time("setup_global_ctxt", || {
         gcx_cell.get_or_init(move || {
             TyCtxt::create_global_ctxt(
@@ -700,9 +708,13 @@
                 hir_arena,
                 untracked,
                 dep_graph,
-                query_result_on_disk_cache,
                 rustc_query_impl::query_callbacks(arena),
-                rustc_query_impl::query_system_fns(local_providers, extern_providers),
+                rustc_query_impl::query_system(
+                    local_providers,
+                    extern_providers,
+                    query_result_on_disk_cache,
+                    incremental,
+                ),
             )
         })
     })
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 1c58caa..2c8014d 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -1,6 +1,6 @@
 use rustc_ast::attr;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 6483d51..c441a8f 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -369,7 +369,7 @@
 
         if sess.opts.unstable_opts.no_link {
             let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
-            CodegenResults::serialize_rlink(&rlink_file, &codegen_results)
+            CodegenResults::serialize_rlink(sess, &rlink_file, &codegen_results)
                 .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
             return Ok(());
         }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 1bae771..28e719a 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -52,7 +52,8 @@
         output_file: None,
         temps_dir,
     };
-    let sess = build_session(sessopts, io, None, registry, vec![], Default::default(), None, None);
+    let sess =
+        build_session(sessopts, io, None, registry, vec![], Default::default(), None, None, "");
     (sess, cfg)
 }
 
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 8d37b10..cb19750 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -88,7 +88,7 @@
     ) {
         Ok(bundle) => bundle,
         Err(e) => {
-            early_error(sopts.error_format, &format!("failed to load fluent bundle: {e}"));
+            early_error(sopts.error_format, format!("failed to load fluent bundle: {e}"));
         }
     };
 
@@ -104,6 +104,7 @@
         lint_caps,
         file_loader,
         target_override,
+        rustc_version_str().unwrap_or("unknown"),
     );
 
     codegen_backend.init(&sess);
@@ -220,13 +221,13 @@
 fn load_backend_from_dylib(path: &Path) -> MakeBackendFn {
     let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| {
         let err = format!("couldn't load codegen backend {path:?}: {err}");
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
 
     let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") }
         .unwrap_or_else(|e| {
             let err = format!("couldn't load codegen backend: {e}");
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         });
 
     // Intentionally leak the dynamic library. We can't ever unload it
@@ -320,7 +321,7 @@
             "failed to find a `codegen-backends` folder \
                            in the sysroot candidates:\n* {candidates}"
         );
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
     info!("probing {} for a codegen backend", sysroot.display());
 
@@ -331,7 +332,7 @@
             sysroot.display(),
             e
         );
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
 
     let mut file: Option<PathBuf> = None;
@@ -359,7 +360,7 @@
                 prev.display(),
                 path.display()
             );
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         }
         file = Some(path.clone());
     }
@@ -368,7 +369,7 @@
         Some(ref s) => load_backend_from_dylib(s),
         None => {
             let err = format!("unsupported builtin codegen backend `{backend_name}`");
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         }
     }
 }
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index c07dc19..d511d2b 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -582,34 +582,38 @@
         let mut base = Base::Decimal;
         if first_digit == '0' {
             // Attempt to parse encoding base.
-            let has_digits = match self.first() {
+            match self.first() {
                 'b' => {
                     base = Base::Binary;
                     self.bump();
-                    self.eat_decimal_digits()
+                    if !self.eat_decimal_digits() {
+                        return Int { base, empty_int: true };
+                    }
                 }
                 'o' => {
                     base = Base::Octal;
                     self.bump();
-                    self.eat_decimal_digits()
+                    if !self.eat_decimal_digits() {
+                        return Int { base, empty_int: true };
+                    }
                 }
                 'x' => {
                     base = Base::Hexadecimal;
                     self.bump();
-                    self.eat_hexadecimal_digits()
+                    if !self.eat_hexadecimal_digits() {
+                        return Int { base, empty_int: true };
+                    }
                 }
-                // Not a base prefix.
-                '0'..='9' | '_' | '.' | 'e' | 'E' => {
+                // Not a base prefix; consume additional digits.
+                '0'..='9' | '_' => {
                     self.eat_decimal_digits();
-                    true
                 }
+
+                // Also not a base prefix; nothing more to do here.
+                '.' | 'e' | 'E' => {}
+
                 // Just a 0.
                 _ => return Int { base, empty_int: false },
-            };
-            // Base prefix was provided, but there were no digits
-            // after it, e.g. "0x".
-            if !has_digits {
-                return Int { base, empty_int: true };
             }
         } else {
             // No base prefix, parse number in the usual way.
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index a563940..d34a3af 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -5,6 +5,202 @@
     .use_explicit_into_iter_suggestion =
         or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
 
+lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
+    .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
+
+lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
+    .label = invalid failure ordering
+    .help = consider using `Acquire` or `Relaxed` failure ordering instead
+
+lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering
+    .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+
+lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
+    .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
+
+lint_bad_attribute_argument = bad attribute argument
+
+lint_bad_opt_access = {$msg}
+
+lint_builtin_allow_internal_unsafe =
+    `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
+
+lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition
+    .suggestion = try naming the parameter or explicitly ignoring it
+
+lint_builtin_asm_labels = avoid using named labels in inline assembly
+
+lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
+
+lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature
+    .previous_decl_label = `{$orig}` previously declared here
+    .mismatch_label = this signature doesn't match the previous declaration
+
+lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature
+    .previous_decl_label = `{$orig}` previously declared here
+    .mismatch_label = this signature doesn't match the previous declaration
+lint_builtin_const_no_mangle = const items should never be `#[no_mangle]`
+    .suggestion = try a static value
+
+lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function
+lint_builtin_decl_unsafe_method = declaration of an `unsafe` method
+lint_builtin_deprecated_attr_default_suggestion = remove this attribute
+
+lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link}
+    .msg_suggestion = {$msg}
+    .default_suggestion = remove this attribute
+lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used.
+lint_builtin_deref_nullptr = dereferencing a null pointer
+    .label = this code causes undefined behavior when executed
+
+lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
+    .suggestion = use `..=` for an inclusive range
+
+lint_builtin_explicit_outlives = outlives requirements can be inferred
+    .suggestion = remove {$count ->
+        [one] this bound
+        *[other] these bounds
+    }
+
+lint_builtin_export_name_fn = declaration of a function with `export_name`
+lint_builtin_export_name_method = declaration of a method with `export_name`
+
+lint_builtin_export_name_static = declaration of a static with `export_name`
+lint_builtin_impl_unsafe_method = implementation of an `unsafe` method
+
+lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
+    .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
+    .help = consider using `min_{$name}` instead, which is more stable and complete
+
+lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition
+    .suggestion = you can use a raw identifier to stay compatible
+
+lint_builtin_link_section_fn = declaration of a function with `link_section`
+
+lint_builtin_link_section_static = declaration of a static with `link_section`
+
+lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy`
+
+lint_builtin_missing_debug_impl =
+    type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation
+
+lint_builtin_missing_doc = missing documentation for {$article} {$desc}
+
+lint_builtin_mutable_transmutes =
+    transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
+
+lint_builtin_no_mangle_fn = declaration of a `no_mangle` function
+lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled
+    .suggestion = remove this attribute
+
+lint_builtin_no_mangle_method = declaration of a `no_mangle` method
+lint_builtin_no_mangle_static = declaration of a `no_mangle` static
+lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant
+    .suggestion = use shorthand field pattern
+
+lint_builtin_overridden_symbol_name =
+    the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
+
+lint_builtin_overridden_symbol_section =
+    the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
+
+lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
+    .note = lib.rs is the root of this crate's library target
+    .help = to refer to it from other targets, use the library's name as the path
+
+lint_builtin_special_module_name_used_main = found module declaration for main.rs
+    .note = a binary crate cannot be used as library
+
+lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
+
+lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
+
+lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
+    .suggestion = the bound will not be checked when the type alias is used, and should be removed
+
+lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
+    .suggestion = the clause will not be checked when the type alias is used, and should be removed
+
+lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
+    .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
+
+lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
+    .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+lint_builtin_unnameable_test_items = cannot test inner items
+
+lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
+lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+
+lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
+
+lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
+lint_builtin_unreachable_pub = unreachable `pub` {$what}
+    .suggestion = consider restricting its visibility
+    .help = or consider exporting it for use by other crates
+
+lint_builtin_unsafe_block = usage of an `unsafe` block
+
+lint_builtin_unsafe_impl = implementation of an `unsafe` trait
+
+lint_builtin_unsafe_trait = declaration of an `unsafe` trait
+
+lint_builtin_unstable_features = unstable feature
+
+lint_builtin_unused_doc_comment = unused doc comment
+    .label = rustdoc does not generate documentation for {$kind}
+    .plain_help = use `//` for a plain comment
+    .block_help = use `/* */` for a plain comment
+
+lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
+    .suggestion = use `loop`
+
+lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
+
+lint_check_name_unknown = unknown lint: `{$lint_name}`
+    .help = did you mean: `{$suggestion}`
+
+lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
+
+lint_check_name_warning = {$msg}
+
+lint_command_line_source = `forbid` lint level was set on command line
+
+lint_confusable_identifier_pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
+    .label = this is where the previous identifier occurred
+
+lint_cstring_ptr = getting the inner pointer of a temporary `CString`
+    .as_ptr_label = this pointer will be invalid
+    .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
+    .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
+    .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
+
+lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
+    .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
+
+lint_default_source = `forbid` lint level is the default for {$id}
+
+lint_deprecated_lint_name =
+    lint name `{$name}` is deprecated and may not have an effect in the future.
+    .suggestion = change it to
+
+lint_diag_out_of_impl =
+    diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+
+lint_drop_glue =
+    types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
+
+lint_drop_trait_constraints =
+    bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
+
+lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+
+lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+
 lint_enum_intrinsics_mem_discriminant =
     the return value of `mem::discriminant` is unspecified when called with a non-enum type
     .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum.
@@ -24,49 +220,12 @@
     .use_while_let = to check pattern in a loop use `while let`
     .use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents
 
-lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
-    .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
-    .function_label = this function returns `()`, which is likely not what you wanted
-    .argument_label = called `Iterator::map` with callable that returns `()`
-    .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
-    .suggestion = you might have meant to use `Iterator::for_each`
-
-lint_non_binding_let_on_sync_lock =
-    non-binding let on a synchronization lock
-
-lint_non_binding_let_on_drop_type =
-    non-binding let on a type that implements `Drop`
-
-lint_non_binding_let_suggestion =
-    consider binding to an unused variable to avoid immediately dropping the value
-
-lint_non_binding_let_multi_suggestion =
-    consider immediately dropping the value
-
-lint_deprecated_lint_name =
-    lint name `{$name}` is deprecated and may not have an effect in the future.
-    .suggestion = change it to
-
-lint_renamed_or_removed_lint = {$msg}
-    .suggestion = use the new name
-
-lint_suspicious_double_ref_op =
-    using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
-        *[should_not_happen] [{$op}]
-        [deref] dereferencing
-        [borrow] borrowing
-        [clone] cloning
-    } the inner type
-
-lint_unknown_lint =
-    unknown lint: `{$name}`
-    .suggestion = did you mean
-
-lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
-
-lint_unknown_gated_lint =
-    unknown lint: `{$name}`
-    .note = the `{$name}` lint is unstable
+lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
 
 lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label}
     .label = this {$label} contains {$count ->
@@ -81,56 +240,111 @@
     .suggestion_escape = if you want to keep them but make them visible in your source code, you can escape them
     .no_suggestion_note_escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped}
 
-lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
-    .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
-
-lint_query_instability = using `{$query}` can result in unstable query results
-    .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
-
-lint_tykind_kind = usage of `ty::TyKind::<kind>`
-    .suggestion = try using `ty::<kind>` directly
-
-lint_tykind = usage of `ty::TyKind`
-    .help = try using `Ty` instead
-
-lint_ty_qualified = usage of qualified `ty::{$ty}`
-    .suggestion = try importing it and using it unqualified
-
-lint_lintpass_by_hand = implementing `LintPass` by hand
-    .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
-
-lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
-    .help = only existing keywords are allowed in core/std
-
-lint_diag_out_of_impl =
-    diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
-
-lint_untranslatable_diag = diagnostics should be created using translatable messages
-
-lint_trivial_untranslatable_diag = diagnostic with static strings only
-
-lint_bad_opt_access = {$msg}
-
-lint_cstring_ptr = getting the inner pointer of a temporary `CString`
-    .as_ptr_label = this pointer will be invalid
-    .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
-    .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
-    .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
-
-lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
-
 lint_identifier_non_ascii_char = identifier contains non-ASCII characters
 
 lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
 
-lint_confusable_identifier_pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}`
-    .label = this is where the previous identifier occurred
+lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
+
+lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
+    .label = not FFI-safe
+    .note = the type is defined here
+
+lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
+
+lint_improper_ctypes_array_help = consider passing a pointer to the array
+
+lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
+lint_improper_ctypes_box = box cannot be represented as a single pointer
+
+lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
+
+lint_improper_ctypes_char_reason = the `char` type has no C equivalent
+lint_improper_ctypes_dyn = trait objects have no C equivalent
+
+lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
+
+lint_improper_ctypes_enum_repr_help =
+    consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+
+lint_improper_ctypes_enum_repr_reason = enum has no representation hint
+lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
+
+lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
+lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
+lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
+
+lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
+
+lint_improper_ctypes_opaque = opaque types have no C equivalent
+
+lint_improper_ctypes_slice_help = consider using a raw pointer instead
+
+lint_improper_ctypes_slice_reason = slices have no C equivalent
+lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
+
+lint_improper_ctypes_str_reason = string slices have no C equivalent
+lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
+
+lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
+lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+
+lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
+lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
+lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
+
+lint_improper_ctypes_tuple_help = consider using a struct instead
+
+lint_improper_ctypes_tuple_reason = tuples have unspecified layout
+lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
+
+lint_improper_ctypes_union_fieldless_reason = this union has no fields
+lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+
+lint_improper_ctypes_union_layout_reason = this union has unspecified layout
+lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
+
+lint_lintpass_by_hand = implementing `LintPass` by hand
+    .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
+
+lint_malformed_attribute = malformed lint attribute input
+
+lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
+    .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+    .function_label = this function returns `()`, which is likely not what you wanted
+    .argument_label = called `Iterator::map` with callable that returns `()`
+    .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+    .suggestion = you might have meant to use `Iterator::for_each`
 
 lint_mixed_script_confusables =
     the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
     .includes_note = the usage includes {$includes}
     .note = please recheck to make sure their usages are indeed what you want
 
+lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
+
+lint_node_source = `forbid` level set here
+    .note = {$reason}
+
+lint_non_binding_let_multi_suggestion =
+    consider immediately dropping the value
+
+lint_non_binding_let_on_drop_type =
+    non-binding let on a type that implements `Drop`
+
+lint_non_binding_let_on_sync_lock =
+    non-binding let on a synchronization lock
+
+lint_non_binding_let_suggestion =
+    consider binding to an unused variable to avoid immediately dropping the value
+
+lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name
+    .suggestion = convert the identifier to upper camel case
+    .label = should have an UpperCamelCase name
+
+lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
+    .help = only existing keywords are allowed in core/std
+
 lint_non_fmt_panic = panic message is not a string literal
     .note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021
     .more_info_note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
@@ -144,6 +358,14 @@
         *[false] use
     } std::panic::panic_any instead
 
+lint_non_fmt_panic_braces =
+    panic message contains {$count ->
+        [one] a brace
+        *[other] braces
+    }
+    .note = this message is not used as a format string, but will be in Rust 2021
+    .suggestion = add a "{"{"}{"}"}" format string to use the message literally
+
 lint_non_fmt_panic_unused =
     panic message contains {$count ->
         [one] an unused
@@ -159,18 +381,6 @@
     }
     .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
 
-lint_non_fmt_panic_braces =
-    panic message contains {$count ->
-        [one] a brace
-        *[other] braces
-    }
-    .note = this message is not used as a format string, but will be in Rust 2021
-    .suggestion = add a "{"{"}{"}"}" format string to use the message literally
-
-lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name
-    .suggestion = convert the identifier to upper camel case
-    .label = should have an UpperCamelCase name
-
 lint_non_snake_case = {$sort} `{$name}` should have a snake case name
     .rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier
     .cannot_convert_note = `{$sc}` cannot be used as a raw identifier
@@ -187,29 +397,13 @@
     .label = unnecessary method call
     .note = the type `{$receiver_ty}` which `{$method}` is being called on is the same as the type returned from `{$method}`, so the method call does not do anything and can be removed
 
-lint_pass_by_value = passing `{$ty}` by reference
-    .suggestion = try passing by value
+lint_only_cast_u8_to_char = only `u8` can be cast into `char`
+    .suggestion = use a `char` literal instead
 
-lint_redundant_semicolons =
-    unnecessary trailing {$multiple ->
-        [true] semicolons
-        *[false] semicolon
-    }
-    .suggestion = remove {$multiple ->
-        [true] these semicolons
-        *[false] this semicolon
-    }
+lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
+    .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
 
-lint_drop_trait_constraints =
-    bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped
-
-lint_drop_glue =
-    types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
-
-lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
-
-lint_range_use_inclusive_range = use an inclusive range instead
-
+lint_opaque_hidden_inferred_bound_sugg = add this bound
 
 lint_overflowing_bin_hex = literal out of range for `{$ty}`
     .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
@@ -222,96 +416,92 @@
     .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
     .help = consider using the type `{$suggestion_ty}` instead
 
-lint_only_cast_u8_to_char = only `u8` can be cast into `char`
-    .suggestion = use a `char` literal instead
+lint_overflowing_literal = literal out of range for `{$ty}`
+    .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
 
 lint_overflowing_uint = literal out of range for `{$ty}`
     .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
 
-lint_overflowing_literal = literal out of range for `{$ty}`
-    .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
+lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
+    .label = overruled by previous forbid
 
-lint_unused_comparisons = comparison is useless due to type limits
+lint_pass_by_value = passing `{$ty}` by reference
+    .suggestion = try passing by value
 
-lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
-    .label = not FFI-safe
-    .note = the type is defined here
+lint_path_statement_drop = path statement drops value
+    .suggestion = use `drop` to clarify the intent
 
-lint_improper_ctypes_opaque = opaque types have no C equivalent
+lint_path_statement_no_effect = path statement with no effect
 
-lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
-lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
+lint_query_instability = using `{$query}` can result in unstable query results
+    .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
 
-lint_improper_ctypes_tuple_reason = tuples have unspecified layout
-lint_improper_ctypes_tuple_help = consider using a struct instead
+lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
 
-lint_improper_ctypes_str_reason = string slices have no C equivalent
-lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
+lint_range_use_inclusive_range = use an inclusive range instead
 
-lint_improper_ctypes_dyn = trait objects have no C equivalent
 
-lint_improper_ctypes_slice_reason = slices have no C equivalent
-lint_improper_ctypes_slice_help = consider using a raw pointer instead
+lint_reason_must_be_string_literal = reason must be a string literal
 
-lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stable ABI
+lint_reason_must_come_last = reason in lint attribute must come last
 
-lint_improper_ctypes_char_reason = the `char` type has no C equivalent
-lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
+lint_redundant_semicolons =
+    unnecessary trailing {$multiple ->
+        [true] semicolons
+        *[false] semicolon
+    }
+    .suggestion = remove {$multiple ->
+        [true] these semicolons
+        *[false] this semicolon
+    }
 
-lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
-lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
+lint_renamed_or_removed_lint = {$msg}
+    .suggestion = use the new name
 
-lint_improper_ctypes_enum_repr_reason = enum has no representation hint
-lint_improper_ctypes_enum_repr_help =
-    consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+lint_requested_level = requested on the command line with `{$level} {$lint_name}`
 
-lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
-lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
+lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
+    .label = target type is set here
 
-lint_improper_ctypes_union_fieldless_reason = this union has no fields
-lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
+lint_suspicious_double_ref_op =
+    using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
+        *[should_not_happen] [{$op}]
+        [deref] dereferencing
+        [borrow] borrowing
+        [clone] cloning
+    } the inner type
 
-lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
-lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
+lint_trivial_untranslatable_diag = diagnostic with static strings only
 
-lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
-lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+lint_ty_qualified = usage of qualified `ty::{$ty}`
+    .suggestion = try importing it and using it unqualified
 
-lint_improper_ctypes_union_layout_reason = this union has unspecified layout
-lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+lint_tykind = usage of `ty::TyKind`
+    .help = try using `Ty` instead
 
-lint_improper_ctypes_box = box cannot be represented as a single pointer
+lint_tykind_kind = usage of `ty::TyKind::<kind>`
+    .suggestion = try using `ty::<kind>` directly
 
-lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
+lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
+     .label = this function will not propagate the caller location
 
-lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
+lint_unknown_gated_lint =
+    unknown lint: `{$name}`
+    .note = the `{$name}` lint is unstable
 
-lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
-lint_improper_ctypes_array_help = consider passing a pointer to the array
+lint_unknown_lint =
+    unknown lint: `{$name}`
+    .suggestion = did you mean
 
-lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
+lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
+    .help = add `#![register_tool({$tool_name})]` to the crate root
 
-lint_variant_size_differences =
-    enum variant is more than three times larger ({$largest} bytes) than the next largest
+lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
 
-lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering
-    .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+lint_untranslatable_diag = diagnostics should be created using translatable messages
 
-lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
-    .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
-
-lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
-    .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
-
-lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write
-    .label = invalid failure ordering
-    .help = consider using `Acquire` or `Relaxed` failure ordering instead
-
-lint_unused_op = unused {$op} that must be used
-    .label = the {$op} produces a value
-    .suggestion = use `let _ = ...` to ignore the resulting value
-
-lint_unused_result = unused result of type `{$ty}`
+lint_unused_allocation = unnecessary allocation, use `&` instead
+lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
 
 lint_unused_closure =
     unused {$pre}{$count ->
@@ -320,6 +510,14 @@
     }{$post} that must be used
     .note = closures are lazy and do nothing unless called
 
+lint_unused_comparisons = comparison is useless due to type limits
+
+lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
+    .suggestion = use `let _ = ...` to ignore the resulting value
+
+lint_unused_delim = unnecessary {$delim} around {$item}
+    .suggestion = remove these {$delim}
+
 lint_unused_generator =
     unused {$pre}{$count ->
         [one] generator
@@ -327,212 +525,13 @@
     }{$post} that must be used
     .note = generators are lazy and do nothing unless resumed
 
-lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
-    .suggestion = use `let _ = ...` to ignore the resulting value
-
-lint_path_statement_drop = path statement drops value
-    .suggestion = use `drop` to clarify the intent
-
-lint_path_statement_no_effect = path statement with no effect
-
-lint_unused_delim = unnecessary {$delim} around {$item}
-    .suggestion = remove these {$delim}
-
 lint_unused_import_braces = braces around {$node} is unnecessary
 
-lint_unused_allocation = unnecessary allocation, use `&` instead
-lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
+lint_unused_op = unused {$op} that must be used
+    .label = the {$op} produces a value
+    .suggestion = use `let _ = ...` to ignore the resulting value
 
-lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
-    .suggestion = use `loop`
+lint_unused_result = unused result of type `{$ty}`
 
-lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
-
-lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant
-    .suggestion = use shorthand field pattern
-
-lint_builtin_overridden_symbol_name =
-    the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
-
-lint_builtin_overridden_symbol_section =
-    the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
-
-lint_builtin_allow_internal_unsafe =
-    `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
-
-lint_builtin_unsafe_block = usage of an `unsafe` block
-
-lint_builtin_unsafe_trait = declaration of an `unsafe` trait
-
-lint_builtin_unsafe_impl = implementation of an `unsafe` trait
-
-lint_builtin_no_mangle_fn = declaration of a `no_mangle` function
-lint_builtin_export_name_fn = declaration of a function with `export_name`
-lint_builtin_link_section_fn = declaration of a function with `link_section`
-
-lint_builtin_no_mangle_static = declaration of a `no_mangle` static
-lint_builtin_export_name_static = declaration of a static with `export_name`
-lint_builtin_link_section_static = declaration of a static with `link_section`
-
-lint_builtin_no_mangle_method = declaration of a `no_mangle` method
-lint_builtin_export_name_method = declaration of a method with `export_name`
-
-lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function
-lint_builtin_decl_unsafe_method = declaration of an `unsafe` method
-lint_builtin_impl_unsafe_method = implementation of an `unsafe` method
-
-lint_builtin_missing_doc = missing documentation for {$article} {$desc}
-
-lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy`
-
-lint_builtin_missing_debug_impl =
-    type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation
-
-lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition
-    .suggestion = try naming the parameter or explicitly ignoring it
-
-lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link}
-    .msg_suggestion = {$msg}
-    .default_suggestion = remove this attribute
-lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used.
-lint_builtin_deprecated_attr_default_suggestion = remove this attribute
-
-lint_builtin_unused_doc_comment = unused doc comment
-    .label = rustdoc does not generate documentation for {$kind}
-    .plain_help = use `//` for a plain comment
-    .block_help = use `/* */` for a plain comment
-
-lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled
-    .suggestion = remove this attribute
-
-lint_builtin_const_no_mangle = const items should never be `#[no_mangle]`
-    .suggestion = try a static value
-
-lint_builtin_mutable_transmutes =
-    transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
-
-lint_builtin_unstable_features = unstable feature
-
-lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
-     .label = this function will not propagate the caller location
-
-lint_builtin_unreachable_pub = unreachable `pub` {$what}
-    .suggestion = consider restricting its visibility
-    .help = or consider exporting it for use by other crates
-
-lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
-    .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
-
-lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
-    .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
-
-lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
-
-lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
-    .suggestion = the clause will not be checked when the type alias is used, and should be removed
-
-lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
-    .suggestion = the bound will not be checked when the type alias is used, and should be removed
-
-lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
-
-lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
-    .suggestion = use `..=` for an inclusive range
-
-lint_builtin_unnameable_test_items = cannot test inner items
-
-lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition
-    .suggestion = you can use a raw identifier to stay compatible
-
-lint_builtin_explicit_outlives = outlives requirements can be inferred
-    .suggestion = remove {$count ->
-        [one] this bound
-        *[other] these bounds
-    }
-
-lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes
-    .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
-    .help = consider using `min_{$name}` instead, which is more stable and complete
-
-lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
-lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
-
-lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
-lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
-
-lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature
-    .previous_decl_label = `{$orig}` previously declared here
-    .mismatch_label = this signature doesn't match the previous declaration
-lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature
-    .previous_decl_label = `{$orig}` previously declared here
-    .mismatch_label = this signature doesn't match the previous declaration
-
-lint_builtin_deref_nullptr = dereferencing a null pointer
-    .label = this code causes undefined behavior when executed
-
-lint_builtin_asm_labels = avoid using named labels in inline assembly
-
-lint_builtin_special_module_name_used_lib = found module declaration for lib.rs
-    .note = lib.rs is the root of this crate's library target
-    .help = to refer to it from other targets, use the library's name as the path
-
-lint_builtin_special_module_name_used_main = found module declaration for main.rs
-    .note = a binary crate cannot be used as library
-
-lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
-    .label = target type is set here
-
-lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
-    .label = overruled by previous forbid
-
-lint_default_source = `forbid` lint level is the default for {$id}
-
-lint_node_source = `forbid` level set here
-    .note = {$reason}
-
-lint_command_line_source = `forbid` lint level was set on command line
-
-lint_malformed_attribute = malformed lint attribute input
-
-lint_bad_attribute_argument = bad attribute argument
-
-lint_reason_must_be_string_literal = reason must be a string literal
-
-lint_reason_must_come_last = reason in lint attribute must come last
-
-lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
-    .help = add `#![register_tool({$tool_name})]` to the crate root
-
-lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
-
-lint_requested_level = requested on the command line with `{$level} {$lint_name}`
-
-lint_check_name_unknown = unknown lint: `{$lint_name}`
-    .help = did you mean: `{$suggestion}`
-
-lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
-
-lint_check_name_warning = {$msg}
-
-lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
-
-lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
-    .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
-
-lint_opaque_hidden_inferred_bound_sugg = add this bound
-
-lint_drop_ref = calls to `std::mem::drop` with a reference instead of an owned value does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
-
-lint_drop_copy = calls to `std::mem::drop` with a value that implements `Copy` does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
-
-lint_forget_ref = calls to `std::mem::forget` with a reference instead of an owned value does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
-
-lint_forget_copy = calls to `std::mem::forget` with a value that implements `Copy` does nothing
-    .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
+lint_variant_size_differences =
+    enum variant is more than three times larger ({$largest} bytes) than the next largest
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index b1c45ea..358d412 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -611,7 +611,7 @@
 
 declare_lint! {
     /// The `missing_copy_implementations` lint detects potentially-forgotten
-    /// implementations of [`Copy`].
+    /// implementations of [`Copy`] for public types.
     ///
     /// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
     ///
@@ -647,7 +647,9 @@
 
 impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
+        if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
+            && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
+        {
             return;
         }
         let (def, ty) = match item.kind {
@@ -727,7 +729,7 @@
 
 declare_lint! {
     /// The `missing_debug_implementations` lint detects missing
-    /// implementations of [`fmt::Debug`].
+    /// implementations of [`fmt::Debug`] for public types.
     ///
     /// [`fmt::Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
     ///
@@ -766,7 +768,9 @@
 
 impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
+        if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
+            && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
+        {
             return;
         }
 
@@ -957,7 +961,7 @@
                 Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi())));
         }
 
-        if attrs.peek().map_or(false, |next_attr| next_attr.is_doc_comment()) {
+        if attrs.peek().is_some_and(|next_attr| next_attr.is_doc_comment()) {
             continue;
         }
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 53d7cf7..1d0c43e 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -49,9 +49,9 @@
 use std::iter;
 use std::slice;
 
-type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync;
+type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync;
 type LateLintPassFactory =
-    dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::Send + sync::Sync;
+    dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync;
 
 /// Information about the registered lints.
 ///
@@ -169,7 +169,7 @@
 
     pub fn register_early_pass(
         &mut self,
-        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
+        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
     ) {
         self.early_passes.push(Box::new(pass));
     }
@@ -182,7 +182,7 @@
     /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
     pub fn register_pre_expansion_pass(
         &mut self,
-        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
+        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
     ) {
         self.pre_expansion_passes.push(Box::new(pass));
     }
@@ -191,8 +191,8 @@
         &mut self,
         pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
         + 'static
-        + sync::Send
-        + sync::Sync,
+        + sync::DynSend
+        + sync::DynSync,
     ) {
         self.late_passes.push(Box::new(pass));
     }
@@ -201,8 +201,8 @@
         &mut self,
         pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
         + 'static
-        + sync::Send
-        + sync::Sync,
+        + sync::DynSend
+        + sync::DynSync,
     ) {
         self.late_module_passes.push(Box::new(pass));
     }
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
index 259abc2..ed2b384 100644
--- a/compiler/rustc_lint/src/drop_forget_useless.rs
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -7,7 +7,7 @@
 };
 
 declare_lint! {
-    /// The `drop_ref` lint checks for calls to `std::mem::drop` with a reference
+    /// The `dropping_references` lint checks for calls to `std::mem::drop` with a reference
     /// instead of an owned value.
     ///
     /// ### Example
@@ -29,13 +29,13 @@
     /// reference itself, which is a no-op. It will not call the `drop` method (from
     /// the `Drop` trait implementation) on the underlying referenced value, which
     /// is likely what was intended.
-    pub DROP_REF,
+    pub DROPPING_REFERENCES,
     Warn,
     "calls to `std::mem::drop` with a reference instead of an owned value"
 }
 
 declare_lint! {
-    /// The `forget_ref` lint checks for calls to `std::mem::forget` with a reference
+    /// The `forgetting_references` lint checks for calls to `std::mem::forget` with a reference
     /// instead of an owned value.
     ///
     /// ### Example
@@ -52,13 +52,13 @@
     /// Calling `forget` on a reference will only forget the
     /// reference itself, which is a no-op. It will not forget the underlying
     /// referenced value, which is likely what was intended.
-    pub FORGET_REF,
+    pub FORGETTING_REFERENCES,
     Warn,
     "calls to `std::mem::forget` with a reference instead of an owned value"
 }
 
 declare_lint! {
-    /// The `drop_copy` lint checks for calls to `std::mem::drop` with a value
+    /// The `dropping_copy_types` lint checks for calls to `std::mem::drop` with a value
     /// that derives the Copy trait.
     ///
     /// ### Example
@@ -76,13 +76,13 @@
     /// Calling `std::mem::drop` [does nothing for types that
     /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
     /// value will be copied and moved into the function on invocation.
-    pub DROP_COPY,
+    pub DROPPING_COPY_TYPES,
     Warn,
     "calls to `std::mem::drop` with a value that implements Copy"
 }
 
 declare_lint! {
-    /// The `forget_copy` lint checks for calls to `std::mem::forget` with a value
+    /// The `forgetting_copy_types` lint checks for calls to `std::mem::forget` with a value
     /// that derives the Copy trait.
     ///
     /// ### Example
@@ -104,12 +104,12 @@
     /// An alternative, but also valid, explanation is that Copy types do not
     /// implement the Drop trait, which means they have no destructors. Without a
     /// destructor, there is nothing for `std::mem::forget` to ignore.
-    pub FORGET_COPY,
+    pub FORGETTING_COPY_TYPES,
     Warn,
     "calls to `std::mem::forget` with a value that implements Copy"
 }
 
-declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]);
+declare_lint_pass!(DropForgetUseless => [DROPPING_REFERENCES, FORGETTING_REFERENCES, DROPPING_COPY_TYPES, FORGETTING_COPY_TYPES]);
 
 impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -123,16 +123,16 @@
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             match fn_name {
                 sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
-                    cx.emit_spanned_lint(DROP_REF, expr.span, DropRefDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(DROPPING_REFERENCES, expr.span, DropRefDiag { arg_ty, label: arg.span });
                 },
                 sym::mem_forget if arg_ty.is_ref() => {
-                    cx.emit_spanned_lint(FORGET_REF, expr.span, ForgetRefDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(FORGETTING_REFERENCES, expr.span, ForgetRefDiag { arg_ty, label: arg.span });
                 },
                 sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
-                    cx.emit_spanned_lint(DROP_COPY, expr.span, DropCopyDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(DROPPING_COPY_TYPES, expr.span, DropCopyDiag { arg_ty, label: arg.span });
                 }
                 sym::mem_forget if is_copy => {
-                    cx.emit_spanned_lint(FORGET_COPY, expr.span, ForgetCopyDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(FORGETTING_COPY_TYPES, expr.span, ForgetCopyDiag { arg_ty, label: arg.span });
                 }
                 _ => return,
             };
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index e9eb14e..b1266b5 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -1,5 +1,5 @@
 use crate::lints::{Expectation, ExpectationNote};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS;
 use rustc_session::lint::LintExpectationId;
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 0082aaa..6f773e0 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -383,9 +383,8 @@
         debug!(?span, ?def_id, ?substs);
         let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
             .ok()
-            .and_then(|inst| inst)
-            .map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics))
-            .unwrap_or(false);
+            .flatten()
+            .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics));
         if !has_attr {
             return;
         }
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index b42878a..8a4a451 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -16,7 +16,7 @@
 
 use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
 use rustc_ast as ast;
-use rustc_data_structures::sync::join;
+use rustc_data_structures::sync::{join, DynSend};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit as hir_visit;
@@ -240,8 +240,10 @@
     }
 
     fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
-        lint_callback!(self, check_arm, a);
-        hir_visit::walk_arm(self, a);
+        self.with_lint_attrs(a.hir_id, |cx| {
+            lint_callback!(cx, check_arm, a);
+            hir_visit::walk_arm(cx, a);
+        })
     }
 
     fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
@@ -429,7 +431,7 @@
 /// Performs lint checking on a crate.
 pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     tcx: TyCtxt<'tcx>,
-    builtin_lints: impl FnOnce() -> T + Send,
+    builtin_lints: impl FnOnce() -> T + Send + DynSend,
 ) {
     join(
         || {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index a43c09a..b92ed11f 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -20,7 +20,7 @@
     reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource,
     ShallowLintLevelMap,
 };
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{RegisteredTools, TyCtxt};
 use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES};
 use rustc_session::lint::{
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 5c70166..dfddfe0 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -86,7 +86,7 @@
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::{
     BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 8e48806..de1c2be 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -662,9 +662,9 @@
     pub end_span: Span,
 }
 
-// drop_ref.rs
+// drop_forget_useless.rs
 #[derive(LintDiagnostic)]
-#[diag(lint_drop_ref)]
+#[diag(lint_dropping_references)]
 #[note]
 pub struct DropRefDiag<'a> {
     pub arg_ty: Ty<'a>,
@@ -673,7 +673,7 @@
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_drop_copy)]
+#[diag(lint_dropping_copy_types)]
 #[note]
 pub struct DropCopyDiag<'a> {
     pub arg_ty: Ty<'a>,
@@ -682,7 +682,7 @@
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_forget_ref)]
+#[diag(lint_forgetting_references)]
 #[note]
 pub struct ForgetRefDiag<'a> {
     pub arg_ty: Ty<'a>,
@@ -691,7 +691,7 @@
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_forget_copy)]
+#[diag(lint_forgetting_copy_types)]
 #[note]
 pub struct ForgetCopyDiag<'a> {
     pub arg_ty: Ty<'a>,
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 5bb1abf..b218cc5 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -128,7 +128,7 @@
             // No clue where this argument is coming from.
             return lint;
         }
-        if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
+        if arg_macro.is_some_and(|id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
             // A case of `panic!(format!(..))`.
             lint.note(fluent::lint_supports_fmt_note);
             if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 125b4dc..4bf4fda 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -677,7 +677,7 @@
     let param_env = tcx.param_env(variant.def_id);
     variant.fields.iter().find(|field| {
         let field_ty = tcx.type_of(field.did).subst_identity();
-        let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
+        let is_zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_zst());
         !is_zst
     })
 }
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index eb175e9..8f75fa1 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -103,8 +103,10 @@
             && let ty = cx.typeck_results().expr_ty(&await_expr)
             && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
             && cx.tcx.ty_is_opaque_future(ty)
-            // FIXME: This also includes non-async fns that return `impl Future`.
             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
+            && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn)
+            // Check that this `impl Future` actually comes from an `async fn`
+            && cx.tcx.asyncness(async_fn_def_id).is_async()
             && check_must_use_def(
                 cx,
                 async_fn_def_id,
@@ -662,8 +664,8 @@
             _ => return,
         };
         let keep_space = (
-            left_pos.map_or(false, |s| s >= value.span.lo()),
-            right_pos.map_or(false, |s| s <= value.span.hi()),
+            left_pos.is_some_and(|s| s >= value.span.lo()),
+            right_pos.is_some_and(|s| s <= value.span.hi()),
         );
         self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
     }
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 7b774d6..c43a027 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1463,63 +1463,6 @@
   return BitcodeOrError->getBufferStart();
 }
 
-// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
-// the comment in `back/lto.rs` for why this exists.
-extern "C" void
-LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
-                                DICompileUnit **A,
-                                DICompileUnit **B) {
-  Module *M = unwrap(Mod);
-  DICompileUnit **Cur = A;
-  DICompileUnit **Next = B;
-  for (DICompileUnit *CU : M->debug_compile_units()) {
-    *Cur = CU;
-    Cur = Next;
-    Next = nullptr;
-    if (Cur == nullptr)
-      break;
-  }
-}
-
-// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
-// the comment in `back/lto.rs` for why this exists.
-extern "C" void
-LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
-  Module *M = unwrap(Mod);
-
-  // If the original source module didn't have a `DICompileUnit` then try to
-  // merge all the existing compile units. If there aren't actually any though
-  // then there's not much for us to do so return.
-  if (Unit == nullptr) {
-    for (DICompileUnit *CU : M->debug_compile_units()) {
-      Unit = CU;
-      break;
-    }
-    if (Unit == nullptr)
-      return;
-  }
-
-  // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
-  // process it recursively. Note that we used to specifically iterate over
-  // instructions to ensure we feed everything into it, but `processModule`
-  // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
-  DebugInfoFinder Finder;
-  Finder.processModule(*M);
-
-  // After we've found all our debuginfo, rewrite all subprograms to point to
-  // the same `DICompileUnit`.
-  for (auto &F : Finder.subprograms()) {
-    F->replaceUnit(Unit);
-  }
-
-  // Erase any other references to other `DICompileUnit` instances, the verifier
-  // will later ensure that we don't actually have any other stale references to
-  // worry about.
-  auto *MD = M->getNamedMetadata("llvm.dbg.cu");
-  MD->clearOperands();
-  MD->addOperand(Unit);
-}
-
 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
 // storing the result in 'KeyOut'.
 // Currently, this cache key is a SHA-1 hash of anything that could affect
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index a8b25ff..d0d41c6 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -253,7 +253,7 @@
         quote! {
             #[allow(unused_variables, unused_braces, rustc::pass_by_value)]
             #[inline]
-            pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
+            pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool {
                 #expr
             }
         }
@@ -262,7 +262,7 @@
             // we're taking `key` by reference, but some rustc types usually prefer being passed by value
             #[allow(rustc::pass_by_value)]
             #[inline]
-            pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
+            pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::queries::#name::Key<'tcx>) -> bool {
                 false
             }
         }
@@ -273,7 +273,7 @@
 
     let desc = quote! {
         #[allow(unused_variables)]
-        pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::ty::query::query_keys::#name<'tcx>) -> String {
+        pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String {
             let (#tcx, #key) = (tcx, key);
             ::rustc_middle::ty::print::with_no_trimmed_paths!(
                 format!(#desc)
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 79b8b41..6d8601b 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -1,131 +1,58 @@
-metadata_rlib_required =
-    crate `{$crate_name}` required to be available in rlib format, but was not found in this form
+metadata_as_needed_compatibility =
+    linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
 
-metadata_lib_required =
-    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+metadata_bad_panic_strategy =
+    the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
 
-metadata_rustc_lib_required =
-    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
-    .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver`
-    .help = try adding `extern crate rustc_driver;` at the top level of this crate
+metadata_bundle_needs_static =
+    linking modifier `bundle` is only compatible with `static` linking kind
+
+metadata_cannot_find_crate =
+    can't find crate for `{$crate_name}`{$add_info}
+
+metadata_cant_find_crate =
+    can't find crate
+
+metadata_compiler_missing_profiler =
+    the compiler may have been built without the profiler runtime
+
+metadata_conflicting_alloc_error_handler =
+    the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}
+
+metadata_conflicting_global_alloc =
+    the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
+
+metadata_consider_building_std =
+    consider building the standard library from source with `cargo build -Zbuild-std`
+
+metadata_consider_downloading_target =
+    consider downloading the target with `rustup target add {$locator_triple}`
 
 metadata_crate_dep_multiple =
     cannot satisfy dependencies so `{$crate_name}` only shows up once
     .help = having upstream crates all available in one format will likely make this go away
 
-metadata_two_panic_runtimes =
-    cannot link together two panic runtimes: {$prev_name} and {$cur_name}
+metadata_crate_location_unknown_type =
+    extern location for {$crate_name} is of an unknown type: {$path}
 
-metadata_bad_panic_strategy =
-    the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
+metadata_crate_not_panic_runtime =
+    the crate `{$crate_name}` is not a panic runtime
 
-metadata_required_panic_strategy =
-    the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
-
-metadata_incompatible_panic_in_drop_strategy =
-    the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
-
-metadata_multiple_names_in_link =
-    multiple `name` arguments in a single `#[link]` attribute
-
-metadata_multiple_kinds_in_link =
-    multiple `kind` arguments in a single `#[link]` attribute
-
-metadata_link_name_form =
-    link name must be of the form `name = "string"`
-
-metadata_link_kind_form =
-    link kind must be of the form `kind = "string"`
-
-metadata_link_modifiers_form =
-    link modifiers must be of the form `modifiers = "string"`
-
-metadata_link_cfg_form =
-    link cfg must be of the form `cfg(/* predicate */)`
-
-metadata_wasm_import_form =
-    wasm import module must be of the form `wasm_import_module = "string"`
+metadata_dl_error =
+    {$err}
 
 metadata_empty_link_name =
     link name must not be empty
     .label = empty link name
 
-metadata_link_framework_apple =
-    link kind `framework` is only supported on Apple targets
-
-metadata_framework_only_windows =
-    link kind `raw-dylib` is only supported on Windows targets
-
-metadata_unknown_link_kind =
-    unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
-    .label = unknown link kind
-
-metadata_multiple_link_modifiers =
-    multiple `modifiers` arguments in a single `#[link]` attribute
-
-metadata_multiple_cfgs =
-    multiple `cfg` arguments in a single `#[link]` attribute
-
-metadata_link_cfg_single_predicate =
-    link cfg must have a single predicate argument
-
-metadata_multiple_wasm_import =
-    multiple `wasm_import_module` arguments in a single `#[link]` attribute
-
-metadata_unexpected_link_arg =
-    unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
-
-metadata_invalid_link_modifier =
-    invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
-
-metadata_multiple_modifiers =
-    multiple `{$modifier}` modifiers in a single `modifiers` argument
-
-metadata_bundle_needs_static =
-    linking modifier `bundle` is only compatible with `static` linking kind
-
-metadata_whole_archive_needs_static =
-    linking modifier `whole-archive` is only compatible with `static` linking kind
-
-metadata_as_needed_compatibility =
-    linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
-
-metadata_unknown_link_modifier =
-    unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
-
-metadata_incompatible_wasm_link =
-    `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
-
-metadata_link_requires_name =
-    `#[link]` attribute requires a `name = "string"` argument
-    .label = missing `name` argument
-
-metadata_raw_dylib_no_nul =
-    link name must not contain NUL characters if link kind is `raw-dylib`
-
-metadata_link_ordinal_raw_dylib =
-    `#[link_ordinal]` is only supported if link kind is `raw-dylib`
-
-metadata_lib_framework_apple =
-    library kind `framework` is only supported on Apple targets
-
 metadata_empty_renaming_target =
     an empty renaming target was specified for library `{$lib_name}`
 
-metadata_renaming_no_link =
-    renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+metadata_extern_location_not_exist =
+    extern location for {$crate_name} does not exist: {$location}
 
-metadata_multiple_renamings =
-    multiple renamings were specified for library `{$lib_name}`
-
-metadata_no_link_mod_override =
-    overriding linking modifiers from command line is not supported
-
-metadata_unsupported_abi_i686 =
-    ABI not supported by `#[link(kind = "raw-dylib")]` on i686
-
-metadata_unsupported_abi =
-    ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+metadata_extern_location_not_file =
+    extern location for {$crate_name} is not a file: {$location}
 
 metadata_fail_create_file_encoder =
     failed to create file encoder: {$err}
@@ -136,72 +63,189 @@
 metadata_fail_write_file =
     failed to write to the file: {$err}
 
-metadata_crate_not_panic_runtime =
-    the crate `{$crate_name}` is not a panic runtime
+metadata_failed_create_encoded_metadata =
+    failed to create encoded metadata from file: {$err}
 
-metadata_no_panic_strategy =
-    the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
+metadata_failed_create_file =
+    failed to create the file {$filename}: {$err}
 
-metadata_profiler_builtins_needs_core =
-    `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+metadata_failed_create_tempdir =
+    couldn't create a temp dir: {$err}
 
-metadata_not_profiler_runtime =
-    the crate `{$crate_name}` is not a profiler runtime
+metadata_failed_write_error =
+    failed to write {$filename}: {$err}
 
-metadata_no_multiple_global_alloc =
-    cannot define multiple global allocators
-    .label = cannot define a new global allocator
+metadata_found_crate_versions =
+    the following crate versions were found:{$found_crates}
 
-metadata_prev_global_alloc =
-    previous global allocator defined here
+metadata_found_staticlib =
+    found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
+    .help = please recompile that crate using --crate-type lib
+
+metadata_framework_only_windows =
+    link kind `raw-dylib` is only supported on Windows targets
+
+metadata_global_alloc_required =
+    no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+
+metadata_import_name_type_form =
+    import name type must be of the form `import_name_type = "string"`
+
+metadata_import_name_type_raw =
+    import name type can only be used with link kind `raw-dylib`
+
+metadata_import_name_type_x86 =
+    import name type is only supported on x86
+
+metadata_incompatible_panic_in_drop_strategy =
+    the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_incompatible_rustc =
+    found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
+    .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
+
+metadata_incompatible_wasm_link =
+    `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+
+metadata_install_missing_components =
+    maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+
+metadata_invalid_link_modifier =
+    invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_invalid_meta_files =
+    found invalid metadata files for crate `{$crate_name}`{$add_info}
+
+metadata_lib_filename_form =
+    file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}
+
+metadata_lib_framework_apple =
+    library kind `framework` is only supported on Apple targets
+
+metadata_lib_required =
+    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+
+metadata_link_cfg_form =
+    link cfg must be of the form `cfg(/* predicate */)`
+
+metadata_link_cfg_single_predicate =
+    link cfg must have a single predicate argument
+
+metadata_link_framework_apple =
+    link kind `framework` is only supported on Apple targets
+
+metadata_link_kind_form =
+    link kind must be of the form `kind = "string"`
+
+metadata_link_modifiers_form =
+    link modifiers must be of the form `modifiers = "string"`
+
+metadata_link_name_form =
+    link name must be of the form `name = "string"`
+
+metadata_link_ordinal_raw_dylib =
+    `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+
+metadata_link_requires_name =
+    `#[link]` attribute requires a `name = "string"` argument
+    .label = missing `name` argument
+
+metadata_missing_native_library =
+    could not find native static library `{$libname}`, perhaps an -L flag is missing?
+
+metadata_multiple_candidates =
+    multiple candidates for `{$flavor}` dependency `{$crate_name}` found
+
+metadata_multiple_cfgs =
+    multiple `cfg` arguments in a single `#[link]` attribute
+
+metadata_multiple_import_name_type =
+    multiple `import_name_type` arguments in a single `#[link]` attribute
+
+metadata_multiple_kinds_in_link =
+    multiple `kind` arguments in a single `#[link]` attribute
+
+metadata_multiple_link_modifiers =
+    multiple `modifiers` arguments in a single `#[link]` attribute
+
+metadata_multiple_modifiers =
+    multiple `{$modifier}` modifiers in a single `modifiers` argument
+
+metadata_multiple_names_in_link =
+    multiple `name` arguments in a single `#[link]` attribute
+
+metadata_multiple_renamings =
+    multiple renamings were specified for library `{$lib_name}`
+
+metadata_multiple_wasm_import =
+    multiple `wasm_import_module` arguments in a single `#[link]` attribute
+
+metadata_newer_crate_version =
+    found possibly newer version of crate `{$crate_name}`{$add_info}
+    .note = perhaps that crate needs to be recompiled?
+
+metadata_no_crate_with_triple =
+    couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
+
+metadata_no_dylib_plugin =
+    plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+
+metadata_no_link_mod_override =
+    overriding linking modifiers from command line is not supported
 
 metadata_no_multiple_alloc_error_handler =
     cannot define multiple allocation error handlers
     .label = cannot define a new allocation error handler
 
-metadata_prev_alloc_error_handler =
-    previous allocation error handler defined here
+metadata_no_multiple_global_alloc =
+    cannot define multiple global allocators
+    .label = cannot define a new global allocator
 
-metadata_conflicting_global_alloc =
-    the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
-
-metadata_conflicting_alloc_error_handler =
-    the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}
-
-metadata_global_alloc_required =
-    no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+metadata_no_panic_strategy =
+    the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
 
 metadata_no_transitive_needs_dep =
     the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
 
-metadata_failed_write_error =
-    failed to write {$filename}: {$err}
-
-metadata_missing_native_library =
-    could not find native static library `{$libname}`, perhaps an -L flag is missing?
-
-metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename
-
-metadata_failed_create_tempdir =
-    couldn't create a temp dir: {$err}
-
-metadata_failed_create_file =
-    failed to create the file {$filename}: {$err}
-
-metadata_failed_create_encoded_metadata =
-    failed to create encoded metadata from file: {$err}
-
 metadata_non_ascii_name =
     cannot load a crate with a non-ascii name `{$crate_name}`
 
-metadata_extern_location_not_exist =
-    extern location for {$crate_name} does not exist: {$location}
+metadata_not_profiler_runtime =
+    the crate `{$crate_name}` is not a profiler runtime
 
-metadata_extern_location_not_file =
-    extern location for {$crate_name} is not a file: {$location}
+metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename
 
-metadata_multiple_candidates =
-    multiple candidates for `{$flavor}` dependency `{$crate_name}` found
+metadata_prev_alloc_error_handler =
+    previous allocation error handler defined here
+
+metadata_prev_global_alloc =
+    previous global allocator defined here
+
+metadata_profiler_builtins_needs_core =
+    `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+
+metadata_raw_dylib_no_nul =
+    link name must not contain NUL characters if link kind is `raw-dylib`
+
+metadata_renaming_no_link =
+    renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+
+metadata_required_panic_strategy =
+    the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_rlib_required =
+    crate `{$crate_name}` required to be available in rlib format, but was not found in this form
+
+metadata_rustc_lib_required =
+    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+    .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver`
+    .help = try adding `extern crate rustc_driver;` at the top level of this crate
+
+metadata_stable_crate_id_collision =
+    found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
+
+metadata_std_required =
+    `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
 
 metadata_symbol_conflicts_current =
     the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
@@ -209,80 +253,36 @@
 metadata_symbol_conflicts_others =
     found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two.
 
-metadata_stable_crate_id_collision =
-    found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
-
-metadata_dl_error =
-    {$err}
-
-metadata_newer_crate_version =
-    found possibly newer version of crate `{$crate_name}`{$add_info}
-    .note = perhaps that crate needs to be recompiled?
-
-metadata_found_crate_versions =
-    the following crate versions were found:{$found_crates}
-
-metadata_no_crate_with_triple =
-    couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
-
-metadata_found_staticlib =
-    found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
-    .help = please recompile that crate using --crate-type lib
-
-metadata_incompatible_rustc =
-    found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
-    .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
-
-metadata_invalid_meta_files =
-    found invalid metadata files for crate `{$crate_name}`{$add_info}
-
-metadata_cannot_find_crate =
-    can't find crate for `{$crate_name}`{$add_info}
-
-metadata_no_dylib_plugin =
-    plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+metadata_target_no_std_support =
+    the `{$locator_triple}` target may not support the standard library
 
 metadata_target_not_installed =
     the `{$locator_triple}` target may not be installed
 
-metadata_target_no_std_support =
-    the `{$locator_triple}` target may not support the standard library
+metadata_two_panic_runtimes =
+    cannot link together two panic runtimes: {$prev_name} and {$cur_name}
 
-metadata_consider_downloading_target =
-    consider downloading the target with `rustup target add {$locator_triple}`
-
-metadata_std_required =
-    `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
-
-metadata_consider_building_std =
-    consider building the standard library from source with `cargo build -Zbuild-std`
-
-metadata_compiler_missing_profiler =
-    the compiler may have been built without the profiler runtime
-
-metadata_install_missing_components =
-    maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
-
-metadata_cant_find_crate =
-    can't find crate
-
-metadata_crate_location_unknown_type =
-    extern location for {$crate_name} is of an unknown type: {$path}
-
-metadata_lib_filename_form =
-    file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}
-
-metadata_multiple_import_name_type =
-    multiple `import_name_type` arguments in a single `#[link]` attribute
-
-metadata_import_name_type_form =
-    import name type must be of the form `import_name_type = "string"`
-
-metadata_import_name_type_x86 =
-    import name type is only supported on x86
+metadata_unexpected_link_arg =
+    unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
 
 metadata_unknown_import_name_type =
     unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
 
-metadata_import_name_type_raw =
-    import name type can only be used with link kind `raw-dylib`
+metadata_unknown_link_kind =
+    unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
+    .label = unknown link kind
+
+metadata_unknown_link_modifier =
+    unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_unsupported_abi =
+    ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+
+metadata_unsupported_abi_i686 =
+    ABI not supported by `#[link(kind = "raw-dylib")]` on i686
+
+metadata_wasm_import_form =
+    wasm import module must be of the form `wasm_import_module = "string"`
+
+metadata_whole_archive_needs_static =
+    linking modifier `whole-archive` is only compatible with `static` linking kind
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index e6e7d25..aaf72ab 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -4,7 +4,7 @@
 use crate::locator::{CrateError, CrateLocator, CratePaths};
 use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
 
-use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, AllocatorKind};
 use rustc_ast::{self as ast, *};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::svh::Svh;
@@ -148,11 +148,15 @@
         assert_eq!(self.metas.len(), self.stable_crate_ids.len());
         let num = CrateNum::new(self.stable_crate_ids.len());
         if let Some(&existing) = self.stable_crate_ids.get(&root.stable_crate_id()) {
-            let crate_name0 = root.name();
-            if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name()) {
+            // Check for (potential) conflicts with the local crate
+            if existing == LOCAL_CRATE {
+                Err(CrateError::SymbolConflictsCurrent(root.name()))
+            } else if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name())
+            {
+                let crate_name0 = root.name();
                 Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1))
             } else {
-                Err(CrateError::SymbolConflictsCurrent(crate_name0))
+                Err(CrateError::NotFound(root.name()))
             }
         } else {
             self.metas.push(None);
@@ -369,7 +373,7 @@
         let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
 
         let private_dep =
-            self.sess.opts.externs.get(name.as_str()).map_or(false, |e| e.is_private_dep);
+            self.sess.opts.externs.get(name.as_str()).is_some_and(|e| e.is_private_dep);
 
         // Claim this crate number and cache it
         let cnum = self.cstore.intern_stable_crate_id(&crate_root)?;
@@ -943,7 +947,7 @@
                     lint::builtin::UNUSED_CRATE_DEPENDENCIES,
                     span,
                     ast::CRATE_NODE_ID,
-                    &format!(
+                    format!(
                         "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
                         name,
                         self.tcx.crate_name(LOCAL_CRATE),
@@ -1044,7 +1048,7 @@
         }
     }
 
-    let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::alloc));
+    let name = Symbol::intern(&global_fn_name(sym::alloc));
     let mut f = Finder { name, spans: Vec::new() };
     visit::walk_crate(&mut f, krate);
     f.spans
@@ -1066,7 +1070,7 @@
         }
     }
 
-    let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::oom));
+    let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global));
     let mut f = Finder { name, spans: Vec::new() };
     visit::walk_crate(&mut f, krate);
     f.spans
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index c6af8d6..ceb348f 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -220,7 +220,6 @@
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
 use rustc_fs_util::try_canonicalize;
 use rustc_session::config::{self, CrateType};
@@ -246,6 +245,7 @@
     only_needs_metadata: bool,
     sysroot: &'a Path,
     metadata_loader: &'a dyn MetadataLoader,
+    cfg_version: &'static str,
 
     // Immutable per-search configuration.
     crate_name: Symbol,
@@ -323,6 +323,7 @@
             only_needs_metadata,
             sysroot: &sess.sysroot,
             metadata_loader,
+            cfg_version: sess.cfg_version,
             crate_name,
             exact_paths: if hash.is_none() {
                 sess.opts
@@ -566,7 +567,7 @@
         let mut err_data: Option<Vec<PathBuf>> = None;
         for (lib, kind) in m {
             info!("{} reading metadata from: {}", flavor, lib.display());
-            if flavor == CrateFlavor::Rmeta && lib.metadata().map_or(false, |m| m.len() == 0) {
+            if flavor == CrateFlavor::Rmeta && lib.metadata().is_ok_and(|m| m.len() == 0) {
                 // Empty files will cause get_metadata_section to fail. Rmeta
                 // files can be empty, for example with binaries (which can
                 // often appear with `cargo check` when checking a library as
@@ -601,7 +602,7 @@
                     }
                 };
             // If we see multiple hashes, emit an error about duplicate candidates.
-            if slot.as_ref().map_or(false, |s| s.0 != hash) {
+            if slot.as_ref().is_some_and(|s| s.0 != hash) {
                 if let Some(candidates) = err_data {
                     return Err(CrateError::MultipleCandidates(
                         self.crate_name,
@@ -655,7 +656,7 @@
     }
 
     fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
-        let rustc_version = rustc_version();
+        let rustc_version = rustc_version(self.cfg_version);
         let found_version = metadata.get_rustc_version();
         if found_version != rustc_version {
             info!("Rejecting via version: expected {} got {}", rustc_version, found_version);
@@ -782,7 +783,7 @@
     if !filename.exists() {
         return Err(MetadataError::NotPresent(filename));
     }
-    let raw_bytes: MetadataRef = match flavor {
+    let raw_bytes = match flavor {
         CrateFlavor::Rlib => {
             loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
         }
@@ -843,7 +844,7 @@
             slice_owned(mmap, Deref::deref)
         }
     };
-    let blob = MetadataBlob::new(raw_bytes);
+    let blob = MetadataBlob(raw_bytes);
     if blob.is_compatible() {
         Ok(blob)
     } else {
@@ -960,6 +961,7 @@
     DlSym(String),
     LocatorCombined(Box<CombinedLocatorError>),
     NonDylibPlugin(Symbol),
+    NotFound(Symbol),
 }
 
 enum MetadataError<'a> {
@@ -1097,7 +1099,7 @@
                         crate_name,
                         add_info,
                         found_crates,
-                        rustc_version: rustc_version(),
+                        rustc_version: rustc_version(sess.cfg_version),
                     });
                 } else if !locator.crate_rejections.via_invalid.is_empty() {
                     let mut crate_rejections = Vec::new();
@@ -1130,6 +1132,18 @@
             CrateError::NonDylibPlugin(crate_name) => {
                 sess.emit_err(errors::NoDylibPlugin { span, crate_name });
             }
+            CrateError::NotFound(crate_name) => {
+                sess.emit_err(errors::CannotFindCrate {
+                    span,
+                    crate_name,
+                    add_info: String::new(),
+                    missing_core,
+                    current_crate: sess.opts.crate_name.clone().unwrap_or("<unknown>".to_string()),
+                    is_nightly_build: sess.is_nightly_build(),
+                    profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
+                    locator_triple: sess.opts.target_triple.clone(),
+                });
+            }
         }
     }
 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index eab32ad..cc4e60c 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -7,6 +7,7 @@
 use rustc_ast as ast;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell};
 use rustc_data_structures::unhash::UnhashMap;
@@ -18,6 +19,7 @@
 use rustc_hir::diagnostic_items::DiagnosticItems;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::metadata::ModChild;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::codec::TyDecoder;
@@ -50,7 +52,7 @@
 /// A `MetadataBlob` internally is just a reference counted pointer to
 /// the actual data, so cloning it is cheap.
 #[derive(Clone)]
-pub(crate) struct MetadataBlob(Lrc<MetadataRef>);
+pub(crate) struct MetadataBlob(pub(crate) OwnedSlice);
 
 impl std::ops::Deref for MetadataBlob {
     type Target = [u8];
@@ -660,10 +662,6 @@
 implement_ty_decoder!(DecodeContext<'a, 'tcx>);
 
 impl MetadataBlob {
-    pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
-        MetadataBlob(Lrc::new(metadata_ref))
-    }
-
     pub(crate) fn is_compatible(&self) -> bool {
         self.blob().starts_with(METADATA_HEADER)
     }
@@ -961,7 +959,7 @@
             .decode((self, sess))
     }
 
-    fn get_debugger_visualizers(self) -> Vec<rustc_span::DebuggerVisualizerFile> {
+    fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> {
         self.root.debugger_visualizers.decode(self).collect::<Vec<_>>()
     }
 
@@ -1062,7 +1060,7 @@
             .expect("argument names not encoded for a function")
             .decode((self, sess))
             .nth(0)
-            .map_or(false, |ident| ident.name == kw::SelfLower)
+            .is_some_and(|ident| ident.name == kw::SelfLower)
     }
 
     fn get_associated_item_or_field_def_ids(
@@ -1254,14 +1252,6 @@
         }
     }
 
-    fn is_foreign_item(self, id: DefIndex) -> bool {
-        if let Some(parent) = self.def_key(id).parent {
-            matches!(self.def_kind(parent), DefKind::ForeignMod)
-        } else {
-            false
-        }
-    }
-
     #[inline]
     fn def_key(self, index: DefIndex) -> DefKey {
         *self
@@ -1472,28 +1462,30 @@
                     ..
                 } = source_file_to_import;
 
-                // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
-                // during rust bootstrapping by `remap-debuginfo = true`, and the user
-                // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
+                // If this file is under $sysroot/lib/rustlib/src/
+                // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
                 // then we change `name` to a similar state as if the rust was bootstrapped
                 // with `remap-debuginfo = true`.
                 // This is useful for testing so that tests about the effects of
                 // `try_to_translate_virtual_to_real` don't have to worry about how the
                 // compiler is bootstrapped.
                 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
-                {
-                    if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
-                        for subdir in ["library", "compiler"] {
-                            if let rustc_span::FileName::Real(ref mut old_name) = name {
-                                if let rustc_span::RealFileName::LocalPath(local) = old_name {
-                                    if let Ok(rest) = local.strip_prefix(real_dir.join(subdir)) {
-                                        *old_name = rustc_span::RealFileName::Remapped {
-                                            local_path: None,
-                                            virtual_name: virtual_dir.join(subdir).join(rest),
-                                        };
-                                    }
-                                }
-                            }
+                && let Some(real_dir) = &sess.opts.real_rust_source_base_dir
+                && let rustc_span::FileName::Real(ref mut old_name) = name {
+                    let relative_path = match old_name {
+                        rustc_span::RealFileName::LocalPath(local) => local.strip_prefix(real_dir).ok(),
+                        rustc_span::RealFileName::Remapped { virtual_name, .. } => {
+                            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
+                        }
+                    };
+                    debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
+                    for subdir in ["library", "compiler"] {
+                        if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
+                            *old_name = rustc_span::RealFileName::Remapped {
+                                local_path: None, // FIXME: maybe we should preserve this?
+                                virtual_name: virtual_dir.join(subdir).join(rest),
+                            };
+                            break;
                         }
                     }
                 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 4a3b783..7425963 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -14,8 +14,8 @@
 use rustc_middle::middle::exported_symbols::ExportedSymbol;
 use rustc_middle::middle::stability::DeprecationEntry;
 use rustc_middle::query::LocalCrate;
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::cstore::CrateStore;
 use rustc_session::{Session, StableCrateId};
@@ -114,8 +114,8 @@
     ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => {
         fn $name<'tcx>(
             $tcx: TyCtxt<'tcx>,
-            def_id_arg: ty::query::query_keys::$name<'tcx>,
-        ) -> ty::query::query_provided::$name<'tcx> {
+            def_id_arg: rustc_middle::query::queries::$name::Key<'tcx>,
+        ) -> rustc_middle::query::queries::$name::ProvidedValue<'tcx> {
             let _prof_timer =
                 $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name)));
 
@@ -280,7 +280,6 @@
     }
     associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
     inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
-    is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
@@ -324,7 +323,7 @@
 
     extra_filename => { cdata.root.extra_filename.clone() }
 
-    traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
+    traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
     trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
     implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
     crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 05402a5..4f280bb 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -1,6 +1,5 @@
 use crate::rmeta::DecodeContext;
 use crate::rmeta::EncodeContext;
-use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
 use rustc_middle::parameterized_over_tcx;
@@ -47,7 +46,7 @@
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> {
         let len = d.read_usize();
         let pos = d.position();
-        let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]);
+        let o = d.blob().clone().0.slice(|blob| &blob[pos..pos + len]);
 
         // Although we already have the data we need via the `OwnedSlice`, we still need
         // to advance the `DecodeContext`'s position so it's in a valid state after
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 36be07f..f067bca 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -8,7 +8,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::memmap::{Mmap, MmapMut};
 use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
-use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
+use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -19,16 +19,17 @@
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::hir::nested_filter;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
 };
 use rustc_middle::mir::interpret;
 use rustc_middle::query::LocalCrate;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_middle::util::common::to_readable_str;
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
@@ -36,9 +37,7 @@
 use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{
-    self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext,
-};
+use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
 use std::hash::Hash;
@@ -1516,8 +1515,11 @@
             if encode_opt {
                 record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
 
-                if tcx.sess.opts.unstable_opts.drop_tracking_mir && let DefKind::Generator = self.tcx.def_kind(def_id) {
-                    record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
+                if tcx.sess.opts.unstable_opts.drop_tracking_mir
+                    && let DefKind::Generator = self.tcx.def_kind(def_id)
+                    && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
+                {
+                    record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
                 }
             }
             if encode_const {
@@ -1852,7 +1854,16 @@
 
     fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
         empty_proc_macro!(self);
-        self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
+        self.lazy_array(
+            self.tcx
+                .debugger_visualizers(LOCAL_CRATE)
+                .iter()
+                // Erase the path since it may contain privacy sensitive data
+                // that we don't want to end up in crate metadata.
+                // The path is only needed for the local crate because of
+                // `--emit dep-info`.
+                .map(DebuggerVisualizerFile::path_erased),
+        )
     }
 
     fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
@@ -1927,7 +1938,7 @@
 
     fn encode_traits(&mut self) -> LazyArray<DefIndex> {
         empty_proc_macro!(self);
-        self.lazy_array(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
+        self.lazy_array(self.tcx.traits(LOCAL_CRATE).iter().map(|def_id| def_id.index))
     }
 
     /// Encodes an index, mapping each trait to its (local) implementations.
@@ -2131,7 +2142,7 @@
         return;
     }
 
-    par_iter(tcx.mir_keys(())).for_each(|&def_id| {
+    par_for_each_in(tcx.mir_keys(()), |&def_id| {
         let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
 
         if encode_const {
@@ -2273,7 +2284,7 @@
     };
 
     // Encode the rustc version string in a predictable location.
-    rustc_version().encode(&mut ecx);
+    rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
 
     // Encode all the entries and extra information in the crate,
     // culminating in the `CrateRoot` which points to all of it.
@@ -2318,7 +2329,7 @@
                 .get(&def_id)
                 .expect("no traits in scope for a doc link")
         },
-        traits_in_crate: |tcx, LocalCrate| {
+        traits: |tcx, LocalCrate| {
             let mut traits = Vec::new();
             for id in tcx.hir().items() {
                 if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 1328d70..97e67fc 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -2,12 +2,12 @@
 use decoder::Metadata;
 use def_path_hash_map::DefPathHashMapRef;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use table::TableBuilder;
 
 use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
@@ -20,8 +20,8 @@
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::mir;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams};
 use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
 use rustc_serialize::opaque::FileEncoder;
@@ -49,8 +49,8 @@
 mod encoder;
 mod table;
 
-pub(crate) fn rustc_version() -> String {
-    format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version"))
+pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
+    format!("rustc {}", cfg_version)
 }
 
 /// Metadata encoding version.
@@ -246,7 +246,7 @@
     proc_macro_data: Option<ProcMacroData>,
 
     tables: LazyTables,
-    debugger_visualizers: LazyArray<rustc_span::DebuggerVisualizerFile>,
+    debugger_visualizers: LazyArray<DebuggerVisualizerFile>,
 
     exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
 
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index a7d97bd..7c56af1 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -11,6 +11,7 @@
 derive_more = "0.99.17"
 either = "1.5.0"
 gsgdt = "0.1.2"
+field-offset = "0.3.5"
 measureme = "10.0.0"
 polonius-engine = "0.13.0"
 rustc_apfloat = { path = "../rustc_apfloat" }
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index c6bbf2e..3d581da 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -1,43 +1,45 @@
-middle_drop_check_overflow =
-    overflow while adding drop-check rules for {$ty}
-    .note = overflowed on {$overflow_ty}
-
-middle_opaque_hidden_type_mismatch =
-    concrete type differs from previous defining opaque type use
-    .label = expected `{$self_ty}`, got `{$other_ty}`
+middle_cannot_be_normalized =
+    unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
 
 middle_conflict_types =
     this expression supplies two conflicting concrete types for the same opaque type
 
-middle_previous_use_here =
-    previous use here
+middle_const_eval_non_int =
+    constant evaluation of enum discriminant resulted in non-integer
+
+middle_const_not_used_in_type_alias =
+    const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+
+middle_cycle =
+    a cycle occurred during layout computation
+
+middle_drop_check_overflow =
+    overflow while adding drop-check rules for {$ty}
+    .note = overflowed on {$overflow_ty}
 
 middle_limit_invalid =
     `limit` must be a non-negative integer
     .label = {$error_str}
 
+middle_opaque_hidden_type_mismatch =
+    concrete type differs from previous defining opaque type use
+    .label = expected `{$self_ty}`, got `{$other_ty}`
+
+middle_previous_use_here =
+    previous use here
+
 middle_recursion_limit_reached =
     reached the recursion limit finding the struct tail for `{$ty}`
     .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]`
 
-middle_const_eval_non_int =
-    constant evaluation of enum discriminant resulted in non-integer
+middle_requires_lang_item = requires `{$name}` lang_item
+
+middle_strict_coherence_needs_negative_coherence =
+    to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
+    .label = due to this attribute
 
 middle_unknown_layout =
     the type `{$ty}` has an unknown layout
 
 middle_values_too_big =
     values of the type `{$ty}` are too big for the current architecture
-
-middle_cannot_be_normalized =
-    unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
-
-middle_cycle =
-    a cycle occurred during layout computation
-
-middle_strict_coherence_needs_negative_coherence =
-    to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
-    .label = due to this attribute
-
-middle_const_not_used_in_type_alias =
-    const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 6a1a2a0..a149a61 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -121,6 +121,7 @@
                 >,
             [] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
             [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
+            [] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
             [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
             [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
             [] mod_child: rustc_middle::metadata::ModChild,
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index dc4aa18..046186d 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,5 +1,5 @@
 use rustc_macros::Diagnostic;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 
 use crate::ty::Ty;
 
@@ -74,6 +74,14 @@
 }
 
 #[derive(Diagnostic)]
+#[diag(middle_requires_lang_item)]
+pub(crate) struct RequiresLangItem {
+    #[primary_span]
+    pub span: Option<Span>,
+    pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
 #[diag(middle_const_not_used_in_type_alias)]
 pub(super) struct ConstNotUsedTraitAlias {
     pub ct: String,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 15d672c..d1ddc8f 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,11 +1,12 @@
 use crate::hir::{ModuleItems, Owner};
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::query::LocalCrate;
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
+use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
@@ -150,11 +151,6 @@
         self.tcx.hir_module_items(module).items()
     }
 
-    #[inline]
-    pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
-        par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
-    }
-
     pub fn def_key(self, def_id: LocalDefId) -> DefKey {
         // Accessing the DefKey is ok, since it is part of DefPathHash.
         self.tcx.definitions_untracked().def_key(def_id)
@@ -414,7 +410,7 @@
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
         let parent = self.parent_id(hir_id);
-        assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)), "{hir_id:?}");
+        assert!(self.find(parent).is_some_and(|n| is_body_owner(n, hir_id)), "{hir_id:?}");
         parent
     }
 
@@ -502,7 +498,7 @@
     }
 
     #[inline]
-    pub fn par_body_owners(self, f: impl Fn(LocalDefId) + Sync + Send) {
+    pub fn par_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
         par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
     }
 
@@ -640,7 +636,7 @@
     }
 
     #[inline]
-    pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) {
+    pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
         let crate_items = self.tcx.hir_crate_items(());
         par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id))
     }
@@ -1170,11 +1166,26 @@
 
     source_file_names.sort_unstable();
 
+    // We have to take care of debugger visualizers explicitly. The HIR (and
+    // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but
+    // these attributes only store the file path to the visualizer file, not
+    // their content. Yet that content is exported into crate metadata, so any
+    // changes to it need to be reflected in the crate hash.
+    let debugger_visualizers: Vec<_> = tcx
+        .debugger_visualizers(LOCAL_CRATE)
+        .iter()
+        // We ignore the path to the visualizer file since it's not going to be
+        // encoded in crate metadata and we already hash the full contents of
+        // the file.
+        .map(DebuggerVisualizerFile::path_erased)
+        .collect();
+
     let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| {
         let mut stable_hasher = StableHasher::new();
         hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
         upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
         source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
+        debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher);
         if tcx.sess.opts.incremental_relative_spans() {
             let definitions = tcx.definitions_untracked();
             let mut owner_spans: Vec<_> = krate
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 7770a5e..45a07fd 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -6,10 +6,11 @@
 pub mod nested_filter;
 pub mod place;
 
-use crate::ty::query::Providers;
+use crate::query::Providers;
 use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
+use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::*;
 use rustc_query_system::ich::StableHashingContext;
@@ -77,19 +78,19 @@
         self.owners().map(|id| id.def_id)
     }
 
-    pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
+    pub fn par_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) {
         par_for_each_in(&self.items[..], |&id| f(id))
     }
 
-    pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + Send + Sync) {
+    pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + DynSend + DynSync) {
         par_for_each_in(&self.trait_items[..], |&id| f(id))
     }
 
-    pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + Send + Sync) {
+    pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + DynSend + DynSync) {
         par_for_each_in(&self.impl_items[..], |&id| f(id))
     }
 
-    pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + Send + Sync) {
+    pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + DynSend + DynSync) {
         par_for_each_in(&self.foreign_items[..], |&id| f(id))
     }
 }
@@ -110,6 +111,12 @@
             None => self.type_of(def_id).map_bound(ImplSubject::Inherent),
         }
     }
+
+    /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
+    pub fn is_foreign_item(self, def_id: impl Into<DefId>) -> bool {
+        self.opt_parent(def_id.into())
+            .is_some_and(|parent| matches!(self.def_kind(parent), DefKind::ForeignMod))
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index c4e41e0..5617131 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -280,7 +280,7 @@
     /// should get its hidden type inferred. So we bubble the opaque type
     /// and the type it was compared against upwards and let the query caller
     /// handle it.
-    pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+    pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
     pub value: R,
 }
 
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index e9172e7..22ee2a8 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -85,12 +85,7 @@
 mod macros;
 
 #[macro_use]
-pub mod query;
-
-#[macro_use]
 pub mod arena;
-#[macro_use]
-pub mod dep_graph;
 pub(crate) mod error;
 pub mod hir;
 pub mod infer;
@@ -104,6 +99,11 @@
 pub mod util;
 mod values;
 
+#[macro_use]
+pub mod query;
+#[macro_use]
+pub mod dep_graph;
+
 // Allows macros to refer to this crate as `::rustc_middle`
 extern crate self as rustc_middle;
 
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index c266584..14343ac 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -468,8 +468,7 @@
 pub fn in_external_macro(sess: &Session, span: Span) -> bool {
     let expn_data = span.ctxt().outer_expn_data();
     match expn_data.kind {
-        ExpnKind::Inlined
-        | ExpnKind::Root
+        ExpnKind::Root
         | ExpnKind::Desugaring(
             DesugaringKind::ForLoop | DesugaringKind::WhileLoop | DesugaringKind::OpaqueTy,
         ) => false,
diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
new file mode 100644
index 0000000..a0497d8
--- /dev/null
+++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
@@ -0,0 +1,38 @@
+use rustc_data_structures::sync::Lrc;
+use std::path::PathBuf;
+
+#[derive(HashStable)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
+pub enum DebuggerVisualizerType {
+    Natvis,
+    GdbPrettyPrinter,
+}
+
+/// A single debugger visualizer file.
+#[derive(HashStable)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
+pub struct DebuggerVisualizerFile {
+    /// The complete debugger visualizer source.
+    pub src: Lrc<[u8]>,
+    /// Indicates which visualizer type this targets.
+    pub visualizer_type: DebuggerVisualizerType,
+    /// The file path to the visualizer file. This is used for reporting
+    /// visualizer files in dep-info. Before it is written to crate metadata,
+    /// the path is erased to `None`, so as not to emit potentially privacy
+    /// sensitive data.
+    pub path: Option<PathBuf>,
+}
+
+impl DebuggerVisualizerFile {
+    pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType, path: PathBuf) -> Self {
+        DebuggerVisualizerFile { src, visualizer_type, path: Some(path) }
+    }
+
+    pub fn path_erased(&self) -> Self {
+        DebuggerVisualizerFile {
+            src: self.src.clone(),
+            visualizer_type: self.visualizer_type,
+            path: None,
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 343ea1f..9a633e0 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -18,12 +18,8 @@
     /// Returns the `DefId` for a given `LangItem`.
     /// If not found, fatally aborts compilation.
     pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
-        self.lang_items().require(lang_item).unwrap_or_else(|err| {
-            if let Some(span) = span {
-                self.sess.span_fatal(span, err.to_string())
-            } else {
-                self.sess.fatal(err.to_string())
-            }
+        self.lang_items().get(lang_item).unwrap_or_else(|| {
+            self.sess.emit_fatal(crate::error::RequiresLangItem { span, name: lang_item.name() });
         })
     }
 
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 12aef66..bd859d4 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -11,7 +11,7 @@
 
 use crate::bug;
 use crate::error::LimitInvalid;
-use crate::ty;
+use crate::query::Providers;
 use rustc_ast::Attribute;
 use rustc_session::Session;
 use rustc_session::{Limit, Limits};
@@ -19,7 +19,7 @@
 
 use std::num::IntErrorKind;
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.limits = |tcx, ()| Limits {
         recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
         move_size_limit: get_limit(
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 9c25f30..85c5af9 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -1,4 +1,5 @@
 pub mod codegen_fn_attrs;
+pub mod debugger_visualizer;
 pub mod dependency_format;
 pub mod exported_symbols;
 pub mod lang_items;
@@ -32,6 +33,6 @@
 pub mod resolve_bound_vars;
 pub mod stability;
 
-pub fn provide(providers: &mut crate::ty::query::Providers) {
+pub fn provide(providers: &mut crate::query::Providers) {
     limits::provide(providers);
 }
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 967fed6..f45cf78 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -64,7 +64,7 @@
         self.at_level(level).is_public()
     }
 
-    pub fn from_vis(vis: Visibility) -> EffectiveVisibility {
+    pub const fn from_vis(vis: Visibility) -> EffectiveVisibility {
         EffectiveVisibility {
             direct: vis,
             reexported: vis,
@@ -72,6 +72,18 @@
             reachable_through_impl_trait: vis,
         }
     }
+
+    #[must_use]
+    pub fn min(mut self, lhs: EffectiveVisibility, tcx: TyCtxt<'_>) -> Self {
+        for l in Level::all_levels() {
+            let rhs_vis = self.at_level_mut(l);
+            let lhs_vis = *lhs.at_level(l);
+            if rhs_vis.is_at_least(lhs_vis, tcx) {
+                *rhs_vis = lhs_vis;
+            };
+        }
+        self
+    }
 }
 
 /// Holds a map of effective visibilities for reachable HIR nodes.
@@ -82,8 +94,7 @@
 
 impl EffectiveVisibilities {
     pub fn is_public_at_level(&self, id: LocalDefId, level: Level) -> bool {
-        self.effective_vis(id)
-            .map_or(false, |effective_vis| effective_vis.is_public_at_level(level))
+        self.effective_vis(id).is_some_and(|effective_vis| effective_vis.is_public_at_level(level))
     }
 
     /// See `Level::Reachable`.
@@ -137,24 +148,6 @@
         };
     }
 
-    pub fn set_public_at_level(
-        &mut self,
-        id: LocalDefId,
-        lazy_private_vis: impl FnOnce() -> Visibility,
-        level: Level,
-    ) {
-        let mut effective_vis = self
-            .effective_vis(id)
-            .copied()
-            .unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
-        for l in Level::all_levels() {
-            if l <= level {
-                *effective_vis.at_level_mut(l) = Visibility::Public;
-            }
-        }
-        self.map.insert(id, effective_vis);
-    }
-
     pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
         if !cfg!(debug_assertions) {
             return;
@@ -219,7 +212,7 @@
     pub fn update(
         &mut self,
         id: Id,
-        nominal_vis: Visibility,
+        nominal_vis: Option<Visibility>,
         lazy_private_vis: impl FnOnce() -> Visibility,
         inherited_effective_vis: EffectiveVisibility,
         level: Level,
@@ -243,12 +236,11 @@
                 if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
                     && level != l)
                 {
-                    calculated_effective_vis =
-                        if nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
-                            inherited_effective_vis_at_level
-                        } else {
-                            nominal_vis
-                        };
+                    calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
+                        nominal_vis
+                    } else {
+                        inherited_effective_vis_at_level
+                    }
                 }
                 // effective visibility can't be decreased at next update call for the
                 // same id
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 89fc864..6354c0a 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -375,7 +375,7 @@
                 let parent_def_id = self.hir().get_parent_item(id);
                 let skip = self
                     .lookup_deprecation_entry(parent_def_id.to_def_id())
-                    .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
+                    .is_some_and(|parent_depr| parent_depr.same_origin(&depr_entry));
 
                 // #[deprecated] doesn't emit a notice if we're not on the
                 // topmost deprecation. For example, if a struct is deprecated,
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 1319ddb..9d70dbf 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -27,6 +27,7 @@
     switch_sources: OnceCell<SwitchSources>,
     is_cyclic: OnceCell<bool>,
     postorder: OnceCell<Vec<BasicBlock>>,
+    dominators: OnceCell<Dominators<BasicBlock>>,
 }
 
 impl<'tcx> BasicBlocks<'tcx> {
@@ -41,8 +42,8 @@
         *self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
     }
 
-    pub fn dominators(&self) -> Dominators<BasicBlock> {
-        dominators(&self)
+    pub fn dominators(&self) -> &Dominators<BasicBlock> {
+        self.cache.dominators.get_or_init(|| dominators(self))
     }
 
     /// Returns predecessors for each basic block.
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index e45284c..055d8e9 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,7 +1,8 @@
 use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
 
 use crate::mir::interpret::ConstValue;
-use crate::ty::{layout, query::TyCtxtAt, tls, Ty, ValTree};
+use crate::query::TyCtxtAt;
+use crate::ty::{layout, tls, Ty, ValTree};
 
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
@@ -15,15 +16,49 @@
 pub enum ErrorHandled {
     /// Already reported an error for this evaluation, and the compilation is
     /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
-    Reported(ErrorGuaranteed),
+    Reported(ReportedErrorInfo),
     /// Don't emit an error, the evaluation failed because the MIR was generic
     /// and the substs didn't fully monomorphize it.
     TooGeneric,
 }
 
 impl From<ErrorGuaranteed> for ErrorHandled {
-    fn from(err: ErrorGuaranteed) -> ErrorHandled {
-        ErrorHandled::Reported(err)
+    #[inline]
+    fn from(error: ErrorGuaranteed) -> ErrorHandled {
+        ErrorHandled::Reported(error.into())
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub struct ReportedErrorInfo {
+    error: ErrorGuaranteed,
+    is_tainted_by_errors: bool,
+}
+
+impl ReportedErrorInfo {
+    #[inline]
+    pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { is_tainted_by_errors: true, error }
+    }
+
+    /// Returns true if evaluation failed because MIR was tainted by errors.
+    #[inline]
+    pub fn is_tainted_by_errors(self) -> bool {
+        self.is_tainted_by_errors
+    }
+}
+
+impl From<ErrorGuaranteed> for ReportedErrorInfo {
+    #[inline]
+    fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { is_tainted_by_errors: false, error }
+    }
+}
+
+impl Into<ErrorGuaranteed> for ReportedErrorInfo {
+    #[inline]
+    fn into(self) -> ErrorGuaranteed {
+        self.error
     }
 }
 
@@ -89,7 +124,7 @@
 
 impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
     fn from(err: ErrorGuaranteed) -> Self {
-        InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err)).into()
+        InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
     }
 }
 
@@ -125,7 +160,7 @@
     /// Resolution can fail if we are in a too generic context.
     TooGeneric,
     /// Abort in case errors are already reported.
-    AlreadyReported(ErrorGuaranteed),
+    AlreadyReported(ReportedErrorInfo),
     /// An error occurred during layout computation.
     Layout(layout::LayoutError<'tcx>),
     /// An error occurred during FnAbi computation: the passed --target lacks FFI support
@@ -144,7 +179,7 @@
         use InvalidProgramInfo::*;
         match self {
             TooGeneric => write!(f, "encountered overly generic constant"),
-            AlreadyReported(ErrorGuaranteed { .. }) => {
+            AlreadyReported(_) => {
                 write!(
                     f,
                     "an error has already been reported elsewhere (this should not usually be printed)"
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index e5a9766..3620385 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -120,8 +120,8 @@
 pub use self::error::{
     struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
     EvalToValTreeResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo,
-    MachineStopType, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
-    UninitBytesAccess, UnsupportedOpInfo,
+    MachineStopType, ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch,
+    UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
 };
 
 pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index ed4ee93..f53dc8c 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -1,9 +1,10 @@
 use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
 
 use crate::mir;
+use crate::query::{TyCtxtAt, TyCtxtEnsure};
 use crate::ty::subst::InternalSubsts;
 use crate::ty::visit::TypeVisitableExt;
-use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
+use crate::ty::{self, TyCtxt};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_session::lint;
@@ -61,7 +62,7 @@
                 self.const_eval_global_id(param_env, cid, span)
             }
             Ok(None) => Err(ErrorHandled::TooGeneric),
-            Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+            Err(err) => Err(ErrorHandled::Reported(err.into())),
         }
     }
 
@@ -110,7 +111,7 @@
                 })
             }
             Ok(None) => Err(ErrorHandled::TooGeneric),
-            Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+            Err(err) => Err(ErrorHandled::Reported(err.into())),
         }
     }
 
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 55991fa..5c71910 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -101,7 +101,7 @@
 /// pass will be named after the type, and it will consist of a main
 /// loop that goes over each available MIR and applies `run_pass`.
 pub trait MirPass<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
@@ -1111,6 +1111,10 @@
     /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
     /// argument number in the original function before it was inlined.
     pub argument_index: Option<u16>,
+
+    /// The data represents `name` dereferenced `references` times,
+    /// and not the direct value.
+    pub references: u8,
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -1550,8 +1554,11 @@
     /// Returns `true` if this is accepted inside `VarDebugInfoContents::Place`.
     pub fn can_use_in_debuginfo(&self) -> bool {
         match self {
-            Self::Deref | Self::Downcast(_, _) | Self::Field(_, _) => true,
-            Self::ConstantIndex { .. }
+            Self::ConstantIndex { from_end: false, .. }
+            | Self::Deref
+            | Self::Downcast(_, _)
+            | Self::Field(_, _) => true,
+            Self::ConstantIndex { from_end: true, .. }
             | Self::Index(_)
             | Self::OpaqueCast(_)
             | Self::Subslice { .. } => false,
@@ -1639,18 +1646,7 @@
             return self;
         }
 
-        let mut v: Vec<PlaceElem<'tcx>>;
-
-        let new_projections = if self.projection.is_empty() {
-            more_projections
-        } else {
-            v = Vec::with_capacity(self.projection.len() + more_projections.len());
-            v.extend(self.projection);
-            v.extend(more_projections);
-            &v
-        };
-
-        Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
+        self.as_ref().project_deeper(more_projections, tcx)
     }
 }
 
@@ -1721,6 +1717,27 @@
             (base, *proj)
         })
     }
+
+    /// Generates a new place by appending `more_projections` to the existing ones
+    /// and interning the result.
+    pub fn project_deeper(
+        self,
+        more_projections: &[PlaceElem<'tcx>],
+        tcx: TyCtxt<'tcx>,
+    ) -> Place<'tcx> {
+        let mut v: Vec<PlaceElem<'tcx>>;
+
+        let new_projections = if self.projection.is_empty() {
+            more_projections
+        } else {
+            v = Vec::with_capacity(self.projection.len() + more_projections.len());
+            v.extend(self.projection);
+            v.extend(more_projections);
+            &v
+        };
+
+        Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
+    }
 }
 
 impl Debug for Place<'_> {
@@ -2313,7 +2330,7 @@
                 if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
                     match val {
                         Ok(val) => Self::Val(val, c.ty()),
-                        Err(_) => Self::Ty(tcx.const_error(self.ty())),
+                        Err(guar) => Self::Ty(tcx.const_error(self.ty(), guar)),
                     }
                 } else {
                     self
@@ -2325,9 +2342,7 @@
                 match tcx.const_eval_resolve(param_env, uneval, None) {
                     Ok(val) => Self::Val(val, ty),
                     Err(ErrorHandled::TooGeneric) => self,
-                    Err(ErrorHandled::Reported(guar)) => {
-                        Self::Ty(tcx.const_error_with_guaranteed(ty, guar))
-                    }
+                    Err(ErrorHandled::Reported(guar)) => Self::Ty(tcx.const_error(ty, guar.into())),
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ff54ec5..f31b343 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -334,10 +334,7 @@
     }
 
     pub fn modify_size_estimate(&mut self, delta: usize) {
-        assert!(self.size_estimate.is_some());
-        if let Some(size_estimate) = self.size_estimate {
-            self.size_estimate = Some(size_estimate + delta);
-        }
+        *self.size_estimate.as_mut().unwrap() += delta;
     }
 
     pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index fa8a339..62c3d8c 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -551,8 +551,13 @@
         }
 
         let indented_debug_info = format!(
-            "{0:1$}debug {2} => {3:?};",
-            INDENT, indent, var_debug_info.name, var_debug_info.value,
+            "{0:1$}debug {2} => {3:&<4$}{5:?};",
+            INDENT,
+            indent,
+            var_debug_info.name,
+            "",
+            var_debug_info.references as usize,
+            var_debug_info.value,
         );
 
         writeln!(
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 33b7fe0..21faf19 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -749,6 +749,29 @@
     },
 }
 
+impl TerminatorKind<'_> {
+    /// Returns a simple string representation of a `TerminatorKind` variant, independent of any
+    /// values it might hold (e.g. `TerminatorKind::Call` always returns `"Call"`).
+    pub const fn name(&self) -> &'static str {
+        match self {
+            TerminatorKind::Goto { .. } => "Goto",
+            TerminatorKind::SwitchInt { .. } => "SwitchInt",
+            TerminatorKind::Resume => "Resume",
+            TerminatorKind::Terminate => "Terminate",
+            TerminatorKind::Return => "Return",
+            TerminatorKind::Unreachable => "Unreachable",
+            TerminatorKind::Drop { .. } => "Drop",
+            TerminatorKind::Call { .. } => "Call",
+            TerminatorKind::Assert { .. } => "Assert",
+            TerminatorKind::Yield { .. } => "Yield",
+            TerminatorKind::GeneratorDrop => "GeneratorDrop",
+            TerminatorKind::FalseEdge { .. } => "FalseEdge",
+            TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
+            TerminatorKind::InlineAsm { .. } => "InlineAsm",
+        }
+    }
+}
+
 /// Action to be taken when a stack unwind happens.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index d7a7fde..596dd80 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -842,6 +842,7 @@
                     source_info,
                     value,
                     argument_index: _,
+                    references: _,
                 } = var_debug_info;
 
                 self.visit_source_info(source_info);
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index b45f7ca..fd02a16 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -28,7 +28,7 @@
     };
 
     Erased::<<T as EraseType>::Result> {
-        // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
+        // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
         data: unsafe { transmute_copy(&src) },
     }
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 5acdd68..1528be4 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -4,13 +4,98 @@
 //! ["Queries: demand-driven compilation"](https://rustc-dev-guide.rust-lang.org/query.html).
 //! This chapter includes instructions for adding new queries.
 
-use crate::ty::{self, print::describe_as_module, TyCtxt};
+#![allow(unused_parens)]
+
+use crate::dep_graph;
+use crate::dep_graph::DepKind;
+use crate::infer::canonical::{self, Canonical};
+use crate::lint::LintExpectation;
+use crate::metadata::ModChild;
+use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
+use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
+use crate::middle::lib_features::LibFeatures;
+use crate::middle::privacy::EffectiveVisibilities;
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
+use crate::middle::stability::{self, DeprecationEntry};
+use crate::mir;
+use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{
+    ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
+};
+use crate::mir::interpret::{LitToConstError, LitToConstInput};
+use crate::mir::mono::CodegenUnit;
+use crate::query::erase::{erase, restore, Erase};
+use crate::query::plumbing::{query_ensure, query_get_at, DynamicQuery};
+use crate::thir;
+use crate::traits::query::{
+    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
+    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
+    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
+};
+use crate::traits::query::{
+    DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
+    OutlivesBound,
+};
+use crate::traits::specialization_graph;
+use crate::traits::{
+    CanonicalChalkEnvironmentAndGoal, CodegenObligationError, EvaluationResult, ImplSource,
+    ObjectSafetyViolation, ObligationCause, OverflowError, WellFormedLoc,
+};
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::ValidityRequirement;
+use crate::ty::subst::{GenericArg, SubstsRef};
+use crate::ty::util::AlwaysRequiresDrop;
+use crate::ty::GeneratorDiagnosticData;
+use crate::ty::TyCtxtFeed;
+use crate::ty::{
+    self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt,
+    UnusedGenericParams,
+};
+use rustc_arena::TypedArena;
+use rustc_ast as ast;
+use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_attr as attr;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
+use rustc_data_structures::steal::Steal;
+use rustc_data_structures::svh::Svh;
+use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::WorkerLocal;
+use rustc_data_structures::unord::UnordSet;
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, DocLinkResMap};
+use rustc_hir::def_id::{
+    CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
+};
+use rustc_hir::lang_items::{LangItem, LanguageItems};
+use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
+use rustc_index::IndexVec;
+use rustc_query_system::ich::StableHashingContext;
+use rustc_query_system::query::{try_get_cached, CacheSelector, QueryCache, QueryMode, QueryState};
+use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
+use rustc_session::cstore::{CrateDepKind, CrateSource};
+use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
+use rustc_session::lint::LintExpectationId;
+use rustc_session::Limits;
 use rustc_span::def_id::LOCAL_CRATE;
+use rustc_span::symbol::Symbol;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi;
+use rustc_target::spec::PanicStrategy;
+use std::mem;
+use std::ops::Deref;
+use std::path::PathBuf;
+use std::sync::Arc;
 
 pub mod erase;
 mod keys;
-pub mod on_disk_cache;
 pub use keys::{AsLocalKey, Key, LocalCrate};
+pub mod on_disk_cache;
+#[macro_use]
+pub mod plumbing;
+pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue};
 
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
@@ -446,7 +531,7 @@
         }
     }
 
-    query mir_generator_witnesses(key: DefId) -> &'tcx mir::GeneratorLayout<'tcx> {
+    query mir_generator_witnesses(key: DefId) -> &'tcx Option<mir::GeneratorLayout<'tcx>> {
         arena_cache
         desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
@@ -645,12 +730,6 @@
         desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) }
     }
 
-    /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
-    query is_foreign_item(key: DefId) -> bool {
-        desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) }
-        separate_provide_extern
-    }
-
     /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator.
     query generator_kind(def_id: DefId) -> Option<hir::GeneratorKind> {
         desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) }
@@ -1197,7 +1276,7 @@
 
     query codegen_select_candidate(
         key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
-    ) -> Result<&'tcx ImplSource<'tcx, ()>, traits::CodegenObligationError> {
+    ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
         cache_on_disk_if { true }
         desc { |tcx| "computing candidate for `{}`", key.1 }
     }
@@ -1218,7 +1297,7 @@
         desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
         cache_on_disk_if { true }
     }
-    query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] {
+    query object_safety_violations(trait_id: DefId) -> &'tcx [ObjectSafetyViolation] {
         desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) }
     }
     query check_is_object_safe(trait_id: DefId) -> bool {
@@ -1709,12 +1788,18 @@
         desc { "looking at the source for a crate" }
         separate_provide_extern
     }
+
     /// Returns the debugger visualizers defined for this crate.
-    query debugger_visualizers(_: CrateNum) -> &'tcx Vec<rustc_span::DebuggerVisualizerFile> {
+    /// NOTE: This query has to be marked `eval_always` because it reads data
+    ///       directly from disk that is not tracked anywhere else. I.e. it
+    ///       represents a genuine input to the query system.
+    query debugger_visualizers(_: CrateNum) -> &'tcx Vec<DebuggerVisualizerFile> {
         arena_cache
         desc { "looking up the debugger visualizers for this crate" }
         separate_provide_extern
+        eval_always
     }
+
     query postorder_cnums(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "generating a postorder list of CrateNums" }
@@ -1756,8 +1841,7 @@
     }
 
     /// A list of all traits in a crate, used by rustdoc and error reporting.
-    /// NOTE: Not named just `traits` due to a naming conflict.
-    query traits_in_crate(_: CrateNum) -> &'tcx [DefId] {
+    query traits(_: CrateNum) -> &'tcx [DefId] {
         desc { "fetching all traits in a crate" }
         separate_provide_extern
     }
@@ -1871,12 +1955,12 @@
     /// `infcx.predicate_must_hold()` instead.
     query evaluate_obligation(
         goal: CanonicalPredicateGoal<'tcx>
-    ) -> Result<traits::EvaluationResult, traits::OverflowError> {
+    ) -> Result<EvaluationResult, OverflowError> {
         desc { "evaluating trait selection obligation `{}`", goal.value.value }
     }
 
     query evaluate_goal(
-        goal: traits::CanonicalChalkEnvironmentAndGoal<'tcx>
+        goal: CanonicalChalkEnvironmentAndGoal<'tcx>
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
         NoSolution
@@ -2046,8 +2130,8 @@
     /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
     /// because the `ty::Ty`-based wfcheck is always run.
     query diagnostic_hir_wf_check(
-        key: (ty::Predicate<'tcx>, traits::WellFormedLoc)
-    ) -> &'tcx Option<traits::ObligationCause<'tcx>> {
+        key: (ty::Predicate<'tcx>, WellFormedLoc)
+    ) -> &'tcx Option<ObligationCause<'tcx>> {
         arena_cache
         eval_always
         no_hash
@@ -2102,3 +2186,6 @@
         desc { "check whether two const param are definitely not equal to eachother"}
     }
 }
+
+rustc_query_append! { define_callbacks! }
+rustc_feedable_queries! { define_feedable! }
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/query/plumbing.rs
similarity index 63%
rename from compiler/rustc_middle/src/ty/query.rs
rename to compiler/rustc_middle/src/query/plumbing.rs
index 07d47ca..97edfc2 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -1,89 +1,26 @@
-#![allow(unused_parens)]
-
 use crate::dep_graph;
 use crate::dep_graph::DepKind;
-use crate::infer::canonical::{self, Canonical};
-use crate::lint::LintExpectation;
-use crate::metadata::ModChild;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use crate::middle::lib_features::LibFeatures;
-use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
-use crate::middle::stability::{self, DeprecationEntry};
-use crate::mir;
-use crate::mir::interpret::GlobalId;
-use crate::mir::interpret::{
-    ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
-};
-use crate::mir::interpret::{LitToConstError, LitToConstInput};
-use crate::mir::mono::CodegenUnit;
-
-use crate::query::erase::{erase, restore, Erase};
 use crate::query::on_disk_cache::CacheEncoder;
 use crate::query::on_disk_cache::EncodedDepNodeIndex;
 use crate::query::on_disk_cache::OnDiskCache;
-use crate::query::{AsLocalKey, Key};
-use crate::thir;
-use crate::traits::query::{
-    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
-    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
-    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
+use crate::query::{
+    DynamicQueries, ExternProviders, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates,
 };
-use crate::traits::query::{
-    DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
-    OutlivesBound,
-};
-use crate::traits::specialization_graph;
-use crate::traits::{self, ImplSource};
-use crate::ty::context::TyCtxtFeed;
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::layout::ValidityRequirement;
-use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::util::AlwaysRequiresDrop;
-use crate::ty::GeneratorDiagnosticData;
-use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
+use crate::ty::TyCtxt;
+use field_offset::FieldOffset;
 use measureme::StringId;
-use rustc_arena::TypedArena;
-use rustc_ast as ast;
-use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_attr as attr;
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
-use rustc_data_structures::steal::Steal;
-use rustc_data_structures::svh::Svh;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::AtomicU64;
-use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::sync::WorkerLocal;
-use rustc_data_structures::unord::UnordSet;
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, DocLinkResMap};
-use rustc_hir::def_id::{
-    CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
-};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::hir_id::OwnerId;
-use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
-use rustc_index::IndexVec;
-use rustc_query_system::ich::StableHashingContext;
+use rustc_query_system::dep_graph::DepNodeIndex;
+use rustc_query_system::dep_graph::SerializedDepNodeIndex;
 pub(crate) use rustc_query_system::query::QueryJobId;
 use rustc_query_system::query::*;
-use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
-use rustc_session::cstore::{CrateDepKind, CrateSource};
-use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
-use rustc_session::lint::LintExpectationId;
-use rustc_session::Limits;
-use rustc_span::symbol::Symbol;
+use rustc_query_system::HandleCycleError;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi;
-use rustc_target::spec::PanicStrategy;
-
-use std::marker::PhantomData;
-use std::mem;
 use std::ops::Deref;
-use std::path::PathBuf;
-use std::sync::Arc;
 
 pub struct QueryKeyStringCache {
     pub def_id_cache: FxHashMap<DefId, StringId>,
@@ -95,19 +32,34 @@
     }
 }
 
-#[derive(Clone, Copy)]
-pub struct QueryStruct<'tcx> {
-    pub try_collect_active_jobs: fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>) -> Option<()>,
-    pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
-    pub encode_query_results:
-        Option<fn(TyCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
+pub struct DynamicQuery<'tcx, C: QueryCache> {
+    pub name: &'static str,
+    pub eval_always: bool,
+    pub dep_kind: DepKind,
+    pub handle_cycle_error: HandleCycleError,
+    pub query_state: FieldOffset<QueryStates<'tcx>, QueryState<C::Key, DepKind>>,
+    pub query_cache: FieldOffset<QueryCaches<'tcx>, C>,
+    pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool,
+    pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value,
+    pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
+    pub can_load_from_disk: bool,
+    pub try_load_from_disk: fn(
+        tcx: TyCtxt<'tcx>,
+        key: &C::Key,
+        prev_index: SerializedDepNodeIndex,
+        index: DepNodeIndex,
+    ) -> Option<C::Value>,
+    pub loadable_from_disk:
+        fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool,
+    pub hash_result: HashResult<C::Value>,
+    pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> C::Value,
+    pub format_value: fn(&C::Value) -> String,
 }
 
 pub struct QuerySystemFns<'tcx> {
     pub engine: QueryEngine,
     pub local_providers: Providers,
     pub extern_providers: ExternProviders,
-    pub query_structs: Vec<QueryStruct<'tcx>>,
     pub encode_query_results: fn(
         tcx: TyCtxt<'tcx>,
         encoder: &mut CacheEncoder<'_, 'tcx>,
@@ -120,6 +72,7 @@
     pub states: QueryStates<'tcx>,
     pub arenas: QueryArenas<'tcx>,
     pub caches: QueryCaches<'tcx>,
+    pub dynamic_queries: DynamicQueries<'tcx>,
 
     /// This provides access to the incremental compilation on-disk cache for query results.
     /// Do not access this directly. It is only meant to be used by
@@ -130,23 +83,6 @@
     pub fns: QuerySystemFns<'tcx>,
 
     pub jobs: AtomicU64,
-
-    // Since we erase query value types we tell the typesystem about them with `PhantomData`.
-    _phantom_values: QueryPhantomValues<'tcx>,
-}
-
-impl<'tcx> QuerySystem<'tcx> {
-    pub fn new(fns: QuerySystemFns<'tcx>, on_disk_cache: Option<OnDiskCache<'tcx>>) -> Self {
-        QuerySystem {
-            states: Default::default(),
-            arenas: Default::default(),
-            caches: Default::default(),
-            on_disk_cache,
-            fns,
-            jobs: AtomicU64::new(1),
-            _phantom_values: Default::default(),
-        }
-    }
 }
 
 #[derive(Copy, Clone)]
@@ -203,7 +139,7 @@
 }
 
 #[inline]
-fn query_get_at<'tcx, Cache>(
+pub fn query_get_at<'tcx, Cache>(
     tcx: TyCtxt<'tcx>,
     execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
     query_cache: &Cache,
@@ -221,7 +157,7 @@
 }
 
 #[inline]
-fn query_ensure<'tcx, Cache>(
+pub fn query_ensure<'tcx, Cache>(
     tcx: TyCtxt<'tcx>,
     execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
     query_cache: &Cache,
@@ -275,8 +211,8 @@
     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
         for<'tcx> fn(
             TyCtxt<'tcx>,
-            query_keys::$name<'tcx>,
-        ) -> query_provided::$name<'tcx>
+            queries::$name::Key<'tcx>,
+        ) -> queries::$name::ProvidedValue<'tcx>
     };
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
         separate_provide_extern_decl!([$($modifiers)*][$($args)*])
@@ -306,60 +242,37 @@
      $($(#[$attr:meta])*
         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
 
-        // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
-        // below, but using type aliases instead of associated types, to bypass
-        // the limitations around normalizing under HRTB - for example, this:
-        // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
-        // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
-        // This is primarily used by the `provide!` macro in `rustc_metadata`.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_keys {
-            use super::*;
+        #[allow(unused_lifetimes)]
+        pub mod queries {
+            $(pub mod $name {
+                use super::super::*;
 
-            $(pub type $name<'tcx> = $($K)*;)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_keys_local {
-            use super::*;
+                pub type Key<'tcx> = $($K)*;
+                pub type Value<'tcx> = $V;
 
-            $(pub type $name<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_values {
-            use super::*;
+                pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);
 
-            $(pub type $name<'tcx> = $V;)*
-        }
+                /// This type alias specifies the type returned from query providers and the type
+                /// used for decoding. For regular queries this is the declared returned type `V`,
+                /// but `arena_cache` will use `<V as Deref>::Target` instead.
+                pub type ProvidedValue<'tcx> = query_if_arena!(
+                    [$($modifiers)*]
+                    (<$V as Deref>::Target)
+                    ($V)
+                );
 
-        /// This module specifies the type returned from query providers and the type used for
-        /// decoding. For regular queries this is the declared returned type `V`, but
-        /// `arena_cache` will use `<V as Deref>::Target` instead.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_provided {
-            use super::*;
-
-            $(
-                pub type $name<'tcx> = query_if_arena!([$($modifiers)*] (<$V as Deref>::Target) ($V));
-            )*
-        }
-
-        /// This module has a function per query which takes a `query_provided` value and coverts
-        /// it to a regular `V` value by allocating it on an arena if the query has the
-        /// `arena_cache` modifier. This will happen when computing the query using a provider or
-        /// decoding a stored result.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_provided_to_value {
-            use super::*;
-
-            $(
+                /// This function takes `ProvidedValue` and coverts it to an erased `Value` by
+                /// allocating it on an arena if the query has the `arena_cache` modifier. The
+                /// value is then erased and returned. This will happen when computing the query
+                /// using a provider or decoding a stored result.
                 #[inline(always)]
-                pub fn $name<'tcx>(
+                pub fn provided_to_erased<'tcx>(
                     _tcx: TyCtxt<'tcx>,
-                    value: query_provided::$name<'tcx>,
-                ) -> Erase<query_values::$name<'tcx>> {
+                    value: ProvidedValue<'tcx>,
+                ) -> Erase<Value<'tcx>> {
                     erase(query_if_arena!([$($modifiers)*]
                         {
-                            if mem::needs_drop::<query_provided::$name<'tcx>>() {
+                            if mem::needs_drop::<ProvidedValue<'tcx>>() {
                                 &*_tcx.query_system.arenas.$name.alloc(value)
                             } else {
                                 &*_tcx.arena.dropless.alloc(value)
@@ -368,46 +281,40 @@
                         (value)
                     ))
                 }
-            )*
+
+                pub type Storage<'tcx> = <
+                    <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>
+                >::Cache;
+
+                // Ensure that keys grow no larger than 64 bytes
+                #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+                const _: () = {
+                    if mem::size_of::<Key<'static>>() > 64 {
+                        panic!("{}", concat!(
+                            "the query `",
+                            stringify!($name),
+                            "` has a key type `",
+                            stringify!($($K)*),
+                            "` that is too large"
+                        ));
+                    }
+                };
+
+                // Ensure that values grow no larger than 64 bytes
+                #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+                const _: () = {
+                    if mem::size_of::<Value<'static>>() > 64 {
+                        panic!("{}", concat!(
+                            "the query `",
+                            stringify!($name),
+                            "` has a value type `",
+                            stringify!($V),
+                            "` that is too large"
+                        ));
+                    }
+                };
+            })*
         }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_storage {
-            use super::*;
-
-            $(
-                pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>>::Cache;
-            )*
-        }
-
-        $(
-            // Ensure that keys grow no larger than 64 bytes
-            #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-            const _: () = {
-                if mem::size_of::<query_keys::$name<'static>>() > 64 {
-                    panic!("{}", concat!(
-                        "the query `",
-                        stringify!($name),
-                        "` has a key type `",
-                        stringify!($($K)*),
-                        "` that is too large"
-                    ));
-                }
-            };
-
-            // Ensure that values grow no larger than 64 bytes
-            #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-            const _: () = {
-                if mem::size_of::<query_values::$name<'static>>() > 64 {
-                    panic!("{}", concat!(
-                        "the query `",
-                        stringify!($name),
-                        "` has a value type `",
-                        stringify!($V),
-                        "` that is too large"
-                    ));
-                }
-            };
-        )*
 
         pub struct QueryArenas<'tcx> {
             $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
@@ -428,13 +335,8 @@
         }
 
         #[derive(Default)]
-        pub struct QueryPhantomValues<'tcx> {
-            $($(#[$attr])* pub $name: PhantomData<query_values::$name<'tcx>>,)*
-        }
-
-        #[derive(Default)]
         pub struct QueryCaches<'tcx> {
-            $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
+            $($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)*
         }
 
         impl<'tcx> TyCtxtEnsure<'tcx> {
@@ -490,6 +392,12 @@
             })*
         }
 
+        pub struct DynamicQueries<'tcx> {
+            $(
+                pub $name: DynamicQuery<'tcx, queries::$name::Storage<'tcx>>,
+            )*
+        }
+
         #[derive(Default)]
         pub struct QueryStates<'tcx> {
             $(
@@ -500,8 +408,8 @@
         pub struct Providers {
             $(pub $name: for<'tcx> fn(
                 TyCtxt<'tcx>,
-                query_keys_local::$name<'tcx>,
-            ) -> query_provided::$name<'tcx>,)*
+                queries::$name::LocalKey<'tcx>,
+            ) -> queries::$name::ProvidedValue<'tcx>,)*
         }
 
         pub struct ExternProviders {
@@ -546,7 +454,7 @@
             $(pub $name: for<'tcx> fn(
                 TyCtxt<'tcx>,
                 Span,
-                query_keys::$name<'tcx>,
+                queries::$name::Key<'tcx>,
                 QueryMode,
             ) -> Option<Erase<$V>>,)*
         }
@@ -570,11 +478,11 @@
         $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
             $(#[$attr])*
             #[inline(always)]
-            pub fn $name(self, value: query_provided::$name<'tcx>) {
+            pub fn $name(self, value: queries::$name::ProvidedValue<'tcx>) {
                 let key = self.key().into_query_param();
 
                 let tcx = self.tcx;
-                let erased = query_provided_to_value::$name(tcx, value);
+                let erased = queries::$name::provided_to_erased(tcx, value);
                 let value = restore::<$V>(erased);
                 let cache = &tcx.query_system.caches.$name;
 
@@ -586,12 +494,20 @@
                             let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx.with_stable_hashing_context(|mut hcx|
                                 (hasher(&mut hcx, &value), hasher(&mut hcx, &old))
                             );
-                            assert_eq!(
-                                old_hash, value_hash,
-                                "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
-                                stringify!($name),
-                            )
+                            if old_hash != value_hash {
+                                // We have an inconsistency. This can happen if one of the two
+                                // results is tainted by errors. In this case, delay a bug to
+                                // ensure compilation is doomed, and keep the `old` value.
+                                tcx.sess.delay_span_bug(DUMMY_SP, format!(
+                                    "Trying to feed an already recorded value for query {} key={key:?}:\n\
+                                    old value: {old:?}\nnew value: {value:?}",
+                                    stringify!($name),
+                                ));
+                            }
                         } else {
+                            // The query is `no_hash`, so we have no way to perform a sanity check.
+                            // If feeding the same value multiple times needs to be supported,
+                            // the query should not be marked `no_hash`.
                             bug!(
                                 "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
                                 stringify!($name),
@@ -627,9 +543,6 @@
 // Queries marked with `fatal_cycle` do not need the latter implementation,
 // as they will raise an fatal error on query cycles instead.
 
-rustc_query_append! { define_callbacks! }
-rustc_feedable_queries! { define_feedable! }
-
 mod sealed {
     use super::{DefId, LocalDefId, OwnerId};
 
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 2f0b07d..0a903a7 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -701,9 +701,9 @@
     }
 
     pub fn borrow_nested_obligations(&self) -> &[N] {
-        match &self {
-            ImplSource::UserDefined(i) => &i.nested[..],
-            ImplSource::Param(n, _) => &n,
+        match self {
+            ImplSource::UserDefined(i) => &i.nested,
+            ImplSource::Param(n, _) => n,
             ImplSource::Builtin(i) => &i.nested,
             ImplSource::AutoImpl(d) => &d.nested,
             ImplSource::Closure(c) => &c.nested,
@@ -717,6 +717,23 @@
         }
     }
 
+    pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
+        match self {
+            ImplSource::UserDefined(i) => &mut i.nested,
+            ImplSource::Param(n, _) => n,
+            ImplSource::Builtin(i) => &mut i.nested,
+            ImplSource::AutoImpl(d) => &mut d.nested,
+            ImplSource::Closure(c) => &mut c.nested,
+            ImplSource::Generator(c) => &mut c.nested,
+            ImplSource::Future(c) => &mut c.nested,
+            ImplSource::Object(d) => &mut d.nested,
+            ImplSource::FnPointer(d) => &mut d.nested,
+            ImplSource::TraitAlias(d) => &mut d.nested,
+            ImplSource::TraitUpcasting(d) => &mut d.nested,
+            ImplSource::ConstDestruct(i) => &mut i.nested,
+        }
+    }
+
     pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
     where
         F: FnMut(N) -> M,
@@ -1091,3 +1108,14 @@
     Unimplemented,
     FulfillmentError,
 }
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub enum DefiningAnchor {
+    /// `DefId` of the item.
+    Bind(LocalDefId),
+    /// When opaque types are not resolved, we `Bubble` up, meaning
+    /// return the opaque/hidden type pair from query, for caller of query to handle it.
+    Bubble,
+    /// Used to catch type mismatch errors when handling opaque types.
+    Error,
+}
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index c4f8718..eae5a28 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -95,8 +95,6 @@
 #[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
 pub struct NoSolution;
 
-pub type Fallible<T> = Result<T, NoSolution>;
-
 impl<'tcx> From<TypeError<'tcx>> for NoSolution {
     fn from(_: TypeError<'tcx>) -> NoSolution {
         NoSolution
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 6b7b910..2c5b64a 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -5,13 +5,13 @@
 
 use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
 use crate::traits::query::NoSolution;
-use crate::traits::Canonical;
+use crate::traits::{Canonical, DefiningAnchor};
 use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
     TypeVisitor,
 };
 
-pub type EvaluationCache<'tcx> = Cache<CanonicalGoal<'tcx>, QueryResult<'tcx>>;
+pub type EvaluationCache<'tcx> = Cache<CanonicalInput<'tcx>, QueryResult<'tcx>>;
 
 /// A goal is a statement, i.e. `predicate`, we want to prove
 /// given some assumptions, i.e. `param_env`.
@@ -96,7 +96,31 @@
     Overflow,
 }
 
-pub type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub struct QueryInput<'tcx, T> {
+    pub goal: Goal<'tcx, T>,
+    pub anchor: DefiningAnchor,
+    pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
+}
+
+/// Additional constraints returned on success.
+#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
+pub struct PredefinedOpaquesData<'tcx> {
+    pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
+}
+
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
+pub struct PredefinedOpaques<'tcx>(pub(crate) Interned<'tcx, PredefinedOpaquesData<'tcx>>);
+
+impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> {
+    type Target = PredefinedOpaquesData<'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+pub type CanonicalInput<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, QueryInput<'tcx, T>>;
 
 pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
 
@@ -124,7 +148,7 @@
 pub struct ExternalConstraintsData<'tcx> {
     // FIXME: implement this.
     pub region_constraints: QueryRegionConstraints<'tcx>,
-    pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+    pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
 }
 
 // FIXME: Having to clone `region_constraints` for folding feels bad and
@@ -165,3 +189,40 @@
         ControlFlow::Continue(())
     }
 }
+
+// FIXME: Having to clone `region_constraints` for folding feels bad and
+// probably isn't great wrt performance.
+//
+// Not sure how to fix this, maybe we should also intern `opaque_types` and
+// `region_constraints` here or something.
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
+    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(FallibleTypeFolder::interner(folder).mk_predefined_opaques_in_body(
+            PredefinedOpaquesData {
+                opaque_types: self
+                    .opaque_types
+                    .iter()
+                    .map(|opaque| opaque.try_fold_with(folder))
+                    .collect::<Result<_, F::Error>>()?,
+            },
+        ))
+    }
+
+    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+        TypeFolder::interner(folder).mk_predefined_opaques_in_body(PredefinedOpaquesData {
+            opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
+        })
+    }
+}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+        &self,
+        visitor: &mut V,
+    ) -> std::ops::ControlFlow<V::BreakTy> {
+        self.opaque_types.visit_with(visitor)
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 468c2c8..cbc68fd 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -83,7 +83,7 @@
 
             (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
 
-            _ => relate::super_relate_tys(self, a, b),
+            _ => relate::structurally_relate_tys(self, a, b),
         }
     }
 
@@ -109,7 +109,7 @@
             _ => {}
         }
 
-        relate::super_relate_consts(self, a, b)
+        relate::structurally_relate_consts(self, a, b)
     }
 
     fn binders<T>(
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 972c417..a39631d 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -53,7 +53,7 @@
             fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
                 let ct = match c.kind() {
                     ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
-                        Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e),
+                        Err(e) => self.tcx.const_error(c.ty(), e),
                         Ok(Some(bac)) => {
                             let substs = self.tcx.erase_regions(uv.substs);
                             let bac = bac.subst(self.tcx, substs);
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index ad9891a..7c5c030 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -111,12 +111,30 @@
     }
 }
 
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `PartialEq` only based on `did`.
 impl PartialEq for AdtDefData {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
-        self.did == other.did
+        // There should be only one `AdtDefData` for each `def_id`, therefore
+        // it is fine to implement `PartialEq` only based on `def_id`.
+        //
+        // Below, we exhaustively destructure `self` and `other` so that if the
+        // definition of `AdtDefData` changes, a compile-error will be produced,
+        // reminding us to revisit this assumption.
+
+        let Self { did: self_def_id, variants: _, flags: _, repr: _ } = self;
+        let Self { did: other_def_id, variants: _, flags: _, repr: _ } = other;
+
+        let res = self_def_id == other_def_id;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.flags == other.flags
+                && self.repr == other.repr
+                && self.variants == other.variants;
+            assert!(deep, "AdtDefData for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index f29bf92..be7b2b7 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -5,6 +5,7 @@
 
 use std::fmt::Write;
 
+use crate::query::Providers;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, LangItem};
@@ -457,6 +458,6 @@
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { closure_typeinfo, ..*providers }
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { closure_typeinfo, ..*providers }
 }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index e7107c2..1a4bd14 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -6,7 +6,6 @@
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::HashStable;
-use std::fmt;
 
 mod int;
 mod kind;
@@ -21,15 +20,6 @@
 #[rustc_pass_by_value]
 pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
 
-impl<'tcx> fmt::Debug for Const<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // This reflects what `Const` looked liked before `Interned` was
-        // introduced. We print it like this to avoid having to update expected
-        // output in a lot of tests.
-        write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
-    }
-}
-
 /// Typed constant value.
 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
 pub struct ConstData<'tcx> {
@@ -142,9 +132,7 @@
                         ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
                         param_ty,
                     )),
-                    Some(rbv::ResolvedArg::Error(guar)) => {
-                        Some(tcx.const_error_with_guaranteed(param_ty, guar))
-                    }
+                    Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)),
                     arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
                 }
             }
@@ -228,7 +216,7 @@
         if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
             match val {
                 Ok(val) => tcx.mk_const(val, self.ty()),
-                Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar),
+                Err(guar) => tcx.const_error(self.ty(), guar),
             }
         } else {
             // Either the constant isn't evaluatable or ValTree creation failed.
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 1ac2cd1..1dd4f8a 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -42,7 +42,7 @@
 }
 
 /// Represents a constant in Rust.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 #[derive(derive_more::From)]
 pub enum ConstKind<'tcx> {
@@ -128,7 +128,7 @@
 }
 
 /// An inference variable for a const, for use in const generics.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
 pub enum InferConst<'tcx> {
     /// Infer the value of the const.
     Var(ty::ConstVid<'tcx>),
@@ -245,7 +245,7 @@
                         // can leak through `val` into the const we return.
                         Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
                         Err(ErrorHandled::TooGeneric) => None,
-                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
                     }
                 }
                 EvalMode::Mir => {
@@ -256,7 +256,7 @@
                         // can leak through `val` into the const we return.
                         Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
                         Err(ErrorHandled::TooGeneric) => None,
-                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
                     }
                 }
             }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8aea2d8..2bde55b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -14,15 +14,16 @@
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstAllocation};
 use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
-use crate::query::on_disk_cache::OnDiskCache;
+use crate::query::plumbing::QuerySystem;
 use crate::query::LocalCrate;
+use crate::query::Providers;
+use crate::query::{IntoQueryParam, TyCtxtAt};
 use crate::thir::Thir;
 use crate::traits;
 use crate::traits::solve;
-use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
-use crate::ty::query::QuerySystem;
-use crate::ty::query::QuerySystemFns;
-use crate::ty::query::{self, TyCtxtAt};
+use crate::traits::solve::{
+    ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
+};
 use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
     GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
@@ -81,8 +82,6 @@
 use std::mem;
 use std::ops::{Bound, Deref};
 
-use super::query::IntoQueryParam;
-
 const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
 
 #[allow(rustc::usage_of_ty_tykind)]
@@ -143,6 +142,7 @@
     layout: InternedSet<'tcx, LayoutS>,
     adt_def: InternedSet<'tcx, AdtDefData>,
     external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
+    predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
     fields: InternedSet<'tcx, List<FieldIdx>>,
 }
 
@@ -167,6 +167,7 @@
             layout: Default::default(),
             adt_def: Default::default(),
             external_constraints: Default::default(),
+            predefined_opaques_in_body: Default::default(),
             fields: Default::default(),
         }
     }
@@ -496,7 +497,7 @@
     ///
     /// FIXME(Centril): consider `dyn LintStoreMarker` once
     /// we can upcast to `Any` for some additional type safety.
-    pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
+    pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>,
 
     pub dep_graph: DepGraph,
 
@@ -513,7 +514,7 @@
 
     untracked: Untracked,
 
-    pub query_system: query::QuerySystem<'tcx>,
+    pub query_system: QuerySystem<'tcx>,
     pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
 
     // Internal caches for metadata decoding. No need to track deps on this.
@@ -648,14 +649,13 @@
     /// reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
-        lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
+        lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
         untracked: Untracked,
         dep_graph: DepGraph,
-        on_disk_cache: Option<OnDiskCache<'tcx>>,
         query_kinds: &'tcx [DepKindStruct<'tcx>],
-        query_system_fns: QuerySystemFns<'tcx>,
+        query_system: QuerySystem<'tcx>,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.emit_fatal(err);
@@ -677,7 +677,7 @@
             lifetimes: common_lifetimes,
             consts: common_consts,
             untracked,
-            query_system: QuerySystem::new(query_system_fns, on_disk_cache),
+            query_system,
             query_kinds,
             ty_rcache: Default::default(),
             pred_rcache: Default::default(),
@@ -704,7 +704,11 @@
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
-    pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
+    pub fn ty_error_with_message<S: Into<MultiSpan>>(
+        self,
+        span: S,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> Ty<'tcx> {
         let reported = self.sess.delay_span_bug(span, msg);
         self.mk_ty_from_kind(Error(reported))
     }
@@ -735,17 +739,13 @@
 
     /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
     #[track_caller]
-    pub fn const_error_with_guaranteed(
-        self,
-        ty: Ty<'tcx>,
-        reported: ErrorGuaranteed,
-    ) -> Const<'tcx> {
+    pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> {
         self.mk_const(ty::ConstKind::Error(reported), ty)
     }
 
     /// Like [TyCtxt::ty_error] but for constants.
     #[track_caller]
-    pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
+    pub fn const_error_misc(self, ty: Ty<'tcx>) -> Const<'tcx> {
         self.const_error_with_message(
             ty,
             DUMMY_SP,
@@ -1203,7 +1203,7 @@
     pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
         iter::once(LOCAL_CRATE)
             .chain(self.crates(()).iter().copied())
-            .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied())
+            .flat_map(move |cnum| self.traits(cnum).iter().copied())
     }
 
     #[inline]
@@ -1524,6 +1524,8 @@
     adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
     external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
         ExternalConstraints -> ExternalConstraints<'tcx>,
+    predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<'tcx>):
+        PredefinedOpaques -> PredefinedOpaques<'tcx>,
 }
 
 macro_rules! slice_interners {
@@ -2345,7 +2347,7 @@
     }
 
     pub fn is_late_bound(self, id: HirId) -> bool {
-        self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
+        self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id))
     }
 
     pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
@@ -2441,7 +2443,7 @@
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
-    pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
+    pub fn ty_error_with_message(self, msg: impl Into<DiagnosticMessage>) -> Ty<'tcx> {
         self.tcx.ty_error_with_message(self.span, msg)
     }
 }
@@ -2461,7 +2463,7 @@
     pub read_only: bool,
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.maybe_unused_trait_imports =
         |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
     providers.names_imported_by_glob_use = |tcx, id| {
@@ -2478,7 +2480,7 @@
         |tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
     providers.has_panic_handler = |tcx, LocalCrate| {
         // We want to check if the panic handler was defined in this crate
-        tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
+        tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
     };
     providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
 }
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
index fb0d909..9de77b9 100644
--- a/compiler/rustc_middle/src/ty/context/tls.rs
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -1,7 +1,7 @@
 use super::{GlobalCtxt, TyCtxt};
 
 use crate::dep_graph::TaskDepsRef;
-use crate::ty::query;
+use crate::query::plumbing::QueryJobId;
 use rustc_data_structures::sync::{self, Lock};
 use rustc_errors::Diagnostic;
 #[cfg(not(parallel_compiler))]
@@ -22,7 +22,7 @@
 
     /// The current query job, if any. This is updated by `JobOwner::start` in
     /// `ty::query::plumbing` when executing a query.
-    pub query: Option<query::QueryJobId>,
+    pub query: Option<QueryJobId>,
 
     /// Where to store diagnostics for the current query job, if any.
     /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
@@ -78,7 +78,7 @@
 {
     TLV.with(|tlv| {
         let old = tlv.replace(erase(context));
-        let _reset = rustc_data_structures::OnDrop(move || tlv.set(old));
+        let _reset = rustc_data_structures::defer(move || tlv.set(old));
         f()
     })
 }
@@ -94,8 +94,8 @@
         f(None)
     } else {
         // We could get an `ImplicitCtxt` pointer from another thread.
-        // Ensure that `ImplicitCtxt` is `Sync`.
-        sync::assert_sync::<ImplicitCtxt<'_, '_>>();
+        // Ensure that `ImplicitCtxt` is `DynSync`.
+        sync::assert_dyn_sync::<ImplicitCtxt<'_, '_>>();
 
         unsafe { f(Some(downcast(context))) }
     }
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index ad930d1..7895993 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,8 +1,9 @@
+use crate::query::Providers;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
 
-pub(super) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { erase_regions_ty, ..*providers };
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers { erase_regions_ty, ..*providers };
 }
 
 fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index baef4ff..b0ffe78 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -103,7 +103,7 @@
             ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
             ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
             ty::GenericParamDefKind::Const { .. } => {
-                tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
+                tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
             }
         }
     }
@@ -298,7 +298,7 @@
             .iter()
             .rev()
             .take_while(|param| {
-                param.default_value(tcx).map_or(false, |default| {
+                param.default_value(tcx).is_some_and(|default| {
                     default.subst(tcx, substs) == substs[param.index as usize]
                 })
             })
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 9e67200..4223502 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -43,6 +43,7 @@
 //! This code should only compile in modules where the uninhabitedness of `Foo`
 //! is visible.
 
+use crate::query::Providers;
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
 
@@ -52,9 +53,8 @@
 
 pub use inhabited_predicate::InhabitedPredicate;
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers =
-        ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
 }
 
 /// Returns an `InhabitedPredicate` that is generic over type parameters and
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 8c69894..e641d1e 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -659,7 +659,7 @@
     } else {
         None
     };
-    let has_upvars = upvars_ty.map_or(false, |ty| !ty.tuple_fields().is_empty());
+    let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty());
     debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars);
 
     struct PolymorphizationFolder<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 47cf48f..b5a743c 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,5 +1,6 @@
 use crate::fluent_generated as fluent;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
 use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
@@ -268,7 +269,7 @@
 impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
     type TargetDataLayoutRef = &'tcx TargetDataLayout;
 
-    fn delay_bug(&self, txt: &str) {
+    fn delay_bug(&self, txt: String) {
         self.tcx.sess.delay_span_bug(DUMMY_SP, txt);
     }
 
@@ -543,20 +544,20 @@
     }
 }
 
-impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasDataLayout for TyCtxtAt<'tcx> {
     #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
         &self.data_layout
     }
 }
 
-impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTargetSpec for TyCtxtAt<'tcx> {
     fn target_spec(&self) -> &Target {
         &self.sess.target
     }
 }
 
-impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         **self
@@ -683,7 +684,7 @@
     }
 }
 
-impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
+impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
     type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 30f036e..71911a5 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -199,6 +199,12 @@
 
 unsafe impl<T: Sync> Sync for List<T> {}
 
+// We need this since `List` uses extern type `OpaqueListContents`.
+#[cfg(parallel_compiler)]
+use rustc_data_structures::sync::DynSync;
+#[cfg(parallel_compiler)]
+unsafe impl<T: DynSync> DynSync for List<T> {}
+
 // Safety:
 // Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
 // thus aligns of `Equivalent<T>` and `List<T>` must be the same.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b414e12..a8d0dca 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -21,6 +21,7 @@
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
 use crate::mir::{Body, GeneratorLayout};
+use crate::query::Providers;
 use crate::traits::{self, Reveal};
 use crate::ty;
 use crate::ty::fast_reject::SimplifiedType;
@@ -36,7 +37,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
@@ -121,7 +122,6 @@
 pub mod layout;
 pub mod normalize_erasing_regions;
 pub mod print;
-pub mod query;
 pub mod relate;
 pub mod subst;
 pub mod trait_def;
@@ -996,17 +996,11 @@
         }
     }
 
-    /// This function returns the inner `AliasTy` if this term is a projection.
-    ///
-    /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
-    /// deal with constants.
-    pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+    /// This function returns the inner `AliasTy` for a `ty::Alias` or `ConstKind::Unevaluated`.
+    pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
         match self.unpack() {
-            TermKind::Ty(ty) => match ty.kind() {
-                ty::Alias(kind, alias_ty) => match kind {
-                    AliasKind::Projection | AliasKind::Inherent => Some(*alias_ty),
-                    AliasKind::Opaque => None,
-                },
+            TermKind::Ty(ty) => match *ty.kind() {
+                ty::Alias(_kind, alias_ty) => Some(alias_ty),
                 _ => None,
             },
             TermKind::Const(ct) => match ct.kind() {
@@ -1070,6 +1064,24 @@
     }
 }
 
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub enum TermVid<'tcx> {
+    Ty(ty::TyVid),
+    Const(ty::ConstVid<'tcx>),
+}
+
+impl From<ty::TyVid> for TermVid<'_> {
+    fn from(value: ty::TyVid) -> Self {
+        TermVid::Ty(value)
+    }
+}
+
+impl<'tcx> From<ty::ConstVid<'tcx>> for TermVid<'tcx> {
+    fn from(value: ty::ConstVid<'tcx>) -> Self {
+        TermVid::Const(value)
+    }
+}
+
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
@@ -1421,14 +1433,26 @@
 }
 
 impl<'tcx> OpaqueHiddenType<'tcx> {
-    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
+    pub fn report_mismatch(
+        &self,
+        other: &Self,
+        opaque_def_id: LocalDefId,
+        tcx: TyCtxt<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        if let Some(diag) = tcx
+            .sess
+            .diagnostic()
+            .steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch)
+        {
+            diag.cancel();
+        }
         // Found different concrete types for the opaque type.
         let sub_diag = if self.span == other.span {
             TypeMismatchReason::ConflictType { span: self.span }
         } else {
             TypeMismatchReason::PreviousUse { span: self.span }
         };
-        tcx.sess.emit_err(OpaqueHiddenTypeMismatch {
+        tcx.sess.create_err(OpaqueHiddenTypeMismatch {
             self_ty: self.ty,
             other_ty: other.ty,
             other_span: other.span,
@@ -1864,7 +1888,20 @@
 
         let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
         let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
-        lhs_def_id == rhs_def_id
+
+        let res = lhs_def_id == rhs_def_id;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.ctor == other.ctor
+                && self.name == other.name
+                && self.discr == other.discr
+                && self.fields == other.fields
+                && self.flags == other.flags;
+            assert!(deep, "VariantDef for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
@@ -1919,7 +1956,15 @@
 
         let Self { did: rhs_did, name: _, vis: _ } = other;
 
-        lhs_did == rhs_did
+        let res = lhs_did == rhs_did;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.name == other.name && self.vis == other.vis;
+            assert!(deep, "FieldDef for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
@@ -2169,8 +2214,8 @@
         let impl_trait_ref2 = self.impl_trait_ref(def_id2);
         // If either trait impl references an error, they're allowed to overlap,
         // as one of them essentially doesn't exist.
-        if impl_trait_ref1.map_or(false, |tr| tr.subst_identity().references_error())
-            || impl_trait_ref2.map_or(false, |tr| tr.subst_identity().references_error())
+        if impl_trait_ref1.is_some_and(|tr| tr.subst_identity().references_error())
+            || impl_trait_ref2.is_some_and(|tr| tr.subst_identity().references_error())
         {
             return Some(ImplOverlapKind::Permitted { marker: false });
         }
@@ -2191,7 +2236,7 @@
 
         let is_marker_overlap = {
             let is_marker_impl = |trait_ref: Option<EarlyBinder<TraitRef<'_>>>| -> bool {
-                trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker)
+                trait_ref.is_some_and(|tr| self.trait_def(tr.skip_binder().def_id).is_marker)
             };
             is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
         };
@@ -2443,9 +2488,7 @@
             && if self.features().collapse_debuginfo {
                 span.in_macro_expansion_with_collapse_debuginfo()
             } else {
-                // Inlined spans should not be collapsed as that leads to all of the
-                // inlined code being attributed to the inline callsite.
-                span.from_expansion() && !span.is_inlined()
+                span.from_expansion()
             }
     }
 
@@ -2590,7 +2633,7 @@
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     closure::provide(providers);
     context::provide(providers);
     erase_regions::provide(providers);
@@ -2599,7 +2642,7 @@
     print::provide(providers);
     super::util::bug::provide(providers);
     super::middle::provide(providers);
-    *providers = ty::query::Providers {
+    *providers = Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
         incoherent_impls: trait_def::incoherent_impls_provider,
         const_param_default: consts::const_param_default,
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 72710b7..1b336b7 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -207,14 +207,16 @@
                     Some(GenericArgKind::Const(c1)) => c1,
                     Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
                     None => {
-                        if !self.ignore_errors {
-                            self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
+                        let guar = self
+                            .tcx
+                            .sess
+                            .create_err(ConstNotUsedTraitAlias {
                                 ct: ct.to_string(),
                                 span: self.span,
-                            });
-                        }
+                            })
+                            .emit_unless(self.ignore_errors);
 
-                        self.interner().const_error(ct.ty())
+                        self.interner().const_error(ct.ty(), guar)
                     }
                 }
             }
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 810c388..a2e77d9 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -56,6 +56,7 @@
     std::string::String,
     crate::metadata::ModChild,
     crate::middle::codegen_fn_attrs::CodegenFnAttrs,
+    crate::middle::debugger_visualizer::DebuggerVisualizerFile,
     crate::middle::exported_symbols::SymbolExportInfo,
     crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
@@ -91,7 +92,6 @@
     rustc_session::cstore::ForeignModule,
     rustc_session::cstore::LinkagePreference,
     rustc_session::cstore::NativeLib,
-    rustc_span::DebuggerVisualizerFile,
     rustc_span::ExpnData,
     rustc_span::ExpnHash,
     rustc_span::ExpnId,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 926172f..a064174 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,5 +1,6 @@
 use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
-use crate::ty::query::IntoQueryParam;
+use crate::query::IntoQueryParam;
+use crate::query::Providers;
 use crate::ty::{
     self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -702,7 +703,7 @@
             ty::Error(_) => p!("[type error]"),
             ty::Param(ref param_ty) => p!(print(param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
-                ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
+                ty::BoundTyKind::Anon => debug_bound_var(&mut self, debruijn, bound_ty.var)?,
                 ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
                     true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
                     true => p!(write("^{}_{}", debruijn.index(), s)),
@@ -740,7 +741,7 @@
             }
             ty::Placeholder(placeholder) => match placeholder.bound.kind {
                 ty::BoundTyKind::Anon => {
-                    self.pretty_print_placeholder_var(placeholder.universe, placeholder.bound.var)?
+                    debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound.var)?;
                 }
                 ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
             },
@@ -1163,28 +1164,20 @@
         traits.entry(trait_ref).or_default().extend(proj_ty);
     }
 
-    fn pretty_print_bound_var(
-        &mut self,
-        debruijn: ty::DebruijnIndex,
-        var: ty::BoundVar,
-    ) -> Result<(), Self::Error> {
-        if debruijn == ty::INNERMOST {
-            write!(self, "^{}", var.index())
-        } else {
-            write!(self, "^{}_{}", debruijn.index(), var.index())
-        }
-    }
-
-    fn pretty_print_placeholder_var(
-        &mut self,
-        ui: ty::UniverseIndex,
-        var: ty::BoundVar,
-    ) -> Result<(), Self::Error> {
-        if ui == ty::UniverseIndex::ROOT {
-            write!(self, "!{}", var.index())
-        } else {
-            write!(self, "!{}_{}", ui.index(), var.index())
-        }
+    fn pretty_print_inherent_projection(
+        self,
+        alias_ty: &ty::AliasTy<'tcx>,
+    ) -> Result<Self::Path, Self::Error> {
+        let def_key = self.tcx().def_key(alias_ty.def_id);
+        self.path_generic_args(
+            |cx| {
+                cx.path_append(
+                    |cx| cx.path_qualified(alias_ty.self_ty(), None),
+                    &def_key.disambiguated_data,
+                )
+            },
+            &alias_ty.substs[1..],
+        )
     }
 
     fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
@@ -1320,7 +1313,7 @@
         define_scoped_cx!(self);
 
         if self.should_print_verbose() {
-            p!(write("Const({:?}: {:?})", ct.kind(), ct.ty()));
+            p!(write("{:?}", ct));
             return Ok(self);
         }
 
@@ -1379,9 +1372,11 @@
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
-                self.pretty_print_bound_var(debruijn, bound_var)?
+                debug_bound_var(&mut self, debruijn, bound_var)?
             }
-            ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
+            ty::ConstKind::Placeholder(placeholder) => {
+                debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound)?;
+            },
             // FIXME(generic_const_exprs):
             // write out some legible representation of an abstract const?
             ty::ConstKind::Expr(_) => p!("[const expr]"),
@@ -2842,7 +2837,11 @@
     }
 
     ty::AliasTy<'tcx> {
-        p!(print_def_path(self.def_id, self.substs));
+        if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) {
+            p!(pretty_print_inherent_projection(self))
+        } else {
+            p!(print_def_path(self.def_id, self.substs));
+        }
     }
 
     ty::ClosureKind {
@@ -3054,8 +3053,8 @@
     map
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { trimmed_def_paths, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { trimmed_def_paths, ..*providers };
 }
 
 #[derive(Default)]
@@ -3066,3 +3065,27 @@
     fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
     return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
 }
+
+pub fn debug_bound_var<T: std::fmt::Write>(
+    fmt: &mut T,
+    debruijn: ty::DebruijnIndex,
+    var: ty::BoundVar,
+) -> Result<(), std::fmt::Error> {
+    if debruijn == ty::INNERMOST {
+        write!(fmt, "^{}", var.index())
+    } else {
+        write!(fmt, "^{}_{}", debruijn.index(), var.index())
+    }
+}
+
+pub fn debug_placeholder_var<T: std::fmt::Write>(
+    fmt: &mut T,
+    universe: ty::UniverseIndex,
+    bound: ty::BoundVar,
+) -> Result<(), std::fmt::Error> {
+    if universe == ty::UniverseIndex::ROOT {
+        write!(fmt, "!{}", bound.index())
+    } else {
+        write!(fmt, "!{}_{}", universe.index(), bound.index())
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index da43475..3bbe6a2 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -388,24 +388,24 @@
     }
 }
 
-/// The main "type relation" routine. Note that this does not handle
-/// inference artifacts, so you should filter those out before calling
-/// it.
-pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of projections, and inference variables have to be
+/// handled by the caller.
+pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
     a: Ty<'tcx>,
     b: Ty<'tcx>,
 ) -> RelateResult<'tcx, Ty<'tcx>> {
     let tcx = relation.tcx();
-    debug!("super_relate_tys: a={:?} b={:?}", a, b);
+    debug!("structurally_relate_tys: a={:?} b={:?}", a, b);
     match (a.kind(), b.kind()) {
         (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
             // The caller should handle these cases!
-            bug!("var types encountered in super_relate_tys")
+            bug!("var types encountered in structurally_relate_tys")
         }
 
         (ty::Bound(..), _) | (_, ty::Bound(..)) => {
-            bug!("bound types encountered in super_relate_tys")
+            bug!("bound types encountered in structurally_relate_tys")
         }
 
         (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
@@ -575,15 +575,18 @@
     }
 }
 
-/// The main "const relation" routine. Note that this does not handle
-/// inference artifacts, so you should filter those out before calling
-/// it.
-pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
+/// to be handled by the caller.
+///
+/// FIXME: This is not totally structual, which probably should be fixed.
+/// See the HACKs below.
+pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
     mut a: ty::Const<'tcx>,
     mut b: ty::Const<'tcx>,
 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-    debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
+    debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
     let tcx = relation.tcx();
 
     // HACK(const_generics): We still need to eagerly evaluate consts when
@@ -602,7 +605,7 @@
         b = tcx.expand_abstract_consts(b);
     }
 
-    debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+    debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
 
     // Currently, the values that can be unified are primitive types,
     // and those that derive both `PartialEq` and `Eq`, corresponding
@@ -610,7 +613,7 @@
     let is_match = match (a.kind(), b.kind()) {
         (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
             // The caller should handle these cases!
-            bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
+            bug!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
         }
 
         (ty::ConstKind::Error(_), _) => return Ok(a),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 29a3bc8..16cb6c9 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -192,6 +192,44 @@
     }
 }
 
+impl<'tcx> fmt::Debug for ty::InferConst<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            InferConst::Var(var) => write!(f, "{var:?}"),
+            InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
+        }
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::Const<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This reflects what `Const` looked liked before `Interned` was
+        // introduced. We print it like this to avoid having to update expected
+        // output in a lot of tests.
+        write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        use ty::ConstKind::*;
+        match self {
+            Param(param) => write!(f, "{param:?}"),
+            Infer(var) => write!(f, "{var:?}"),
+            Bound(debruijn, var) => ty::print::debug_bound_var(f, *debruijn, *var),
+            Placeholder(placeholder) => {
+                ty::print::debug_placeholder_var(f, placeholder.universe, placeholder.bound)
+            }
+            Unevaluated(uv) => {
+                f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish()
+            }
+            Value(valtree) => write!(f, "{valtree:?}"),
+            Error(_) => write!(f, "[const error]"),
+            Expr(expr) => write!(f, "{expr:?}"),
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Atomic structs
 //
@@ -204,6 +242,7 @@
     (),
     bool,
     usize,
+    u8,
     u16,
     u32,
     u64,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d175cf7..e6d51c4 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1708,7 +1708,9 @@
             ty::ReErased => {
                 flags = flags | TypeFlags::HAS_RE_ERASED;
             }
-            ty::ReError(_) => {}
+            ty::ReError(_) => {
+                flags = flags | TypeFlags::HAS_FREE_REGIONS;
+            }
         }
 
         debug!("type_flags({:?}) = {:?}", self, flags);
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 5a0571f..e04dbbf 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -151,10 +151,14 @@
     /// this field will be set to `Some(ErrorGuaranteed)`.
     pub tainted_by_errors: Option<ErrorGuaranteed>,
 
-    /// All the opaque types that have hidden types set
-    /// by this function. We also store the
-    /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
-    /// even if they are only set in dead code (which doesn't show up in MIR).
+    /// All the opaque types that have hidden types set by this function.
+    /// We also store the type here, so that the compiler can use it as a hint
+    /// for figuring out hidden types, even if they are only set in dead code
+    /// (which doesn't show up in MIR).
+    ///
+    /// These types are mapped back to the opaque's identity substitutions
+    /// (with erased regions), which is why we don't associated substs with any
+    /// of these usages.
     pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
 
     /// Tracks the minimum captures required for a closure;
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 9bab693..ba05135 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,6 +2,7 @@
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir;
+use crate::query::Providers;
 use crate::ty::layout::IntegerExt;
 use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -517,6 +518,42 @@
         Ok(())
     }
 
+    /// Checks whether each generic argument is simply a unique generic placeholder.
+    ///
+    /// This is used in the new solver, which canonicalizes params to placeholders
+    /// for better caching.
+    pub fn uses_unique_placeholders_ignoring_regions(
+        self,
+        substs: SubstsRef<'tcx>,
+    ) -> Result<(), NotUniqueParam<'tcx>> {
+        let mut seen = GrowableBitSet::default();
+        for arg in substs {
+            match arg.unpack() {
+                // Ignore regions, since we can't resolve those in a canonicalized
+                // query in the trait solver.
+                GenericArgKind::Lifetime(_) => {}
+                GenericArgKind::Type(t) => match t.kind() {
+                    ty::Placeholder(p) => {
+                        if !seen.insert(p.bound.var) {
+                            return Err(NotUniqueParam::DuplicateParam(t.into()));
+                        }
+                    }
+                    _ => return Err(NotUniqueParam::NotParam(t.into())),
+                },
+                GenericArgKind::Const(c) => match c.kind() {
+                    ty::ConstKind::Placeholder(p) => {
+                        if !seen.insert(p.bound) {
+                            return Err(NotUniqueParam::DuplicateParam(c.into()));
+                        }
+                    }
+                    _ => return Err(NotUniqueParam::NotParam(c.into())),
+                },
+            }
+        }
+
+        Ok(())
+    }
+
     /// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
     /// that closures have a `DefId`, but the closure *expression* also
     /// has a `HirId` that is located within the context where the
@@ -667,10 +704,10 @@
         self,
         def_id: DefId,
     ) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
-        let generator_layout = &self.mir_generator_witnesses(def_id);
+        let generator_layout = self.mir_generator_witnesses(def_id);
         generator_layout
-            .field_tys
-            .iter()
+            .as_ref()
+            .map_or_else(|| [].iter(), |l| l.field_tys.iter())
             .filter(|decl| !decl.ignore_for_traits)
             .map(|decl| ty::EarlyBinder(decl.ty))
     }
@@ -1484,8 +1521,8 @@
     matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
         reveal_opaque_types_in_bounds,
         is_doc_hidden,
         is_doc_notable_trait,
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index 3dfd082..43ee034 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -48,6 +48,6 @@
     );
 }
 
-pub fn provide(providers: &mut crate::ty::query::Providers) {
-    *providers = crate::ty::query::Providers { trigger_delay_span_bug, ..*providers };
+pub fn provide(providers: &mut crate::query::Providers) {
+    *providers = crate::query::Providers { trigger_delay_span_bug, ..*providers };
 }
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index f346cd4..cb265cf 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -1,62 +1,40 @@
-mir_build_unconditional_recursion = function cannot return without recursing
-    .label = cannot return without recursing
-    .help = a `loop` may express intention better if this is on purpose
+mir_build_adt_defined_here = `{$ty}` defined here
 
-mir_build_unconditional_recursion_call_site_label = recursive call site
+mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable
 
-mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
-    call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
-    .note = consult the function's documentation for information on how to avoid undefined behavior
-    .label = call to unsafe function
+mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
 
-mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
-    call to unsafe function is unsafe and requires unsafe block (error E0133)
-    .note = consult the function's documentation for information on how to avoid undefined behavior
-    .label = call to unsafe function
+mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
 
-mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
-    use of inline assembly is unsafe and requires unsafe block (error E0133)
-    .note = inline assembly is entirely unchecked and can cause undefined behavior
-    .label = use of inline assembly
+mir_build_bindings_with_variant_name =
+    pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
+    .suggestion = to match on the variant, qualify the path
 
-mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
-    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
-    block (error E0133)
-    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
-    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_borrow = value is borrowed by `{$name}` here
 
-mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
-    use of mutable static is unsafe and requires unsafe block (error E0133)
-    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-    .label = use of mutable static
-
-mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
-    use of extern static is unsafe and requires unsafe block (error E0133)
-    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-    .label = use of extern static
-
-mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
-    dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-    .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-    .label = dereference of raw pointer
-
-mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
-    access to union field is unsafe and requires unsafe block (error E0133)
-    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-    .label = access to union field
-
-mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
-    mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
-    .note = mutating layout constrained fields cannot statically be checked for valid values
-    .label = mutation of layout constrained field
-
-mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
-    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+mir_build_borrow_of_layout_constrained_field_requires_unsafe =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
     .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
     .label = borrow of layout constrained field with interior mutability
 
-mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
-    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+    .label = borrow of layout constrained field with interior mutability
+
+mir_build_borrow_of_moved_value = borrow of moved value
+    .label = value moved into `{$name}` here
+    .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
+    .value_borrowed_label = value borrowed here after move
+    .suggestion = borrow this binding in the pattern to avoid moving the value
+
+mir_build_call_to_fn_with_requires_unsafe =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
+    .note = can only be called if the required target features are available
+    .label = call to function with `#[target_feature]`
+
+mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
     .note = can only be called if the required target features are available
     .label = call to function with `#[target_feature]`
 
@@ -70,55 +48,24 @@
     .note = consult the function's documentation for information on how to avoid undefined behavior
     .label = call to unsafe function
 
-mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    call to unsafe function `{$function}` is unsafe and requires unsafe function or block
-    .note = consult the function's documentation for information on how to avoid undefined behavior
-    .label = call to unsafe function
-
 mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed =
     call to unsafe function is unsafe and requires unsafe function or block
     .note = consult the function's documentation for information on how to avoid undefined behavior
     .label = call to unsafe function
 
-mir_build_inline_assembly_requires_unsafe =
-    use of inline assembly is unsafe and requires unsafe block
-    .note = inline assembly is entirely unchecked and can cause undefined behavior
-    .label = use of inline assembly
+mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    call to unsafe function `{$function}` is unsafe and requires unsafe function or block
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
 
-mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    use of inline assembly is unsafe and requires unsafe function or block
-    .note = inline assembly is entirely unchecked and can cause undefined behavior
-    .label = use of inline assembly
+mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
 
-mir_build_initializing_type_with_requires_unsafe =
-    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
-    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
-    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
 
-mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
-    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
-    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_build_const_pattern_depends_on_generic_parameter =
+    constant pattern depends on a generic parameter
 
-mir_build_mutable_static_requires_unsafe =
-    use of mutable static is unsafe and requires unsafe block
-    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-    .label = use of mutable static
-
-mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    use of mutable static is unsafe and requires unsafe function or block
-    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-    .label = use of mutable static
-
-mir_build_extern_static_requires_unsafe =
-    use of extern static is unsafe and requires unsafe block
-    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-    .label = use of extern static
-
-mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    use of extern static is unsafe and requires unsafe function or block
-    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-    .label = use of extern static
+mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
 
 mir_build_deref_raw_pointer_requires_unsafe =
     dereference of raw pointer is unsafe and requires unsafe block
@@ -130,117 +77,46 @@
     .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
     .label = dereference of raw pointer
 
-mir_build_union_field_requires_unsafe =
-    access to union field is unsafe and requires unsafe block
-    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-    .label = access to union field
+mir_build_extern_static_requires_unsafe =
+    use of extern static is unsafe and requires unsafe block
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
 
-mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    access to union field is unsafe and requires unsafe function or block
-    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-    .label = access to union field
+mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of extern static is unsafe and requires unsafe function or block
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
 
-mir_build_mutation_of_layout_constrained_field_requires_unsafe =
-    mutation of layout constrained field is unsafe and requires unsafe block
-    .note = mutating layout constrained fields cannot statically be checked for valid values
-    .label = mutation of layout constrained field
+mir_build_float_pattern = floating-point types cannot be used in patterns
 
-mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    mutation of layout constrained field is unsafe and requires unsafe function or block
-    .note = mutating layout constrained fields cannot statically be checked for valid values
-    .label = mutation of layout constrained field
+mir_build_indirect_structural_match =
+    to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
 
-mir_build_borrow_of_layout_constrained_field_requires_unsafe =
-    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
-    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-    .label = borrow of layout constrained field with interior mutability
+mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
 
-mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
-    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-    .label = borrow of layout constrained field with interior mutability
+mir_build_initializing_type_with_requires_unsafe =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
 
-mir_build_call_to_fn_with_requires_unsafe =
-    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
-    .note = can only be called if the required target features are available
-    .label = call to function with `#[target_feature]`
+mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
 
-mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
-    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
-    .note = can only be called if the required target features are available
-    .label = call to function with `#[target_feature]`
+mir_build_inline_assembly_requires_unsafe =
+    use of inline assembly is unsafe and requires unsafe block
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
 
-mir_build_unused_unsafe = unnecessary `unsafe` block
-    .label = unnecessary `unsafe` block
+mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of inline assembly is unsafe and requires unsafe function or block
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
 
-mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
-mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
+mir_build_interpreted_as_const = introduce a variable instead
 
-mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
-    .def_note = `{$peeled_ty}` defined here
-    .type_note = the matched value is of type `{$ty}`
-    .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
-    .reference_note = references are always considered inhabited
-    .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
-    .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
-
-mir_build_static_in_pattern = statics cannot be referenced in patterns
-
-mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
-
-mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
-
-mir_build_non_const_path = runtime values cannot be referenced in patterns
-
-mir_build_unreachable_pattern = unreachable pattern
-    .label = unreachable pattern
-    .catchall_label = matches any value
-
-mir_build_const_pattern_depends_on_generic_parameter =
-    constant pattern depends on a generic parameter
-
-mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
-
-mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
-    lower range bound must be less than or equal to upper
-    .label = lower bound larger than upper bound
-    .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
-
-mir_build_literal_in_range_out_of_bounds =
-    literal out of range for `{$ty}`
-    .label = this value doesn't fit in `{$ty}` whose maximum value is `{$max}`
-
-mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
-
-mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
-        [one] pattern
-        *[other] patterns
-    } in let chain
-    .note = {$count ->
-        [one] this pattern
-        *[other] these patterns
-    } will always match
-    .help = consider moving {$count ->
-        [one] it
-        *[other] them
-    } outside of the construct
-
-mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
-        [one] pattern
-        *[other] patterns
-    } in let chain
-    .note = {$count ->
-        [one] this pattern
-        *[other] these patterns
-    } will always match
-    .help = consider moving {$count ->
-        [one] it
-        *[other] them
-    } into the body
-
-mir_build_bindings_with_variant_name =
-    pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
-    .suggestion = to match on the variant, qualify the path
+mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
 
 mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
         [one] pattern
@@ -282,78 +158,97 @@
     } will always match, so the loop will never exit
     .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it
 
-mir_build_borrow_of_moved_value = borrow of moved value
-    .label = value moved into `{$name}` here
-    .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
-    .value_borrowed_label = value borrowed here after move
-    .suggestion = borrow this binding in the pattern to avoid moving the value
+mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
+        [one] pattern
+        *[other] patterns
+    } in let chain
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match
+    .help = consider moving {$count ->
+        [one] it
+        *[other] them
+    } outside of the construct
 
-mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
+mir_build_literal_in_range_out_of_bounds =
+    literal out of range for `{$ty}`
+    .label = this value doesn't fit in `{$ty}` whose maximum value is `{$max}`
 
-mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable
+mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
+    lower range bound must be less than or equal to upper
+    .label = lower bound larger than upper bound
+    .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
 
-mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
+mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
 
-mir_build_moved_while_borrowed = cannot move out of value because it is borrowed
-
-mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here
-
-mir_build_borrow = value is borrowed by `{$name}` here
+mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 
 mir_build_moved = value is moved into `{$name}` here
 
-mir_build_union_pattern = cannot use unions in constant patterns
+mir_build_moved_while_borrowed = cannot move out of value because it is borrowed
 
-mir_build_type_not_structural =
-     to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
 
-mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
+mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here
 
-mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
+mir_build_mutable_static_requires_unsafe =
+    use of mutable static is unsafe and requires unsafe block
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
 
-mir_build_float_pattern = floating-point types cannot be used in patterns
+mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of mutable static is unsafe and requires unsafe function or block
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
 
-mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+mir_build_mutation_of_layout_constrained_field_requires_unsafe =
+    mutation of layout constrained field is unsafe and requires unsafe block
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
 
-mir_build_indirect_structural_match =
-    to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    mutation of layout constrained field is unsafe and requires unsafe function or block
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
 
-mir_build_nontrivial_structural_match =
-    to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
-
-mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
-
-mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
-
-mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
-    .range = ... with this range
-    .note = you likely meant to write mutually exclusive ranges
+mir_build_non_const_path = runtime values cannot be referenced in patterns
 
 mir_build_non_exhaustive_omitted_pattern = some variants are not matched explicitly
     .help = ensure that all variants are matched explicitly by adding the suggested match arms
     .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
 
-mir_build_uncovered = {$count ->
-        [1] pattern `{$witness_1}`
-        [2] patterns `{$witness_1}` and `{$witness_2}`
-        [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
-        *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
-    } not covered
+mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
+    .def_note = `{$peeled_ty}` defined here
+    .type_note = the matched value is of type `{$ty}`
+    .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
+    .reference_note = references are always considered inhabited
+    .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+    .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+mir_build_nontrivial_structural_match =
+    to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
+
+mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
+    .range = ... with this range
+    .note = you likely meant to write mutually exclusive ranges
 
 mir_build_pattern_not_covered = refutable pattern in {$origin}
     .pattern_ty = the matched value is of type `{$pattern_ty}`
 
-mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
 
-mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
 
-mir_build_adt_defined_here = `{$ty}` defined here
+mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
+    .attributes = no other attributes may be applied
+    .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
+    .missing_box = `#[rustc_box]` requires the `owned_box` lang item
 
-mir_build_variant_defined_here = not covered
+mir_build_static_in_pattern = statics cannot be referenced in patterns
 
-mir_build_interpreted_as_const = introduce a variable instead
+mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
 
-mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
 
 mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count ->
         [one] variant that isn't
@@ -365,10 +260,117 @@
         *[other] variants that aren't
     } matched
 
-mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
+mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
+        [one] pattern
+        *[other] patterns
+    } in let chain
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match
+    .help = consider moving {$count ->
+        [one] it
+        *[other] them
+    } into the body
 
+mir_build_type_not_structural =
+     to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
 
-mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
-    .attributes = no other attributes may be applied
-    .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
-    .missing_box = `#[rustc_box]` requires the `owned_box` lang item
+mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
+
+mir_build_unconditional_recursion = function cannot return without recursing
+    .label = cannot return without recursing
+    .help = a `loop` may express intention better if this is on purpose
+
+mir_build_unconditional_recursion_call_site_label = recursive call site
+
+mir_build_uncovered = {$count ->
+        [1] pattern `{$witness_1}`
+        [2] patterns `{$witness_1}` and `{$witness_2}`
+        [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
+        *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
+    } not covered
+
+mir_build_union_field_requires_unsafe =
+    access to union field is unsafe and requires unsafe block
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    access to union field is unsafe and requires unsafe function or block
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_union_pattern = cannot use unions in constant patterns
+
+mir_build_unreachable_pattern = unreachable pattern
+    .label = unreachable pattern
+    .catchall_label = matches any value
+
+mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+    .label = borrow of layout constrained field with interior mutability
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+    .note = can only be called if the required target features are available
+    .label = call to function with `#[target_feature]`
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
+    call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
+    call to unsafe function is unsafe and requires unsafe block (error E0133)
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
+    dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+    .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+    .label = dereference of raw pointer
+
+mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
+    use of extern static is unsafe and requires unsafe block (error E0133)
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
+
+mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
+    block (error E0133)
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
+    use of inline assembly is unsafe and requires unsafe block (error E0133)
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
+
+mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
+    use of mutable static is unsafe and requires unsafe block (error E0133)
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
+
+mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
+    mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
+
+mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
+    access to union field is unsafe and requires unsafe block (error E0133)
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
+
+mir_build_unused_unsafe = unnecessary `unsafe` block
+    .label = unnecessary `unsafe` block
+
+mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
+mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
+
+mir_build_variant_defined_here = not covered
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 609ab19..ab4cd24 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -351,7 +351,7 @@
             }
 
             let popped = this.block_context.pop();
-            assert!(popped.map_or(false, |bf| bf.is_statement()));
+            assert!(popped.is_some_and(|bf| bf.is_statement()));
         }
 
         // Then, the block may have an optional trailing expression which is a “return” value
@@ -367,7 +367,7 @@
             unpack!(block = this.expr_into_dest(destination, block, expr));
             let popped = this.block_context.pop();
 
-            assert!(popped.map_or(false, |bf| bf.is_tail_expr()));
+            assert!(popped.is_some_and(|bf| bf.is_tail_expr()));
         } else {
             // If a block has no trailing expression, then it is given an implicit return type.
             // This return type is usually `()`, unless the block is diverging, in which case the
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 931fe1b..b744227 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -154,6 +154,7 @@
                 Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
             },
             @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
+            @call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
             ExprKind::Borrow { borrow_kind, arg } => Ok(
                 Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
             ),
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 5954943..4d99ab4 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -52,7 +52,7 @@
                 match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
                     Ok(c) => c,
                     Err(LitToConstError::Reported(guar)) => {
-                        ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
+                        ConstantKind::Ty(tcx.const_error(ty, guar))
                     }
                     Err(LitToConstError::TypeError) => {
                         bug!("encountered type error in `lit_to_mir_constant`")
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 6941da3..744111e 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -118,7 +118,10 @@
         let category = Category::of(&expr.kind).unwrap();
         debug!(?category, ?expr.kind);
         match category {
-            Category::Constant if let NeedsTemporary::No = needs_temporary || !expr.ty.needs_drop(this.tcx, this.param_env) => {
+            Category::Constant
+                if matches!(needs_temporary, NeedsTemporary::No)
+                    || !expr.ty.needs_drop(this.tcx, this.param_env) =>
+            {
                 let constant = this.as_constant(expr);
                 block.and(Operand::Constant(Box::new(constant)))
             }
@@ -126,7 +129,8 @@
                 let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
                 // Overwrite temp local info if we have something more interesting to record.
                 if !matches!(local_info, LocalInfo::Boring) {
-                    let decl_info = this.local_decls[operand].local_info.as_mut().assert_crate_local();
+                    let decl_info =
+                        this.local_decls[operand].local_info.as_mut().assert_crate_local();
                     if let LocalInfo::Boring | LocalInfo::BlockTailTemp(_) = **decl_info {
                         **decl_info = local_info;
                     }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index c385b00..bcab4c0 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -15,6 +15,7 @@
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
+use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Ty, UpvarSubsts};
 use rustc_span::Span;
 
@@ -225,49 +226,63 @@
                     );
                     let (op,ty) = (Operand::Move(discr), discr_ty);
 
-                    if let Abi::Scalar(scalar) = layout.unwrap().abi{
-                        if let Primitive::Int(_, signed) = scalar.primitive() {
-                            let range = scalar.valid_range(&this.tcx);
-                            // FIXME: Handle wraparound cases too.
-                            if range.end >= range.start {
-                                let mut assumer = |range: u128, bin_op: BinOp| {
-                                    // We will be overwriting this val if our scalar is signed value
-                                    // because sign extension on unsigned types might cause unintended things
-                                    let mut range_val =
-                                        ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(discr_ty));
-                                    let bool_ty = this.tcx.types.bool;
-                                    if signed {
-                                        let scalar_size_extend = scalar.size(&this.tcx).sign_extend(range);
-                                        let discr_layout = this.tcx.layout_of(this.param_env.and(discr_ty));
-                                        let truncated_val = discr_layout.unwrap().size.truncate(scalar_size_extend);
-                                        range_val = ConstantKind::from_bits(
-                                            this.tcx,
-                                            truncated_val,
-                                            ty::ParamEnv::empty().and(discr_ty),
-                                        );
-                                    }
-                                    let lit_op = this.literal_operand(expr.span, range_val);
-                                    let is_bin_op = this.temp(bool_ty, expr_span);
-                                    this.cfg.push_assign(
-                                        block,
-                                        source_info,
-                                        is_bin_op,
-                                        Rvalue::BinaryOp(bin_op, Box::new(((lit_op), (Operand::Copy(discr))))),
-                                    );
-                                    this.cfg.push(
-                                        block,
-                                        Statement {
-                                            source_info,
-                                            kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
-                                                Operand::Copy(is_bin_op),
-                                            ))),
-                                        },
-                                    )
-                                };
-                                assumer(range.end, BinOp::Ge);
-                                assumer(range.start, BinOp::Le);
-                            }
-                        }
+                    if let Abi::Scalar(scalar) = layout.unwrap().abi
+                        && !scalar.is_always_valid(&this.tcx)
+                        && let Primitive::Int(int_width, _signed) = scalar.primitive()
+                    {
+                        let unsigned_ty = int_width.to_ty(this.tcx, false);
+                        let unsigned_place = this.temp(unsigned_ty, expr_span);
+                        this.cfg.push_assign(
+                            block,
+                            source_info,
+                            unsigned_place,
+                            Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr), unsigned_ty));
+
+                        let bool_ty = this.tcx.types.bool;
+                        let range = scalar.valid_range(&this.tcx);
+                        let merge_op =
+                            if range.start <= range.end {
+                                BinOp::BitAnd
+                            } else {
+                                BinOp::BitOr
+                            };
+
+                        let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
+                            let range_val =
+                                ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(unsigned_ty));
+                            let lit_op = this.literal_operand(expr.span, range_val);
+                            let is_bin_op = this.temp(bool_ty, expr_span);
+                            this.cfg.push_assign(
+                                block,
+                                source_info,
+                                is_bin_op,
+                                Rvalue::BinaryOp(bin_op, Box::new((Operand::Copy(unsigned_place), lit_op))),
+                            );
+                            is_bin_op
+                        };
+                        let assert_place = if range.start == 0 {
+                            comparer(range.end, BinOp::Le)
+                        } else {
+                            let start_place = comparer(range.start, BinOp::Ge);
+                            let end_place = comparer(range.end, BinOp::Le);
+                            let merge_place = this.temp(bool_ty, expr_span);
+                            this.cfg.push_assign(
+                                block,
+                                source_info,
+                                merge_place,
+                                Rvalue::BinaryOp(merge_op, Box::new((Operand::Move(start_place), Operand::Move(end_place)))),
+                            );
+                            merge_place
+                        };
+                        this.cfg.push(
+                            block,
+                            Statement {
+                                source_info,
+                                kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
+                                    Operand::Move(assert_place),
+                                ))),
+                            },
+                        );
                     }
 
                     (op,ty)
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 4926ff8..6df06df 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -2241,6 +2241,7 @@
         self.var_debug_info.push(VarDebugInfo {
             name,
             source_info: debug_source_info,
+            references: 0,
             value: VarDebugInfoContents::Place(for_arm_body.into()),
             argument_index: None,
         });
@@ -2260,6 +2261,7 @@
             self.var_debug_info.push(VarDebugInfo {
                 name,
                 source_info: debug_source_info,
+                references: 0,
                 value: VarDebugInfoContents::Place(ref_for_guard.into()),
                 argument_index: None,
             });
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 4536ecf..dbdb5b4 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -380,18 +380,19 @@
         );
     }
 
-    /// Compare two `&T` values using `<T as std::compare::PartialEq>::eq`
+    /// Compare two values using `<T as std::compare::PartialEq>::eq`.
+    /// If the values are already references, just call it directly, otherwise
+    /// take a reference to the values first and then call it.
     fn non_scalar_compare(
         &mut self,
         block: BasicBlock,
         make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
         source_info: SourceInfo,
         value: ConstantKind<'tcx>,
-        place: Place<'tcx>,
+        mut val: Place<'tcx>,
         mut ty: Ty<'tcx>,
     ) {
         let mut expect = self.literal_operand(source_info.span, value);
-        let mut val = Operand::Copy(place);
 
         // If we're using `b"..."` as a pattern, we need to insert an
         // unsizing coercion, as the byte string has the type `&[u8; N]`.
@@ -421,9 +422,13 @@
                         block,
                         source_info,
                         temp,
-                        Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), val, ty),
+                        Rvalue::Cast(
+                            CastKind::Pointer(PointerCast::Unsize),
+                            Operand::Copy(val),
+                            ty,
+                        ),
                     );
-                    val = Operand::Move(temp);
+                    val = temp;
                 }
                 if opt_ref_test_ty.is_some() {
                     let slice = self.temp(ty, source_info.span);
@@ -438,12 +443,36 @@
             }
         }
 
-        let ty::Ref(_, deref_ty, _) = *ty.kind() else {
-            bug!("non_scalar_compare called on non-reference type: {}", ty);
-        };
+        match *ty.kind() {
+            ty::Ref(_, deref_ty, _) => ty = deref_ty,
+            _ => {
+                // non_scalar_compare called on non-reference type
+                let temp = self.temp(ty, source_info.span);
+                self.cfg.push_assign(block, source_info, temp, Rvalue::Use(expect));
+                let ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, ty);
+                let ref_temp = self.temp(ref_ty, source_info.span);
+
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    ref_temp,
+                    Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, temp),
+                );
+                expect = Operand::Move(ref_temp);
+
+                let ref_temp = self.temp(ref_ty, source_info.span);
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    ref_temp,
+                    Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, val),
+                );
+                val = ref_temp;
+            }
+        }
 
         let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
-        let method = trait_method(self.tcx, eq_def_id, sym::eq, [deref_ty, deref_ty]);
+        let method = trait_method(self.tcx, eq_def_id, sym::eq, [ty, ty]);
 
         let bool_ty = self.tcx.types.bool;
         let eq_result = self.temp(bool_ty, source_info.span);
@@ -463,7 +492,7 @@
 
                     literal: method,
                 })),
-                args: vec![val, expect],
+                args: vec![Operand::Copy(val), expect],
                 destination: eq_result,
                 target: Some(eq_block),
                 unwind: UnwindAction::Continue,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 20d381e..4e3e98b 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -798,6 +798,7 @@
                 };
                 self.var_debug_info.push(VarDebugInfo {
                     name,
+                    references: 0,
                     source_info: SourceInfo::outermost(captured_place.var_ident.span),
                     value: VarDebugInfoContents::Place(use_place),
                     argument_index: None,
@@ -828,6 +829,7 @@
                 self.var_debug_info.push(VarDebugInfo {
                     name,
                     source_info,
+                    references: 0,
                     value: VarDebugInfoContents::Place(arg_local.into()),
                     argument_index: Some(argument_index as u16 + 1),
                 });
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 56c87c4..7331f8e 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -325,10 +325,10 @@
         entry_points.sort();
 
         for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
-            if entry_points.last().map_or(false, |entry_point| entry_point.0 == drop_idx) {
+            if entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
                 let block = *blocks[drop_idx].get_or_insert_with(|| T::make_block(cfg));
                 needs_block[drop_idx] = Block::Own;
-                while entry_points.last().map_or(false, |entry_point| entry_point.0 == drop_idx) {
+                while entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
                     let entry_block = entry_points.pop().unwrap().1;
                     T::add_entry(cfg, entry_block, block);
                 }
@@ -644,24 +644,27 @@
             }
         };
 
-        if let Some(destination) = destination {
-            if let Some(value) = value {
+        match (destination, value) {
+            (Some(destination), Some(value)) => {
                 debug!("stmt_expr Break val block_context.push(SubExpr)");
                 self.block_context.push(BlockFrame::SubExpr);
                 unpack!(block = self.expr_into_dest(destination, block, value));
                 self.block_context.pop();
-            } else {
+            }
+            (Some(destination), None) => {
                 self.cfg.push_assign_unit(block, source_info, destination, self.tcx)
             }
-        } else {
-            assert!(value.is_none(), "`return` and `break` should have a destination");
-            if self.tcx.sess.instrument_coverage() {
+            (None, Some(_)) => {
+                panic!("`return`, `become` and `break` with value and must have a destination")
+            }
+            (None, None) if self.tcx.sess.instrument_coverage() => {
                 // Unlike `break` and `return`, which push an `Assign` statement to MIR, from which
                 // a Coverage code region can be generated, `continue` needs no `Assign`; but
                 // without one, the `InstrumentCoverage` MIR pass cannot generate a code region for
                 // `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR.
                 self.add_dummy_assignment(span, block, source_info);
             }
+            (None, None) => {}
         }
 
         let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
@@ -671,12 +674,12 @@
         } else {
             self.scopes.breakable_scopes[break_index].continue_drops.as_mut().unwrap()
         };
-        let mut drop_idx = ROOT_NODE;
-        for scope in &self.scopes.scopes[scope_index + 1..] {
-            for drop in &scope.drops {
-                drop_idx = drops.add_drop(*drop, drop_idx);
-            }
-        }
+
+        let drop_idx = self.scopes.scopes[scope_index + 1..]
+            .iter()
+            .flat_map(|scope| &scope.drops)
+            .fold(ROOT_NODE, |drop_idx, &drop| drops.add_drop(drop, drop_idx));
+
         drops.add_entry(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
@@ -728,7 +731,7 @@
     fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
         // If we are emitting a `drop` statement, we need to have the cached
         // diverge cleanup pads ready in case that drop panics.
-        let needs_cleanup = self.scopes.scopes.last().map_or(false, |scope| scope.needs_cleanup());
+        let needs_cleanup = self.scopes.scopes.last().is_some_and(|scope| scope.needs_cleanup());
         let is_generator = self.generator_kind.is_some();
         let unwind_to = if needs_cleanup { self.diverge_cleanup() } else { DropIdx::MAX };
 
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index dcdeaf0..7c0df20 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -781,6 +781,8 @@
     pub interpreted_as_const: Option<InterpretedAsConst>,
     #[subdiagnostic]
     pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
+    #[note(mir_build_privately_uninhabited)]
+    pub witness_1_is_privately_uninhabited: Option<()>,
     #[note(mir_build_pattern_ty)]
     pub _p: (),
     pub pattern_ty: Ty<'tcx>,
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 2765a10..c964e62 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -22,7 +22,7 @@
 mod lints;
 pub mod thir;
 
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index f46eb5a..b20495d 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -130,6 +130,7 @@
                 ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) }
             }
             Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) },
+            Adjust::NeverToAny if adjustment.target.is_never() => return expr,
             Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
             Adjust::Deref(None) => {
                 adjust_span(&mut expr);
@@ -332,7 +333,7 @@
                         } else if let Some(box_item) = tcx.lang_items().owned_box() {
                             if let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, fn_path)) = fun.kind
                                 && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
-                                && path.res.opt_def_id().map_or(false, |did| did == box_item)
+                                && path.res.opt_def_id().is_some_and(|did| did == box_item)
                                 && fn_path.ident.name == sym::new
                                 && let [value] = args
                             {
@@ -955,7 +956,7 @@
         let is_upvar = self
             .tcx
             .upvars_mentioned(self.body_owner)
-            .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
+            .is_some_and(|upvars| upvars.contains_key(&var_hir_id));
 
         debug!(
             "convert_var({:?}): is_upvar={}, body_owner={:?}",
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index ca25f83..1e51cb9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -90,35 +90,34 @@
 
     #[instrument(level = "trace", skip(self))]
     fn visit_arm(&mut self, arm: &Arm<'tcx>) {
-        match arm.guard {
-            Some(Guard::If(expr)) => {
-                self.with_let_source(LetSource::IfLetGuard, |this| {
-                    this.visit_expr(&this.thir[expr])
-                });
+        self.with_lint_level(arm.lint_level, |this| {
+            match arm.guard {
+                Some(Guard::If(expr)) => {
+                    this.with_let_source(LetSource::IfLetGuard, |this| {
+                        this.visit_expr(&this.thir[expr])
+                    });
+                }
+                Some(Guard::IfLet(ref pat, expr)) => {
+                    this.with_let_source(LetSource::IfLetGuard, |this| {
+                        this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
+                        this.visit_pat(pat);
+                        this.visit_expr(&this.thir[expr]);
+                    });
+                }
+                None => {}
             }
-            Some(Guard::IfLet(ref pat, expr)) => {
-                self.with_let_source(LetSource::IfLetGuard, |this| {
-                    this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
-                    this.visit_pat(pat);
-                    this.visit_expr(&this.thir[expr]);
-                });
-            }
-            None => {}
-        }
-        self.visit_pat(&arm.pattern);
-        self.visit_expr(&self.thir[arm.body]);
+            this.visit_pat(&arm.pattern);
+            this.visit_expr(&self.thir[arm.body]);
+        });
     }
 
     #[instrument(level = "trace", skip(self))]
     fn visit_expr(&mut self, ex: &Expr<'tcx>) {
         match ex.kind {
             ExprKind::Scope { value, lint_level, .. } => {
-                let old_lint_level = self.lint_level;
-                if let LintLevel::Explicit(hir_id) = lint_level {
-                    self.lint_level = hir_id;
-                }
-                self.visit_expr(&self.thir[value]);
-                self.lint_level = old_lint_level;
+                self.with_lint_level(lint_level, |this| {
+                    this.visit_expr(&this.thir[value]);
+                });
                 return;
             }
             ExprKind::If { cond, then, else_opt, if_then_scope: _ } => {
@@ -190,6 +189,17 @@
         self.let_source = old_let_source;
     }
 
+    fn with_lint_level(&mut self, new_lint_level: LintLevel, f: impl FnOnce(&mut Self)) {
+        if let LintLevel::Explicit(hir_id) = new_lint_level {
+            let old_lint_level = self.lint_level;
+            self.lint_level = hir_id;
+            f(self);
+            self.lint_level = old_lint_level;
+        } else {
+            f(self);
+        }
+    }
+
     fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) {
         pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
         check_for_bindings_named_same_as_variants(self, pat, rf);
@@ -236,7 +246,9 @@
         for &arm in arms {
             // Check the arm for some things unrelated to exhaustiveness.
             let arm = &self.thir.arms[arm];
-            self.check_patterns(&arm.pattern, Refutable);
+            self.with_lint_level(arm.lint_level, |this| {
+                this.check_patterns(&arm.pattern, Refutable);
+            });
         }
 
         let tarms: Vec<_> = arms
@@ -479,12 +491,30 @@
             AdtDefinedHere { adt_def_span, ty, variants }
         };
 
+        // Emit an extra note if the first uncovered witness would be uninhabited
+        // if we disregard visibility.
+        let witness_1_is_privately_uninhabited =
+            if cx.tcx.features().exhaustive_patterns
+                && let Some(witness_1) = witnesses.get(0)
+                && let ty::Adt(adt, substs) = witness_1.ty().kind()
+                && adt.is_enum()
+                && let Constructor::Variant(variant_index) = witness_1.ctor()
+            {
+                let variant = adt.variant(*variant_index);
+                let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs);
+                assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module));
+                !inhabited.apply_ignore_module(cx.tcx, cx.param_env)
+            } else {
+                false
+            };
+
         self.error = Err(self.tcx.sess.emit_err(PatternNotCovered {
             span: pat.span,
             origin,
             uncovered: Uncovered::new(pat.span, &cx, witnesses),
             inform,
             interpreted_as_const,
+            witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()),
             _p: (),
             pattern_ty,
             let_suggestion,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index c73f828..b243f1d 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -62,21 +62,13 @@
     treat_byte_string_as_slice: bool,
 }
 
-mod fallback_to_const_ref {
-    #[derive(Debug)]
-    /// This error type signals that we encountered a non-struct-eq situation behind a reference.
-    /// We bubble this up in order to get back to the reference destructuring and make that emit
-    /// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
-    /// on such patterns (since that function takes a reference) and not have to jump through any
-    /// hoops to get a reference to the value.
-    pub(super) struct FallbackToConstRef(());
-
-    pub(super) fn fallback_to_const_ref(c2p: &super::ConstToPat<'_>) -> FallbackToConstRef {
-        assert!(c2p.behind_reference.get());
-        FallbackToConstRef(())
-    }
-}
-use fallback_to_const_ref::{fallback_to_const_ref, FallbackToConstRef};
+/// This error type signals that we encountered a non-struct-eq situation.
+/// We bubble this up in order to get back to the reference destructuring and make that emit
+/// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
+/// on such patterns (since that function takes a reference) and not have to jump through any
+/// hoops to get a reference to the value.
+#[derive(Debug)]
+struct FallbackToConstRef;
 
 impl<'tcx> ConstToPat<'tcx> {
     fn new(
@@ -236,13 +228,13 @@
 
         let kind = match cv.ty().kind() {
             ty::Float(_) => {
-                    tcx.emit_spanned_lint(
-                        lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-                        id,
-                        span,
-                        FloatPattern,
-                    );
-                PatKind::Constant { value: cv }
+                tcx.emit_spanned_lint(
+                    lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+                    id,
+                    span,
+                    FloatPattern,
+                );
+                return Err(FallbackToConstRef);
             }
             ty::Adt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
@@ -289,7 +281,7 @@
                 // Since we are behind a reference, we can just bubble the error up so we get a
                 // constant at reference type, making it easy to let the fallback call
                 // `PartialEq::eq` on it.
-                return Err(fallback_to_const_ref(self));
+                return Err(FallbackToConstRef);
             }
             ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty()) => {
                 debug!(
@@ -393,11 +385,11 @@
                     self.behind_reference.set(old);
                     val
                 }
-                // Backwards compatibility hack: support references to non-structural types.
-                // We'll lower
-                // this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a
-                // reference. This makes the rest of the matching logic simpler as it doesn't have
-                // to figure out how to get a reference again.
+                // Backwards compatibility hack: support references to non-structural types,
+                // but hard error if we aren't behind a double reference. We could just use
+                // the fallback code path below, but that would allow *more* of this fishy
+                // code to compile, as then it only goes through the future incompat lint
+                // instead of a hard error.
                 ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
                     if self.behind_reference.get() {
                         if !self.saw_const_match_error.get()
@@ -411,7 +403,7 @@
                                 IndirectStructuralMatch { non_sm_ty: *pointee_ty },
                             );
                         }
-                        PatKind::Constant { value: cv }
+                        return Err(FallbackToConstRef);
                     } else {
                         if !self.saw_const_match_error.get() {
                             self.saw_const_match_error.set(true);
@@ -435,16 +427,9 @@
                         PatKind::Wild
                     } else {
                         let old = self.behind_reference.replace(true);
-                        // In case there are structural-match violations somewhere in this subpattern,
-                        // we fall back to a const pattern. If we do not do this, we may end up with
-                        // a !structural-match constant that is not of reference type, which makes it
-                        // very hard to invoke `PartialEq::eq` on it as a fallback.
-                        let val = match self.recur(tcx.deref_mir_constant(self.param_env.and(cv)), false) {
-                            Ok(subpattern) => PatKind::Deref { subpattern },
-                            Err(_) => PatKind::Constant { value: cv },
-                        };
+                        let subpattern = self.recur(tcx.deref_mir_constant(self.param_env.and(cv)), false)?;
                         self.behind_reference.set(old);
-                        val
+                        PatKind::Deref { subpattern }
                     }
                 }
             },
@@ -452,7 +437,7 @@
                 PatKind::Constant { value: cv }
             }
             ty::RawPtr(pointee) if pointee.ty.is_sized(tcx, param_env) => {
-                PatKind::Constant { value: cv }
+                return Err(FallbackToConstRef);
             }
             // FIXME: these can have very surprising behaviour where optimization levels or other
             // compilation choices change the runtime behaviour of the match.
@@ -469,7 +454,7 @@
                         PointerPattern
                     );
                 }
-                PatKind::Constant { value: cv }
+                return Err(FallbackToConstRef);
             }
             _ => {
                 self.saw_const_match_error.set(true);
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index 9af1378..6a77146 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -844,8 +844,8 @@
     }
 
     /// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is
-    /// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is
-    /// assumed to have been split from a wildcard.
+    /// assumed to be built from `matrix.head_ctors()` with wildcards and opaques filtered out,
+    /// and `self` is assumed to have been split from a wildcard.
     fn is_covered_by_any<'p>(
         &self,
         pcx: &PatCtxt<'_, 'p, 'tcx>,
@@ -894,7 +894,7 @@
 /// in `to_ctors`: in some cases we only return `Missing`.
 #[derive(Debug)]
 pub(super) struct SplitWildcard<'tcx> {
-    /// Constructors seen in the matrix.
+    /// Constructors (other than wildcards and opaques) seen in the matrix.
     matrix_ctors: Vec<Constructor<'tcx>>,
     /// All the constructors for this type
     all_ctors: SmallVec<[Constructor<'tcx>; 1]>,
@@ -1037,7 +1037,7 @@
         // Since `all_ctors` never contains wildcards, this won't recurse further.
         self.all_ctors =
             self.all_ctors.iter().flat_map(|ctor| ctor.split(pcx, ctors.clone())).collect();
-        self.matrix_ctors = ctors.filter(|c| !c.is_wildcard()).cloned().collect();
+        self.matrix_ctors = ctors.filter(|c| !matches!(c, Wildcard | Opaque)).cloned().collect();
     }
 
     /// Whether there are any value constructors for this type that are not present in the matrix.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index f229b10..e5b6350 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -288,6 +288,22 @@
 //!
 //! The details are not necessary to understand this file, so we explain them in
 //! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function.
+//!
+//! # Constants in patterns
+//!
+//! There are two kinds of constants in patterns:
+//!
+//! * literals (`1`, `true`, `"foo"`)
+//! * named or inline consts (`FOO`, `const { 5 + 6 }`)
+//!
+//! The latter are converted into other patterns with literals at the leaves. For example
+//! `const_to_pat(const { [1, 2, 3] })` becomes an `Array(vec![Const(1), Const(2), Const(3)])`
+//! pattern. This gets problematic when comparing the constant via `==` would behave differently
+//! from matching on the constant converted to a pattern. Situations like that can occur, when
+//! the user implements `PartialEq` manually, and thus could make `==` behave arbitrarily different.
+//! In order to honor the `==` implementation, constants of types that implement `PartialEq` manually
+//! stay as a full constant and become an `Opaque` pattern. These `Opaque` patterns do not participate
+//! in exhaustiveness, specialization or overlap checking.
 
 use self::ArmType::*;
 use self::Usefulness::*;
diff --git a/compiler/rustc_mir_dataflow/messages.ftl b/compiler/rustc_mir_dataflow/messages.ftl
index 9885415..5698367 100644
--- a/compiler/rustc_mir_dataflow/messages.ftl
+++ b/compiler/rustc_mir_dataflow/messages.ftl
@@ -1,11 +1,23 @@
+mir_dataflow_duplicate_values_for =
+    duplicate values for `{$name}`
+
 mir_dataflow_path_must_end_in_filename =
     path must end in a filename
 
-mir_dataflow_unknown_formatter =
-    unknown formatter
+mir_dataflow_peek_argument_not_a_local =
+    rustc_peek: argument was not a local
 
-mir_dataflow_duplicate_values_for =
-    duplicate values for `{$name}`
+mir_dataflow_peek_argument_untracked =
+    rustc_peek: argument untracked
+
+mir_dataflow_peek_bit_not_set =
+    rustc_peek: bit not set
+
+mir_dataflow_peek_must_be_not_temporary =
+    dataflow::sanity_check cannot feed a non-temp to rustc_peek
+
+mir_dataflow_peek_must_be_place_or_ref_place =
+    rustc_peek: argument expression must be either `place` or `&place`
 
 mir_dataflow_requires_an_argument =
     `{$name}` requires an argument
@@ -13,17 +25,5 @@
 mir_dataflow_stop_after_dataflow_ended_compilation =
     stop_after_dataflow ended compilation
 
-mir_dataflow_peek_must_be_place_or_ref_place =
-    rustc_peek: argument expression must be either `place` or `&place`
-
-mir_dataflow_peek_must_be_not_temporary =
-    dataflow::sanity_check cannot feed a non-temp to rustc_peek
-
-mir_dataflow_peek_bit_not_set =
-    rustc_peek: bit not set
-
-mir_dataflow_peek_argument_not_a_local =
-    rustc_peek: argument was not a local
-
-mir_dataflow_peek_argument_untracked =
-    rustc_peek: argument untracked
+mir_dataflow_unknown_formatter =
+    unknown formatter
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 2e68c79..1889507 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -276,6 +276,7 @@
                 assert_eq!(self.elaborator.param_env().reveal(), Reveal::All);
                 let field_ty =
                     tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, substs));
+
                 (tcx.mk_place_field(base_place, field, field_ty), subpath)
             })
             .collect()
diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl
index 8c85cb5f..b13429d 100644
--- a/compiler/rustc_mir_transform/messages.ftl
+++ b/compiler/rustc_mir_transform/messages.ftl
@@ -1,3 +1,8 @@
+mir_transform_arithmetic_overflow = this arithmetic operation will overflow
+mir_transform_call_to_unsafe_label = call to unsafe function
+mir_transform_call_to_unsafe_note = consult the function's documentation for information on how to avoid undefined behavior
+mir_transform_const_defined_here = `const` item defined here
+
 mir_transform_const_modify = attempting to modify a `const` item
     .note = each usage of a `const` item creates a new temporary; the original `const` item will not be modified
 
@@ -6,50 +11,10 @@
     .note2 = the mutable reference will refer to this temporary, not the original `const` item
     .note3 = mutable reference created due to call to this method
 
-mir_transform_const_defined_here = `const` item defined here
-
-mir_transform_unaligned_packed_ref = reference to packed field is unaligned
-    .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
-    .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
-    .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-mir_transform_unused_unsafe = unnecessary `unsafe` block
-    .label = because it's nested under this `unsafe` block
-
-mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in_unsafe_fn_allowed ->
-    [true] function or block
-    *[false] block
-    }
-    .not_inherited = items do not inherit unsafety from separate enclosing items
-
-mir_transform_call_to_unsafe_label = call to unsafe function
-mir_transform_call_to_unsafe_note = consult the function's documentation for information on how to avoid undefined behavior
-mir_transform_use_of_asm_label = use of inline assembly
-mir_transform_use_of_asm_note = inline assembly is entirely unchecked and can cause undefined behavior
-mir_transform_initializing_valid_range_label = initializing type with `rustc_layout_scalar_valid_range` attr
-mir_transform_initializing_valid_range_note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
 mir_transform_const_ptr2int_label = cast of pointer to int
 mir_transform_const_ptr2int_note = casting pointers to integers in constants
-mir_transform_use_of_static_mut_label = use of mutable static
-mir_transform_use_of_static_mut_note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-mir_transform_use_of_extern_static_label = use of extern static
-mir_transform_use_of_extern_static_note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
 mir_transform_deref_ptr_label = dereference of raw pointer
 mir_transform_deref_ptr_note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-mir_transform_union_access_label = access to union field
-mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
-mir_transform_mutation_layout_constrained_label = mutation of layout constrained field
-mir_transform_mutation_layout_constrained_note = mutating layout constrained fields cannot statically be checked for valid values
-mir_transform_mutation_layout_constrained_borrow_label = borrow of layout constrained field with interior mutability
-mir_transform_mutation_layout_constrained_borrow_note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
-mir_transform_target_feature_call_label = call to function with `#[target_feature]`
-mir_transform_target_feature_call_note = can only be called if the required target features are available
-
-mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133)
-
-mir_transform_arithmetic_overflow = this arithmetic operation will overflow
-mir_transform_operation_will_panic = this operation will panic at runtime
-
 mir_transform_ffi_unwind_call = call to {$foreign ->
     [true] foreign function
     *[false] function pointer
@@ -58,9 +23,45 @@
 mir_transform_fn_item_ref = taking a reference to a function item does not give a function pointer
     .suggestion = cast `{$ident}` to obtain a function pointer
 
+mir_transform_initializing_valid_range_label = initializing type with `rustc_layout_scalar_valid_range` attr
+mir_transform_initializing_valid_range_note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
 mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspend point, but should not be
     .label = the value is held across this suspend point
     .note = {$reason}
     .help = consider using a block (`{"{ ... }"}`) to shrink the value's scope, ending before the suspend point
 
+mir_transform_mutation_layout_constrained_borrow_label = borrow of layout constrained field with interior mutability
+mir_transform_mutation_layout_constrained_borrow_note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+mir_transform_mutation_layout_constrained_label = mutation of layout constrained field
+mir_transform_mutation_layout_constrained_note = mutating layout constrained fields cannot statically be checked for valid values
+mir_transform_operation_will_panic = this operation will panic at runtime
+
+mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in_unsafe_fn_allowed ->
+    [true] function or block
+    *[false] block
+    }
+    .not_inherited = items do not inherit unsafety from separate enclosing items
+
 mir_transform_simd_shuffle_last_const = last argument of `simd_shuffle` is required to be a `const` item
+
+mir_transform_target_feature_call_label = call to function with `#[target_feature]`
+mir_transform_target_feature_call_note = can only be called if the required target features are available
+
+mir_transform_unaligned_packed_ref = reference to packed field is unaligned
+    .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses
+    .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+    .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+mir_transform_union_access_label = access to union field
+mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133)
+
+mir_transform_unused_unsafe = unnecessary `unsafe` block
+    .label = because it's nested under this `unsafe` block
+
+mir_transform_use_of_asm_label = use of inline assembly
+mir_transform_use_of_asm_note = inline assembly is entirely unchecked and can cause undefined behavior
+mir_transform_use_of_extern_static_label = use of extern static
+mir_transform_use_of_extern_static_note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+mir_transform_use_of_static_mut_label = use of mutable static
+mir_transform_use_of_static_mut_note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index bdb4f20..069514d 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -7,7 +7,7 @@
 use rustc_hir::{BlockCheckMode, ExprKind, Node};
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index adb09c5..0fe49b8 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -363,7 +363,7 @@
             let left_size = self.ecx.layout_of(left_ty).ok()?.size;
             let right_size = r.layout.size;
             let r_bits = r.to_scalar().to_bits(right_size).ok();
-            if r_bits.map_or(false, |b| b >= left_size.bits() as u128) {
+            if r_bits.is_some_and(|b| b >= left_size.bits() as u128) {
                 debug!("check_binary_op: reporting assert for {:?}", location);
                 let source_info = self.body().source_info(location);
                 let panic = AssertKind::Overflow(
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index c565d6f..319f3a7 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -162,20 +162,22 @@
     }
 
     fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
-        match stmt.kind {
-            // When removing storage statements, we need to remove both (#107511).
-            StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
-                if self.storage_to_remove.contains(l) =>
-            {
-                stmt.make_nop()
-            }
-            StatementKind::Assign(box (ref place, ref mut rvalue))
-                if place.as_local().is_some() =>
-            {
-                // Do not replace assignments.
-                self.visit_rvalue(rvalue, loc)
-            }
-            _ => self.super_statement(stmt, loc),
+        // When removing storage statements, we need to remove both (#107511).
+        if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = stmt.kind
+            && self.storage_to_remove.contains(l)
+        {
+            stmt.make_nop();
+            return
+        }
+
+        self.super_statement(stmt, loc);
+
+        // Do not leave tautological assignments around.
+        if let StatementKind::Assign(box (lhs, ref rhs)) = stmt.kind
+            && let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)) | Rvalue::CopyForDeref(rhs) = *rhs
+            && lhs == rhs
+        {
+            stmt.make_nop();
         }
     }
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index e554c47..6a3d425 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -118,7 +118,7 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::coverage::*;
-use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
+use rustc_middle::mir::{self, BasicBlock};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
@@ -639,7 +639,7 @@
     let def_id = mir_source.def_id();
 
     let span_viewables = span_viewables(tcx, mir_body, basic_coverage_blocks, &coverage_spans);
-    let mut file = create_dump_file(tcx, "html", false, pass_name, &0, mir_body)
+    let mut file = create_dump_file(tcx, "html", false, pass_name, &0i32, mir_body)
         .expect("Unexpected error creating MIR spanview HTML file");
     let crate_name = tcx.crate_name(def_id.krate);
     let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate();
@@ -740,7 +740,7 @@
                 .join("\n  ")
         ));
     }
-    let mut file = create_dump_file(tcx, "dot", false, pass_name, &0, mir_body)
+    let mut file = create_dump_file(tcx, "dot", false, pass_name, &0i32, mir_body)
         .expect("Unexpected error creating BasicCoverageBlock graphviz DOT file");
     graphviz_writer
         .write_graphviz(tcx, &mut file)
@@ -796,7 +796,7 @@
     }
     let non_term_blocks = bcb_data.basic_blocks[0..len - 1]
         .iter()
-        .map(|&bb| format!("{:?}: {}", bb, term_type(&mir_body[bb].terminator().kind)))
+        .map(|&bb| format!("{:?}: {}", bb, mir_body[bb].terminator().kind.name()))
         .collect::<Vec<_>>();
     if non_term_blocks.len() > 0 {
         sections.push(non_term_blocks.join("\n"));
@@ -804,28 +804,7 @@
     sections.push(format!(
         "{:?}: {}",
         bcb_data.basic_blocks.last().unwrap(),
-        term_type(&bcb_data.terminator(mir_body).kind)
+        bcb_data.terminator(mir_body).kind.name(),
     ));
     sections
 }
-
-/// Returns a simple string representation of a `TerminatorKind` variant, independent of any
-/// values it might hold.
-pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
-    match kind {
-        TerminatorKind::Goto { .. } => "Goto",
-        TerminatorKind::SwitchInt { .. } => "SwitchInt",
-        TerminatorKind::Resume => "Resume",
-        TerminatorKind::Terminate => "Terminate",
-        TerminatorKind::Return => "Return",
-        TerminatorKind::Unreachable => "Unreachable",
-        TerminatorKind::Drop { .. } => "Drop",
-        TerminatorKind::Call { .. } => "Call",
-        TerminatorKind::Assert { .. } => "Assert",
-        TerminatorKind::Yield { .. } => "Yield",
-        TerminatorKind::GeneratorDrop => "GeneratorDrop",
-        TerminatorKind::FalseEdge { .. } => "FalseEdge",
-        TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
-        TerminatorKind::InlineAsm { .. } => "InlineAsm",
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 986d2fd..ea1223f 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -9,6 +9,7 @@
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::{self, BasicBlock, BasicBlockData, Terminator, TerminatorKind};
 
+use std::cmp::Ordering;
 use std::ops::{Index, IndexMut};
 
 const ID_SEPARATOR: &str = ",";
@@ -212,8 +213,12 @@
     }
 
     #[inline(always)]
-    pub fn dominators(&self) -> &Dominators<BasicCoverageBlock> {
-        self.dominators.as_ref().unwrap()
+    pub fn rank_partial_cmp(
+        &self,
+        a: BasicCoverageBlock,
+        b: BasicCoverageBlock,
+    ) -> Option<Ordering> {
+        self.dominators.as_ref().unwrap().rank_partial_cmp(a, b)
     }
 }
 
@@ -650,26 +655,6 @@
     let mut backedges = IndexVec::from_elem_n(Vec::<BasicCoverageBlock>::new(), num_bcbs);
 
     // Identify loops by their backedges.
-    //
-    // The computational complexity is bounded by: n(s) x d where `n` is the number of
-    // `BasicCoverageBlock` nodes (the simplified/reduced representation of the CFG derived from the
-    // MIR); `s` is the average number of successors per node (which is most likely less than 2, and
-    // independent of the size of the function, so it can be treated as a constant);
-    // and `d` is the average number of dominators per node.
-    //
-    // The average number of dominators depends on the size and complexity of the function, and
-    // nodes near the start of the function's control flow graph typically have less dominators
-    // than nodes near the end of the CFG. Without doing a detailed mathematical analysis, I
-    // think the resulting complexity has the characteristics of O(n log n).
-    //
-    // The overall complexity appears to be comparable to many other MIR transform algorithms, and I
-    // don't expect that this function is creating a performance hot spot, but if this becomes an
-    // issue, there may be ways to optimize the `dominates` algorithm (as indicated by an
-    // existing `FIXME` comment in that code), or possibly ways to optimize it's usage here, perhaps
-    // by keeping track of results for visited `BasicCoverageBlock`s if they can be used to short
-    // circuit downstream `dominates` checks.
-    //
-    // For now, that kind of optimization seems unnecessarily complicated.
     for (bcb, _) in basic_coverage_blocks.iter_enumerated() {
         for &successor in &basic_coverage_blocks.successors[bcb] {
             if basic_coverage_blocks.dominates(successor, bcb) {
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index bf01b45..74b4b4a 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -2,7 +2,7 @@
 
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::{self, Body, Coverage, CoverageInfo};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 287ae21..d272004 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,4 +1,3 @@
-use super::debug::term_type;
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB};
 
 use itertools::Itertools;
@@ -40,7 +39,7 @@
                     "{}: @{}.{}: {:?}",
                     source_range_no_file(tcx, span),
                     bb.index(),
-                    term_type(&term.kind),
+                    term.kind.name(),
                     term.kind
                 )
             }
@@ -345,7 +344,7 @@
                         // before the dominated equal spans). When later comparing two spans in
                         // order, the first will either dominate the second, or they will have no
                         // dominator relationship.
-                        self.basic_coverage_blocks.dominators().rank_partial_cmp(a.bcb, b.bcb)
+                        self.basic_coverage_blocks.rank_partial_cmp(a.bcb, b.bcb)
                     }
                 } else {
                     // Sort hi() in reverse order so shorter spans are attempted after longer spans.
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 83a3351..90b5893 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -25,7 +25,6 @@
 //! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
 
 use super::counters;
-use super::debug;
 use super::graph;
 use super::spans;
 
@@ -188,12 +187,12 @@
                     | TerminatorKind::Goto { target }
                     | TerminatorKind::InlineAsm { destination: Some(target), .. }
                     | TerminatorKind::Yield { resume: target, .. } => {
-                        format!("{}{:?}:{} -> {:?}", sp, bb, debug::term_type(kind), target)
+                        format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), target)
                     }
                     TerminatorKind::SwitchInt { targets, .. } => {
-                        format!("{}{:?}:{} -> {:?}", sp, bb, debug::term_type(kind), targets)
+                        format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets)
                     }
-                    _ => format!("{}{:?}:{}", sp, bb, debug::term_type(kind)),
+                    _ => format!("{}{:?}:{}", sp, bb, kind.name()),
                 }
             })
             .collect::<Vec<_>>()
@@ -215,7 +214,7 @@
                         "    {:?} [label=\"{:?}: {}\"];\n{}",
                         bb,
                         bb,
-                        debug::term_type(&data.terminator().kind),
+                        data.terminator().kind.name(),
                         mir_body
                             .basic_blocks
                             .successors(bb)
@@ -244,7 +243,7 @@
                         "    {:?} [label=\"{:?}: {}\"];\n{}",
                         bcb,
                         bcb,
-                        debug::term_type(&bcb_data.terminator(mir_body).kind),
+                        bcb_data.terminator(mir_body).kind.name(),
                         basic_coverage_blocks
                             .successors(bcb)
                             .map(|successor| { format!("    {:?} -> {:?};", bcb, successor) })
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
index 1b3ac78..bf5722b 100644
--- a/compiler/rustc_mir_transform/src/ctfe_limit.rs
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -47,7 +47,7 @@
         return false;
     }
     // Check if any of the dominators of the node are also the node's successor.
-    doms.dominators(node).any(|dom| node_data.terminator().successors().any(|succ| succ == dom))
+    node_data.terminator().successors().any(|succ| doms.dominates(succ, node))
 }
 
 fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) {
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 8ee08c5..a133c9d 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -8,7 +8,7 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
+use rustc_middle::mir::{Body, Location, Operand, Place, Terminator, TerminatorKind, RETURN_PLACE};
 use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 
@@ -29,31 +29,31 @@
 }
 
 impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
-    fn visit_local(&mut self, local: Local, mut context: PlaceContext, _: Location) {
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
         // We're only interested in arguments.
-        if local == RETURN_PLACE || local.index() > self.mutable_args.domain_size() {
+        if place.local == RETURN_PLACE || place.local.index() > self.mutable_args.domain_size() {
             return;
         }
 
-        // Replace place contexts that are moves with copies. This is safe in all cases except
-        // function argument position, which we already handled in `visit_terminator()` by using the
-        // ArgumentChecker. See the comment in that method for more details.
-        //
-        // In the future, we might want to move this out into a separate pass, but for now let's
-        // just do it on the fly because that's faster.
-        if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) {
-            context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
-        }
-
-        match context {
-            PlaceContext::MutatingUse(..)
-            | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {
+        let mark_as_mutable = match context {
+            PlaceContext::MutatingUse(..) => {
                 // This is a mutation, so mark it as such.
-                self.mutable_args.insert(local.index() - 1);
+                true
+            }
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) => {
+                // Whether mutating though a `&raw const` is allowed is still undecided, so we
+                // disable any sketchy `readonly` optimizations for now.
+                // But we only need to do this if the pointer would point into the argument.
+                !place.is_indirect()
             }
             PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {
                 // Not mutating, so it's fine.
+                false
             }
+        };
+
+        if mark_as_mutable {
+            self.mutable_args.insert(place.local.index() - 1);
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 594cbd8..746e3d9 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -12,7 +12,7 @@
 pub struct Marker(pub &'static str);
 
 impl<'tcx> MirPass<'tcx> for Marker {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0
     }
 
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index ac1de98..58cc161 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -1,8 +1,8 @@
 use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
 use rustc_middle::mir::*;
 use rustc_middle::query::LocalCrate;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::FFI_UNWIND_CALLS;
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index c914472..891e446 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1397,7 +1397,7 @@
 pub(crate) fn mir_generator_witnesses<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-) -> GeneratorLayout<'tcx> {
+) -> Option<GeneratorLayout<'tcx>> {
     assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
 
     let (body, _) = tcx.mir_promoted(def_id);
@@ -1410,6 +1410,7 @@
     // Get the interior types and substs which typeck computed
     let movable = match *gen_ty.kind() {
         ty::Generator(_, _, movability) => movability == hir::Movability::Movable,
+        ty::Error(_) => return None,
         _ => span_bug!(body.span, "unexpected generator type {}", gen_ty),
     };
 
@@ -1425,7 +1426,7 @@
 
     check_suspend_tys(tcx, &generator_layout, &body);
 
-    generator_layout
+    Some(generator_layout)
 }
 
 impl<'tcx> MirPass<'tcx> for StateTransform {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index ece20d8..1748b1b 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -7,9 +7,9 @@
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
-use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 use rustc_target::spec::abi::Abi;
 
@@ -167,8 +167,20 @@
     ) -> Result<std::ops::Range<BasicBlock>, &'static str> {
         let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
         self.check_codegen_attributes(callsite, callee_attrs)?;
+
+        let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
+        let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
+        let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
+        for arg in args {
+            if !arg.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
+                // We do not allow inlining functions with unsized params. Inlining these functions
+                // could create unsized locals, which are unsound and being phased out.
+                return Err("Call has unsized argument");
+            }
+        }
+
         self.check_mir_is_available(caller_body, &callsite.callee)?;
-        let callee_body = self.tcx.instance_mir(callsite.callee.def);
+        let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?;
         self.check_mir_body(callsite, callee_body, callee_attrs)?;
 
         if !self.tcx.consider_optimizing(|| {
@@ -188,9 +200,6 @@
         // Check call signature compatibility.
         // Normally, this shouldn't be required, but trait normalization failure can create a
         // validation ICE.
-        let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
-        let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
-        let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
         let output_type = callee_body.return_ty();
         if !util::is_subtype(self.tcx, self.param_env, output_type, destination_ty) {
             trace!(?output_type, ?destination_ty);
@@ -541,16 +550,6 @@
                 // Copy the arguments if needed.
                 let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
 
-                let mut expn_data = ExpnData::default(
-                    ExpnKind::Inlined,
-                    callsite.source_info.span,
-                    self.tcx.sess.edition(),
-                    None,
-                    None,
-                );
-                expn_data.def_site = callee_body.span;
-                let expn_data =
-                    self.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx));
                 let mut integrator = Integrator {
                     args: &args,
                     new_locals: Local::new(caller_body.local_decls.len())..,
@@ -562,7 +561,6 @@
                     cleanup_block: unwind,
                     in_cleanup_block: false,
                     tcx: self.tcx,
-                    expn_data,
                     always_live_locals: BitSet::new_filled(callee_body.local_decls.len()),
                 };
 
@@ -946,7 +944,6 @@
     cleanup_block: UnwindAction,
     in_cleanup_block: bool,
     tcx: TyCtxt<'tcx>,
-    expn_data: LocalExpnId,
     always_live_locals: BitSet<Local>,
 }
 
@@ -1032,11 +1029,6 @@
         *scope = self.map_scope(*scope);
     }
 
-    fn visit_span(&mut self, span: &mut Span) {
-        // Make sure that all spans track the fact that they were inlined.
-        *span = span.fresh_expansion(self.expn_data);
-    }
-
     fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
         self.in_cleanup_block = data.is_cleanup;
         self.super_basic_block_data(block, data);
@@ -1128,3 +1120,27 @@
         }
     }
 }
+
+#[instrument(skip(tcx), level = "debug")]
+fn try_instance_mir<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: InstanceDef<'tcx>,
+) -> Result<&'tcx Body<'tcx>, &'static str> {
+    match instance {
+        ty::InstanceDef::DropGlue(_, Some(ty)) => match ty.kind() {
+            ty::Adt(def, substs) => {
+                let fields = def.all_fields();
+                for field in fields {
+                    let field_ty = field.ty(tcx, substs);
+                    if field_ty.has_param() && field_ty.has_projections() {
+                        return Err("cannot build drop shim for polymorphic type");
+                    }
+                }
+
+                Ok(tcx.instance_mir(instance))
+            }
+            _ => Ok(tcx.instance_mir(instance)),
+        },
+        _ => Ok(tcx.instance_mir(instance)),
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 6bff535..e4dc617 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -5,7 +5,6 @@
 use rustc_hir::Mutability;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::ValidityRequirement;
-use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::FieldIdx;
@@ -163,18 +162,6 @@
                     return;
                 }
 
-                // Transmuting a fieldless enum to its repr is a discriminant read
-                if let ty::Adt(adt_def, ..) = operand_ty.kind()
-                    && adt_def.is_enum()
-                    && adt_def.is_payloadfree()
-                    && let Some(place) = operand.place()
-                    && let Some(repr_int) = adt_def.repr().int
-                    && repr_int.to_ty(self.tcx) == *cast_ty
-                {
-                    *rvalue = Rvalue::Discriminant(place);
-                    return;
-                }
-
                 // Transmuting a transparent struct/union to a field's type is a projection
                 if let ty::Adt(adt_def, substs) = operand_ty.kind()
                     && adt_def.repr().transparent()
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 277237a..65864dc 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -34,7 +34,7 @@
     MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo,
     Statement, StatementKind, TerminatorKind, START_BLOCK,
 };
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
index 85b2622..5ce9601 100644
--- a/compiler/rustc_mir_transform/src/nrvo.rs
+++ b/compiler/rustc_mir_transform/src/nrvo.rs
@@ -108,7 +108,7 @@
 
         // If multiple different locals are copied to the return place. We can't pick a
         // single one to rename.
-        if copied_to_return_place.map_or(false, |old| old != returned_local) {
+        if copied_to_return_place.is_some_and(|old| old != returned_local) {
             return None;
         }
 
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index e1b6582..710eed3 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -6,7 +6,7 @@
 
 /// Just like `MirPass`, except it cannot mutate `Body`.
 pub trait MirLint<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
@@ -26,7 +26,7 @@
 where
     T: MirLint<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0.name()
     }
 
@@ -49,7 +49,7 @@
 where
     T: MirPass<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.1.name()
     }
 
@@ -121,7 +121,7 @@
                 validate_body(tcx, body, format!("before pass {}", name));
             }
 
-            pass.run_pass(tcx, body);
+            tcx.sess.time(name, || pass.run_pass(tcx, body));
 
             if dump_enabled {
                 dump_mir_for_pass(tcx, body, &name, true);
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index d1bc9ee..bbd9f76 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -77,11 +77,11 @@
     #[instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!(def_id = ?body.source.def_id());
-        propagate_ssa(tcx, body);
+        while propagate_ssa(tcx, body) {}
     }
 }
 
-fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
     let ssa = SsaLocals::new(body);
 
     let mut replacer = compute_replacement(tcx, body, &ssa);
@@ -94,6 +94,8 @@
     if replacer.any_replacement {
         crate::simplify::remove_unused_definitions(body);
     }
+
+    replacer.any_replacement
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -263,6 +265,7 @@
         targets,
         storage_to_remove,
         allowed_replacements,
+        fully_replacable_locals,
         any_replacement: false,
     };
 
@@ -343,6 +346,7 @@
     storage_to_remove: BitSet<Local>,
     allowed_replacements: FxHashSet<(Local, Location)>,
     any_replacement: bool,
+    fully_replacable_locals: BitSet<Local>,
 }
 
 impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
@@ -350,6 +354,25 @@
         self.tcx
     }
 
+    fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
+        if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
+            && place.projection.is_empty()
+            && let Value::Pointer(target, _) = self.targets[place.local]
+            && target.projection.iter().all(|p| p.can_use_in_debuginfo())
+        {
+            if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
+                *place = Place::from(target.local).project_deeper(rest, self.tcx);
+                self.any_replacement = true;
+            } else if self.fully_replacable_locals.contains(place.local)
+                && let Some(references) = debuginfo.references.checked_add(1)
+            {
+                debuginfo.references = references;
+                *place = target;
+                self.any_replacement = true;
+            }
+        }
+    }
+
     fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
         if place.projection.first() != Some(&PlaceElem::Deref) {
             return;
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 19d07fa..7c47d88 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -2,7 +2,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::*;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 1b96df3..e592193 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -74,7 +74,7 @@
 }
 
 impl<'tcx> MirPass<'tcx> for SimplifyCfg {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         &self.name()
     }
 
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index a7b4536..e8e4246 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -31,11 +31,11 @@
 /// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
 /// actually compute dominators, we can just compare block indices because bb0 is always the first
 /// block, and in any body all other blocks are always dominated by bb0.
-struct SmallDominators {
-    inner: Option<Dominators<BasicBlock>>,
+struct SmallDominators<'a> {
+    inner: Option<&'a Dominators<BasicBlock>>,
 }
 
-impl SmallDominators {
+impl SmallDominators<'_> {
     fn dominates(&self, first: Location, second: Location) -> bool {
         if first.block == second.block {
             first.statement_index <= second.statement_index
@@ -101,14 +101,15 @@
             .retain(|&local| matches!(visitor.assignments[local], Set1::One(_)));
         debug!(?visitor.assignment_order);
 
-        let copy_classes = compute_copy_classes(&mut visitor, body);
-
-        SsaLocals {
+        let mut ssa = SsaLocals {
             assignments: visitor.assignments,
             assignment_order: visitor.assignment_order,
             direct_uses: visitor.direct_uses,
-            copy_classes,
-        }
+            // This is filled by `compute_copy_classes`.
+            copy_classes: IndexVec::default(),
+        };
+        compute_copy_classes(&mut ssa, body);
+        ssa
     }
 
     pub fn num_locals(&self) -> usize {
@@ -197,14 +198,14 @@
     Arg,
 }
 
-struct SsaVisitor {
-    dominators: SmallDominators,
+struct SsaVisitor<'a> {
+    dominators: SmallDominators<'a>,
     assignments: IndexVec<Local, Set1<LocationExtended>>,
     assignment_order: Vec<Local>,
     direct_uses: IndexVec<Local, u32>,
 }
 
-impl<'tcx> Visitor<'tcx> for SsaVisitor {
+impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
     fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) {
         match ctxt {
             PlaceContext::MutatingUse(MutatingUseContext::Projection)
@@ -261,49 +262,54 @@
 }
 
 #[instrument(level = "trace", skip(ssa, body))]
-fn compute_copy_classes(ssa: &mut SsaVisitor, body: &Body<'_>) -> IndexVec<Local, Local> {
+fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
+    let mut direct_uses = std::mem::take(&mut ssa.direct_uses);
     let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len());
 
-    for &local in &ssa.assignment_order {
-        debug!(?local);
-
-        if local == RETURN_PLACE {
-            // `_0` is special, we cannot rename it.
-            continue;
-        }
-
-        // This is not SSA: mark that we don't know the value.
-        debug!(assignments = ?ssa.assignments[local]);
-        let Set1::One(LocationExtended::Plain(loc)) = ssa.assignments[local] else { continue };
-
-        // `loc` must point to a direct assignment to `local`.
-        let Either::Left(stmt) = body.stmt_at(loc) else { bug!() };
-        let Some((_target, rvalue)) = stmt.kind.as_assign() else { bug!() };
-        assert_eq!(_target.as_local(), Some(local));
-
+    for (local, rvalue, _) in ssa.assignments(body) {
         let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
             = rvalue
         else { continue };
 
         let Some(rhs) = place.as_local() else { continue };
-        let Set1::One(_) = ssa.assignments[rhs] else { continue };
+        if !ssa.is_ssa(rhs) {
+            continue;
+        }
 
         // We visit in `assignment_order`, ie. reverse post-order, so `rhs` has been
         // visited before `local`, and we just have to copy the representing local.
-        copies[local] = copies[rhs];
-        ssa.direct_uses[rhs] -= 1;
+        let head = copies[rhs];
+
+        if local == RETURN_PLACE {
+            // `_0` is special, we cannot rename it. Instead, rename the class of `rhs` to
+            // `RETURN_PLACE`. This is only possible if the class head is a temporary, not an
+            // argument.
+            if body.local_kind(head) != LocalKind::Temp {
+                continue;
+            }
+            for h in copies.iter_mut() {
+                if *h == head {
+                    *h = RETURN_PLACE;
+                }
+            }
+        } else {
+            copies[local] = head;
+        }
+        direct_uses[rhs] -= 1;
     }
 
     debug!(?copies);
-    debug!(?ssa.direct_uses);
+    debug!(?direct_uses);
 
     // Invariant: `copies` must point to the head of an equivalence class.
     #[cfg(debug_assertions)]
     for &head in copies.iter() {
         assert_eq!(copies[head], head);
     }
+    debug_assert_eq!(copies[RETURN_PLACE], RETURN_PLACE);
 
-    copies
+    ssa.direct_uses = direct_uses;
+    ssa.copy_classes = copies;
 }
 
 #[derive(Debug)]
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 6cea6a6..fdd47e6 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -1,32 +1,32 @@
-monomorphize_recursion_limit =
-    reached the recursion limit while instantiating `{$shrunk}`
-    .note = `{$def_path_str}` defined here
-
-monomorphize_written_to_path = the full type name has been written to '{$path}'
-
-monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
-
 monomorphize_consider_type_length_limit =
     consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate
 
-monomorphize_fatal_error = {$error_message}
-
-monomorphize_unknown_partition_strategy = unknown partitioning strategy
-
-monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
-
-monomorphize_unused_generic_params = item has unused generic parameters
-
-monomorphize_large_assignments =
-    moving {$size} bytes
-    .label = value moved from here
-    .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
-
 monomorphize_couldnt_dump_mono_stats =
     unexpected error occurred while dumping monomorphization stats: {$error}
 
 monomorphize_encountered_error_while_instantiating =
     the above error was encountered while instantiating `{$formatted_item}`
 
+monomorphize_fatal_error = {$error_message}
+
+monomorphize_large_assignments =
+    moving {$size} bytes
+    .label = value moved from here
+    .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+monomorphize_recursion_limit =
+    reached the recursion limit while instantiating `{$shrunk}`
+    .note = `{$def_path_str}` defined here
+
+monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
+
+monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
+
 monomorphize_unknown_cgu_collection_mode =
     unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
+
+monomorphize_unknown_partition_strategy = unknown partitioning strategy
+
+monomorphize_unused_generic_params = item has unused generic parameters
+
+monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 55c937b..35b154b 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -185,9 +185,9 @@
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
 use rustc_middle::mir::visit::Visitor as MirVisitor;
 use rustc_middle::mir::{self, Local, Location};
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::query::TyCtxtAt;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{
     self, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 7253acf..ecc50c3 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -12,9 +12,9 @@
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir::lang_items::LangItem;
+use rustc_middle::query::{Providers, TyCtxtAt};
 use rustc_middle::traits;
 use rustc_middle::ty::adjustment::CustomCoerceUnsized;
-use rustc_middle::ty::query::{Providers, TyCtxtAt};
 use rustc_middle::ty::{self, Ty};
 
 mod collector;
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 37b7f6b..603b3dd 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -1,3 +1,4 @@
+use std::cmp;
 use std::collections::hash_map::Entry;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -14,10 +15,7 @@
 
 use super::PartitioningCx;
 use crate::collector::InliningMap;
-use crate::partitioning::merging;
-use crate::partitioning::{
-    MonoItemPlacement, Partition, PostInliningPartitioning, PreInliningPartitioning,
-};
+use crate::partitioning::{MonoItemPlacement, Partition, PlacedRootMonoItems};
 
 pub struct DefaultPartitioning;
 
@@ -26,7 +24,7 @@
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
         mono_items: &mut I,
-    ) -> PreInliningPartitioning<'tcx>
+    ) -> PlacedRootMonoItems<'tcx>
     where
         I: Iterator<Item = MonoItem<'tcx>>,
     {
@@ -91,38 +89,120 @@
             codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
         }
 
-        PreInliningPartitioning {
-            codegen_units: codegen_units.into_values().collect(),
-            roots,
-            internalization_candidates,
-        }
+        let codegen_units = codegen_units.into_values().collect();
+        PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
     }
 
     fn merge_codegen_units(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+        codegen_units: &mut Vec<CodegenUnit<'tcx>>,
     ) {
-        merging::merge_codegen_units(cx, initial_partitioning);
+        assert!(cx.target_cgu_count >= 1);
+
+        // Note that at this point in time the `codegen_units` here may not be
+        // in a deterministic order (but we know they're deterministically the
+        // same set). We want this merging to produce a deterministic ordering
+        // of codegen units from the input.
+        //
+        // Due to basically how we've implemented the merging below (merge the
+        // two smallest into each other) we're sure to start off with a
+        // deterministic order (sorted by name). This'll mean that if two cgus
+        // have the same size the stable sort below will keep everything nice
+        // and deterministic.
+        codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+
+        // This map keeps track of what got merged into what.
+        let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
+            codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
+
+        // Merge the two smallest codegen units until the target size is
+        // reached.
+        while codegen_units.len() > cx.target_cgu_count {
+            // Sort small cgus to the back
+            codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
+            let mut smallest = codegen_units.pop().unwrap();
+            let second_smallest = codegen_units.last_mut().unwrap();
+
+            // Move the mono-items from `smallest` to `second_smallest`
+            second_smallest.modify_size_estimate(smallest.size_estimate());
+            for (k, v) in smallest.items_mut().drain() {
+                second_smallest.items_mut().insert(k, v);
+            }
+
+            // Record that `second_smallest` now contains all the stuff that was
+            // in `smallest` before.
+            let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
+            cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
+
+            debug!(
+                "CodegenUnit {} merged into CodegenUnit {}",
+                smallest.name(),
+                second_smallest.name()
+            );
+        }
+
+        let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
+
+        if cx.tcx.sess.opts.incremental.is_some() {
+            // If we are doing incremental compilation, we want CGU names to
+            // reflect the path of the source level module they correspond to.
+            // For CGUs that contain the code of multiple modules because of the
+            // merging done above, we use a concatenation of the names of all
+            // contained CGUs.
+            let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
+                .into_iter()
+                // This `filter` makes sure we only update the name of CGUs that
+                // were actually modified by merging.
+                .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
+                .map(|(current_cgu_name, cgu_contents)| {
+                    let mut cgu_contents: Vec<&str> =
+                        cgu_contents.iter().map(|s| s.as_str()).collect();
+
+                    // Sort the names, so things are deterministic and easy to
+                    // predict. We are sorting primitive `&str`s here so we can
+                    // use unstable sort.
+                    cgu_contents.sort_unstable();
+
+                    (current_cgu_name, cgu_contents.join("--"))
+                })
+                .collect();
+
+            for cgu in codegen_units.iter_mut() {
+                if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
+                    if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
+                        cgu.set_name(Symbol::intern(&new_cgu_name));
+                    } else {
+                        // If we don't require CGU names to be human-readable,
+                        // we use a fixed length hash of the composite CGU name
+                        // instead.
+                        let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
+                        cgu.set_name(Symbol::intern(&new_cgu_name));
+                    }
+                }
+            }
+        } else {
+            // If we are compiling non-incrementally we just generate simple CGU
+            // names containing an index.
+            for (index, cgu) in codegen_units.iter_mut().enumerate() {
+                let numbered_codegen_unit_name =
+                    cgu_name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index));
+                cgu.set_name(numbered_codegen_unit_name);
+            }
+        }
     }
 
     fn place_inlined_mono_items(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: PreInliningPartitioning<'tcx>,
-    ) -> PostInliningPartitioning<'tcx> {
-        let mut new_partitioning = Vec::new();
+        codegen_units: &mut [CodegenUnit<'tcx>],
+        roots: FxHashSet<MonoItem<'tcx>>,
+    ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
         let mut mono_item_placements = FxHashMap::default();
 
-        let PreInliningPartitioning {
-            codegen_units: initial_cgus,
-            roots,
-            internalization_candidates,
-        } = initial_partitioning;
+        let single_codegen_unit = codegen_units.len() == 1;
 
-        let single_codegen_unit = initial_cgus.len() == 1;
-
-        for old_codegen_unit in initial_cgus {
+        for old_codegen_unit in codegen_units.iter_mut() {
             // Collect all items that need to be available in this codegen unit.
             let mut reachable = FxHashSet::default();
             for root in old_codegen_unit.items().keys() {
@@ -174,14 +254,10 @@
                 }
             }
 
-            new_partitioning.push(new_codegen_unit);
+            *old_codegen_unit = new_codegen_unit;
         }
 
-        return PostInliningPartitioning {
-            codegen_units: new_partitioning,
-            mono_item_placements,
-            internalization_candidates,
-        };
+        return mono_item_placements;
 
         fn follow_inlining<'tcx>(
             mono_item: MonoItem<'tcx>,
@@ -201,14 +277,16 @@
     fn internalize_symbols(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        partitioning: &mut PostInliningPartitioning<'tcx>,
+        codegen_units: &mut [CodegenUnit<'tcx>],
+        mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+        internalization_candidates: FxHashSet<MonoItem<'tcx>>,
     ) {
-        if partitioning.codegen_units.len() == 1 {
+        if codegen_units.len() == 1 {
             // Fast path for when there is only one codegen unit. In this case we
             // can internalize all candidates, since there is nowhere else they
             // could be accessed from.
-            for cgu in &mut partitioning.codegen_units {
-                for candidate in &partitioning.internalization_candidates {
+            for cgu in codegen_units {
+                for candidate in &internalization_candidates {
                     cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
                 }
             }
@@ -225,15 +303,13 @@
             }
         });
 
-        let mono_item_placements = &partitioning.mono_item_placements;
-
         // For each internalization candidates in each codegen unit, check if it is
         // accessed from outside its defining codegen unit.
-        for cgu in &mut partitioning.codegen_units {
+        for cgu in codegen_units {
             let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
 
             for (accessee, linkage_and_visibility) in cgu.items_mut() {
-                if !partitioning.internalization_candidates.contains(accessee) {
+                if !internalization_candidates.contains(accessee) {
                     // This item is no candidate for internalizing, so skip it.
                     continue;
                 }
diff --git a/compiler/rustc_monomorphize/src/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs
deleted file mode 100644
index 5c524a1..0000000
--- a/compiler/rustc_monomorphize/src/partitioning/merging.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-use std::cmp;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
-use rustc_span::symbol::Symbol;
-
-use super::PartitioningCx;
-use crate::partitioning::PreInliningPartitioning;
-
-pub fn merge_codegen_units<'tcx>(
-    cx: &PartitioningCx<'_, 'tcx>,
-    initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-) {
-    assert!(cx.target_cgu_count >= 1);
-    let codegen_units = &mut initial_partitioning.codegen_units;
-
-    // Note that at this point in time the `codegen_units` here may not be in a
-    // deterministic order (but we know they're deterministically the same set).
-    // We want this merging to produce a deterministic ordering of codegen units
-    // from the input.
-    //
-    // Due to basically how we've implemented the merging below (merge the two
-    // smallest into each other) we're sure to start off with a deterministic
-    // order (sorted by name). This'll mean that if two cgus have the same size
-    // the stable sort below will keep everything nice and deterministic.
-    codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
-
-    // This map keeps track of what got merged into what.
-    let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
-        codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
-
-    // Merge the two smallest codegen units until the target size is reached.
-    while codegen_units.len() > cx.target_cgu_count {
-        // Sort small cgus to the back
-        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
-        let mut smallest = codegen_units.pop().unwrap();
-        let second_smallest = codegen_units.last_mut().unwrap();
-
-        // Move the mono-items from `smallest` to `second_smallest`
-        second_smallest.modify_size_estimate(smallest.size_estimate());
-        for (k, v) in smallest.items_mut().drain() {
-            second_smallest.items_mut().insert(k, v);
-        }
-
-        // Record that `second_smallest` now contains all the stuff that was in
-        // `smallest` before.
-        let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
-        cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
-
-        debug!(
-            "CodegenUnit {} merged into CodegenUnit {}",
-            smallest.name(),
-            second_smallest.name()
-        );
-    }
-
-    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
-
-    if cx.tcx.sess.opts.incremental.is_some() {
-        // If we are doing incremental compilation, we want CGU names to
-        // reflect the path of the source level module they correspond to.
-        // For CGUs that contain the code of multiple modules because of the
-        // merging done above, we use a concatenation of the names of
-        // all contained CGUs.
-        let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
-            .into_iter()
-            // This `filter` makes sure we only update the name of CGUs that
-            // were actually modified by merging.
-            .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
-            .map(|(current_cgu_name, cgu_contents)| {
-                let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect();
-
-                // Sort the names, so things are deterministic and easy to
-                // predict.
-
-                // We are sorting primitive &strs here so we can use unstable sort
-                cgu_contents.sort_unstable();
-
-                (current_cgu_name, cgu_contents.join("--"))
-            })
-            .collect();
-
-        for cgu in codegen_units.iter_mut() {
-            if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
-                if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
-                    cgu.set_name(Symbol::intern(&new_cgu_name));
-                } else {
-                    // If we don't require CGU names to be human-readable, we
-                    // use a fixed length hash of the composite CGU name
-                    // instead.
-                    let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
-                    cgu.set_name(Symbol::intern(&new_cgu_name));
-                }
-            }
-        }
-    } else {
-        // If we are compiling non-incrementally we just generate simple CGU
-        // names containing an index.
-        for (index, cgu) in codegen_units.iter_mut().enumerate() {
-            cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
-        }
-    }
-}
-
-fn numbered_codegen_unit_name(
-    name_builder: &mut CodegenUnitNameBuilder<'_>,
-    index: usize,
-) -> Symbol {
-    name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
-}
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 993e35c..d0b23ca 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -93,7 +93,6 @@
 //! inlining, even when they are not marked `#[inline]`.
 
 mod default;
-mod merging;
 
 use std::cmp;
 use std::fs::{self, File};
@@ -106,8 +105,8 @@
 use rustc_middle::mir;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{CodegenUnit, Linkage};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
 use rustc_span::symbol::Symbol;
@@ -129,7 +128,7 @@
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
         mono_items: &mut I,
-    ) -> PreInliningPartitioning<'tcx>
+    ) -> PlacedRootMonoItems<'tcx>
     where
         I: Iterator<Item = MonoItem<'tcx>>,
     {
@@ -142,12 +141,10 @@
     fn merge_codegen_units(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+        codegen_units: &mut Vec<CodegenUnit<'tcx>>,
     ) {
         match self {
-            Partitioner::Default(partitioner) => {
-                partitioner.merge_codegen_units(cx, initial_partitioning)
-            }
+            Partitioner::Default(partitioner) => partitioner.merge_codegen_units(cx, codegen_units),
             Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
         }
     }
@@ -155,11 +152,12 @@
     fn place_inlined_mono_items(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: PreInliningPartitioning<'tcx>,
-    ) -> PostInliningPartitioning<'tcx> {
+        codegen_units: &mut [CodegenUnit<'tcx>],
+        roots: FxHashSet<MonoItem<'tcx>>,
+    ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
         match self {
             Partitioner::Default(partitioner) => {
-                partitioner.place_inlined_mono_items(cx, initial_partitioning)
+                partitioner.place_inlined_mono_items(cx, codegen_units, roots)
             }
             Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
         }
@@ -168,48 +166,62 @@
     fn internalize_symbols(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        post_inlining_partitioning: &mut PostInliningPartitioning<'tcx>,
+        codegen_units: &mut [CodegenUnit<'tcx>],
+        mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+        internalization_candidates: FxHashSet<MonoItem<'tcx>>,
     ) {
         match self {
-            Partitioner::Default(partitioner) => {
-                partitioner.internalize_symbols(cx, post_inlining_partitioning)
-            }
+            Partitioner::Default(partitioner) => partitioner.internalize_symbols(
+                cx,
+                codegen_units,
+                mono_item_placements,
+                internalization_candidates,
+            ),
             Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
         }
     }
 }
 
-pub struct PartitioningCx<'a, 'tcx> {
+struct PartitioningCx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     target_cgu_count: usize,
     inlining_map: &'a InliningMap<'tcx>,
 }
 
+pub struct PlacedRootMonoItems<'tcx> {
+    codegen_units: Vec<CodegenUnit<'tcx>>,
+    roots: FxHashSet<MonoItem<'tcx>>,
+    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+}
+
 trait Partition<'tcx> {
     fn place_root_mono_items<I>(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
         mono_items: &mut I,
-    ) -> PreInliningPartitioning<'tcx>
+    ) -> PlacedRootMonoItems<'tcx>
     where
         I: Iterator<Item = MonoItem<'tcx>>;
 
     fn merge_codegen_units(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+        codegen_units: &mut Vec<CodegenUnit<'tcx>>,
     );
 
     fn place_inlined_mono_items(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        initial_partitioning: PreInliningPartitioning<'tcx>,
-    ) -> PostInliningPartitioning<'tcx>;
+        codegen_units: &mut [CodegenUnit<'tcx>],
+        roots: FxHashSet<MonoItem<'tcx>>,
+    ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement>;
 
     fn internalize_symbols(
         &mut self,
         cx: &PartitioningCx<'_, 'tcx>,
-        partitioning: &mut PostInliningPartitioning<'tcx>,
+        codegen_units: &mut [CodegenUnit<'tcx>],
+        mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+        internalization_candidates: FxHashSet<MonoItem<'tcx>>,
     );
 }
 
@@ -225,7 +237,7 @@
     }
 }
 
-pub fn partition<'tcx, I>(
+fn partition<'tcx, I>(
     tcx: TyCtxt<'tcx>,
     mono_items: &mut I,
     max_cgu_count: usize,
@@ -241,44 +253,51 @@
     // In the first step, we place all regular monomorphizations into their
     // respective 'home' codegen unit. Regular monomorphizations are all
     // functions and statics defined in the local crate.
-    let mut initial_partitioning = {
+    let PlacedRootMonoItems { mut codegen_units, roots, internalization_candidates } = {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
         partitioner.place_root_mono_items(cx, mono_items)
     };
 
-    for cgu in &mut initial_partitioning.codegen_units {
+    for cgu in &mut codegen_units {
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
+    debug_dump(tcx, "INITIAL PARTITIONING", &codegen_units);
 
     // Merge until we have at most `max_cgu_count` codegen units.
+    // `merge_codegen_units` is responsible for updating the CGU size
+    // estimates.
     {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
-        partitioner.merge_codegen_units(cx, &mut initial_partitioning);
-        debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
+        partitioner.merge_codegen_units(cx, &mut codegen_units);
+        debug_dump(tcx, "POST MERGING", &codegen_units);
     }
 
     // In the next step, we use the inlining map to determine which additional
     // monomorphizations have to go into each codegen unit. These additional
     // monomorphizations can be drop-glue, functions from external crates, and
     // local functions the definition of which is marked with `#[inline]`.
-    let mut post_inlining = {
+    let mono_item_placements = {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
-        partitioner.place_inlined_mono_items(cx, initial_partitioning)
+        partitioner.place_inlined_mono_items(cx, &mut codegen_units, roots)
     };
 
-    for cgu in &mut post_inlining.codegen_units {
+    for cgu in &mut codegen_units {
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
+    debug_dump(tcx, "POST INLINING", &codegen_units);
 
     // Next we try to make as many symbols "internal" as possible, so LLVM has
     // more freedom to optimize.
     if !tcx.sess.link_dead_code() {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
-        partitioner.internalize_symbols(cx, &mut post_inlining);
+        partitioner.internalize_symbols(
+            cx,
+            &mut codegen_units,
+            mono_item_placements,
+            internalization_candidates,
+        );
     }
 
     let instrument_dead_code =
@@ -286,7 +305,7 @@
 
     if instrument_dead_code {
         assert!(
-            post_inlining.codegen_units.len() > 0,
+            codegen_units.len() > 0,
             "There must be at least one CGU that code coverage data can be generated in."
         );
 
@@ -297,7 +316,7 @@
         // the object file (CGU) containing the dead function stubs is included
         // in the final binary. This will probably require forcing these
         // function symbols to be included via `-u` or `/include` linker args.
-        let mut cgus: Vec<_> = post_inlining.codegen_units.iter_mut().collect();
+        let mut cgus: Vec<_> = codegen_units.iter_mut().collect();
         cgus.sort_by_key(|cgu| cgu.size_estimate());
 
         let dead_code_cgu =
@@ -308,27 +327,17 @@
             } else {
                 // If there are no CGUs that have externally linked items,
                 // then we just pick the first CGU as a fallback.
-                &mut post_inlining.codegen_units[0]
+                &mut codegen_units[0]
             };
         dead_code_cgu.make_code_coverage_dead_code_cgu();
     }
 
     // Finally, sort by codegen unit name, so that we get deterministic results.
-    let PostInliningPartitioning {
-        codegen_units: mut result,
-        mono_item_placements: _,
-        internalization_candidates: _,
-    } = post_inlining;
+    codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 
-    result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+    debug_dump(tcx, "FINAL", &codegen_units);
 
-    result
-}
-
-pub struct PreInliningPartitioning<'tcx> {
-    codegen_units: Vec<CodegenUnit<'tcx>>,
-    roots: FxHashSet<MonoItem<'tcx>>,
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+    codegen_units
 }
 
 /// For symbol internalization, we need to know whether a symbol/mono-item is
@@ -340,39 +349,37 @@
     MultipleCgus,
 }
 
-struct PostInliningPartitioning<'tcx> {
-    codegen_units: Vec<CodegenUnit<'tcx>>,
-    mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-}
-
-fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I)
-where
-    I: Iterator<Item = &'a CodegenUnit<'tcx>>,
-    'tcx: 'a,
-{
+fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
     let dump = move || {
         use std::fmt::Write;
 
+        let num_cgus = cgus.len();
+        let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
+        let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
+        let ratio = max as f64 / min as f64;
+
         let s = &mut String::new();
-        let _ = writeln!(s, "{label}");
+        let _ = writeln!(
+            s,
+            "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
+        );
         for cgu in cgus {
             let _ =
-                writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
+                writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
 
             for (mono_item, linkage) in cgu.items() {
                 let symbol_name = mono_item.symbol_name(tcx).name;
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
 
-                let _ = writeln!(
+                let _ = with_no_trimmed_paths!(writeln!(
                     s,
                     " - {} [{:?}] [{}] estimated size {}",
                     mono_item,
                     linkage,
                     symbol_hash,
                     mono_item.size_estimate(tcx)
-                );
+                ));
             }
 
             let _ = writeln!(s);
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index ddc62d9..88a3e02 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -11,9 +11,9 @@
     visit::{TyContext, Visitor},
     Constant, ConstantKind, Local, LocalDecl, Location,
 };
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self,
-    query::Providers,
     subst::SubstsRef,
     visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
     Const, Ty, TyCtxt, UnusedGenericParams,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 1bbf833..9263394 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -1,230 +1,298 @@
-parse_struct_literal_body_without_path =
-    struct literal body without path
-    .suggestion = you might have forgotten to add the struct literal inside the block
-
-parse_struct_literal_needing_parens =
-    invalid struct literal
-    .suggestion = you might need to surround the struct literal in parentheses
-
-parse_maybe_report_ambiguous_plus =
-    ambiguous `+` in a type
-    .suggestion = use parentheses to disambiguate
-
-parse_maybe_recover_from_bad_type_plus =
-    expected a path on the left-hand side of `+`, not `{$ty}`
-
 parse_add_paren = try adding parentheses
 
-parse_forgot_paren = perhaps you forgot parentheses?
+parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
+    .suggestion = if you meant to call a macro, try
+    .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
 
-parse_expect_path = expected a path
+parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
+    .suggestion = add parentheses to clarify the precedence
 
-parse_maybe_recover_from_bad_qpath_stage_2 =
-    missing angle brackets in associated item path
-    .suggestion = try: `{$ty}`
+parse_array_brackets_instead_of_braces = this is a block expression, not an array
+    .suggestion = to make an array, use square brackets instead of curly braces
 
-parse_incorrect_semicolon =
-    expected item, found `;`
-    .suggestion = remove this semicolon
-    .help = {$name} declarations are not followed by a semicolon
+parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
 
-parse_incorrect_use_of_await =
-    incorrect use of `await`
-    .parentheses_suggestion = `await` is not a method call, remove the parentheses
-    .postfix_suggestion = `await` is a postfix operation
+parse_assoc_lifetime = associated lifetimes are not supported
+    .label = the lifetime is given here
+    .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
 
-parse_in_in_typo =
-    expected iterable, found keyword `in`
-    .suggestion = remove the duplicated `in`
+parse_associated_static_item_not_allowed = associated `static` items are not allowed
 
-parse_invalid_variable_declaration =
-    invalid variable declaration
+parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
 
-parse_switch_mut_let_order =
-    switch the order of `mut` and `let`
-parse_missing_let_before_mut = missing keyword
-parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
-parse_use_let_not_var = write `let` instead of `var` to introduce a new variable
+parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
+    .label = to use `async fn`, switch to Rust 2018 or later
 
-parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
-    .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
-    .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
+parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
+    .suggestion = try switching the order
 
-parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
-    .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
-    .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
-    .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
+parse_attr_after_generic = trailing attribute after generic parameter
+    .label = attributes must go before parameters
 
-parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
-    .suggestion = use `!` to perform bitwise not
+parse_attr_without_generics = attribute without generic parameters
+    .label = attributes are only permitted when preceding parameters
 
-parse_unexpected_if_with_if = unexpected `if` in the condition expression
-    .suggestion = remove the `if`
+parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
+    .label = attributes are not allowed here
 
-parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier
-parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not
-parse_unexpected_token_after_not_logical = use `!` to perform logical negation
-parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not
+parse_bad_assoc_type_bounds = bounds on associated types do not belong here
+    .label = belongs in `where` clause
 
-parse_malformed_loop_label = malformed loop label
-    .suggestion = use the correct loop label format
+parse_bad_item_kind = {$descr} is not supported in {$ctx}
+    .help = consider moving the {$descr} out to a nearby module scope
 
-parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
-    .suggestion = remove the lifetime annotation
-    .label = annotated with lifetime here
+parse_bad_return_type_notation_dotdot =
+    return type notation uses `()` instead of `(..)` for elided arguments
+    .suggestion = remove the `..`
 
-parse_field_expression_with_generic = field expressions cannot have generic arguments
+parse_bad_return_type_notation_output =
+    return type not allowed with return type notation
+    .suggestion = remove the return type
 
-parse_macro_invocation_with_qualified_path = macros cannot use qualified paths
+parse_bare_cr = {$double_quotes ->
+    [true] bare CR not allowed in string, use `\r` instead
+    *[false] character constant must be escaped: `\r`
+    }
+    .escape = escape the character
 
-parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
-    .suggestion_remove_label = consider removing the label
-    .suggestion_enclose_in_block = consider enclosing expression in a block
+parse_bare_cr_in_raw_string = bare CR not allowed in raw string
 
-parse_require_colon_after_labeled_expression = labeled expression must be followed by `:`
-    .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
-    .label = the label
-    .suggestion = add `:` after the label
+parse_binary_float_literal_not_supported = binary float literal is not supported
+parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
 
-parse_do_catch_syntax_removed = found removed `do catch` syntax
-    .note = following RFC #2388, the new non-placeholder syntax is `try`
-    .suggestion = replace with the new syntax
+parse_box_not_pat = expected pattern, found {$descr}
+    .note = `box` is a reserved keyword
+    .suggestion = escape `box` to use it as an identifier
 
-parse_float_literal_requires_integer_part = float literals must have an integer part
-    .suggestion = must have an integer part
+parse_box_syntax_removed = `box_syntax` has been removed
+    .suggestion = use `Box::new()` instead
 
-parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
-    .help = valid widths are 8, 16, 32, 64 and 128
-
-parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
-    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
-    .suggestion = try making the prefix lowercase
-
-parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
-    .label = invalid suffix `{$suffix}`
-    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
-
-parse_invalid_float_literal_width = invalid width `{$width}` for float literal
-    .help = valid widths are 32 and 64
-
-parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
-    .label = invalid suffix `{$suffix}`
-    .help = valid suffixes are `f32` and `f64`
-
-parse_int_literal_too_large = integer literal is too large
-
-parse_missing_semicolon_before_array = expected `;`, found `[`
-    .suggestion = consider adding `;` here
-
-parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
-    .label = the `block` fragment is within this context
-
-parse_expect_dotdot_not_dotdotdot = expected `..`, found `...`
-    .suggestion = use `..` to fill in the rest of the fields
-
-parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition
-    .add_then_block = add a block here
-    .condition_possibly_unfinished = this binary operation is possibly unfinished
-
-parse_if_expression_missing_condition = missing condition for `if` expression
-    .condition_label = expected condition here
-    .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
-
-parse_expected_expression_found_let = expected expression, found `let` statement
-
-parse_expect_eq_instead_of_eqeq = expected `=`, found `==`
-    .suggestion = consider using `=` here
-
-parse_expected_else_block = expected `{"{"}`, found {$first_tok}
-    .label = expected an `if` or a block after this `else`
-    .suggestion = add an `if` if this is the condition of a chained `else if` statement
-
-parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
-    .branch_label = the attributes are attached to this branch
-    .ctx_label = the branch belongs to this `{$ctx}`
-    .suggestion = remove the attributes
-
-parse_missing_in_in_for_loop = missing `in` in `for` loop
-    .use_in_not_of = try using `in` here instead
-    .add_in = try adding `in` here
-
-parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
-    .suggestion = try adding an expression to the `for` loop
-
-parse_loop_else = `{$loop_kind}...else` loops are not supported
-    .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
-    .loop_keyword = `else` is attached to this loop
-
-parse_missing_comma_after_match_arm = expected `,` following `match` arm
-    .suggestion = missing a comma here to end this `match` arm
+parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
 
 parse_catch_after_try = keyword `catch` cannot follow a `try` block
     .help = try using `match` on the result of the `try` block instead
 
+parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
+parse_colon_as_semi = statements are terminated with a semicolon
+    .suggestion = use a semicolon instead
+
 parse_comma_after_base_struct = cannot use a comma after the base struct
     .note = the base struct must always be the last field
     .suggestion = remove this comma
 
-parse_eq_field_init = expected `:`, found `=`
-    .suggestion = replace equals symbol with a colon
-
-parse_dotdotdot = unexpected token: `...`
-    .suggest_exclusive_range = use `..` for an exclusive range
-    .suggest_inclusive_range = or `..=` for an inclusive range
-
-parse_left_arrow_operator = unexpected token: `<-`
-    .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
-
-parse_remove_let = expected pattern, found `let`
-    .suggestion = remove the unnecessary `let` keyword
-
-parse_use_eq_instead = unexpected `==`
-    .suggestion = try using `=` instead
-
-parse_use_empty_block_not_semi = expected { "`{}`" }, found `;`
-    .suggestion = try using { "`{}`" } instead
-
 parse_comparison_interpreted_as_generic =
     `<` is interpreted as a start of generic arguments for `{$type}`, not a comparison
     .label_args = interpreted as generic arguments
     .label_comparison = not interpreted as comparison
     .suggestion = try comparing the cast value
 
-parse_shift_interpreted_as_generic =
-    `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift
-    .label_args = interpreted as generic arguments
-    .label_comparison = not interpreted as shift
-    .suggestion = try shifting the cast value
+parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained
+    .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
+    .sugg_split_comparison = split the comparison into two
+    .sugg_parenthesize = parenthesize the comparison
+parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
+    .suggestion = initialize the variable
+    .help = if you meant to overwrite, remove the `let` binding
+
+parse_const_bounds_missing_tilde = const bounds must start with `~`
+    .suggestion = add `~`
+
+parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
+    .suggestion = enclose the `const` expression in braces
+
+parse_const_global_cannot_be_mutable = const globals cannot be mutable
+    .label = cannot be mutable
+    .suggestion = you might want to declare a static instead
+
+parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
+    .suggestion = remove `let`
+
+parse_cr_doc_comment = bare CR not allowed in {$block ->
+    [true] block doc-comment
+    *[false] doc-comment
+}
+
+parse_default_not_followed_by_item = `default` is not followed by an item
+    .label = the `default` qualifier
+    .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
+
+parse_do_catch_syntax_removed = found removed `do catch` syntax
+    .note = following RFC #2388, the new non-placeholder syntax is `try`
+    .suggestion = replace with the new syntax
+
+parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything
+    .help = doc comments must come before what they document, if a comment was intended use `//`
+    .suggestion = missing comma here
+
+parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
+    .label = doc comments are not allowed here
+
+parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
+    .suggestion = to omit remaining fields, use `..`
+
+parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
+    .suggestion = use `..=` instead
+
+parse_dotdotdot = unexpected token: `...`
+    .suggest_exclusive_range = use `..` for an exclusive range
+    .suggest_inclusive_range = or `..=` for an inclusive range
+
+parse_dotdotdot_rest_pattern = unexpected `...`
+    .label = not a valid pattern
+    .suggestion = for a rest pattern, use `..` instead of `...`
+
+parse_double_colon_in_bound = expected `:` followed by trait or lifetime
+    .suggestion = use single colon
+
+parse_dyn_after_mut = `mut` must precede `dyn`
+    .suggestion = place `mut` before `dyn`
+
+parse_empty_exponent_float = expected at least one digit in exponent
+
+parse_empty_unicode_escape = empty unicode escape
+    .label = this escape must have at least 1 hex digit
+
+parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
+
+parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
+    .suggestion = replace `enum struct` with
+
+parse_eq_field_init = expected `:`, found `=`
+    .suggestion = replace equals symbol with a colon
+
+parse_equals_struct_default = default values on `struct` fields aren't supported
+    .suggestion = remove this unsupported default value
+
+parse_escape_only_char = {$byte ->
+    [true] byte
+    *[false] character
+    } constant must be escaped: `{$escaped_msg}`
+    .escape = escape the character
+
+parse_expect_dotdot_not_dotdotdot = expected `..`, found `...`
+    .suggestion = use `..` to fill in the rest of the fields
+
+parse_expect_eq_instead_of_eqeq = expected `=`, found `==`
+    .suggestion = consider using `=` here
+
+parse_expect_label_found_ident = expected a label, found an identifier
+    .suggestion = labels start with a tick
+
+parse_expect_path = expected a path
+
+parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
+    .label_lhs = interpreted as a pattern, not a binding
+    .label_rhs = also a pattern
+    .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+parse_expected_builtin_ident = expected identifier after `builtin #`
+
+parse_expected_comma_after_pattern_field = expected `,`
+
+parse_expected_else_block = expected `{"{"}`, found {$first_tok}
+    .label = expected an `if` or a block after this `else`
+    .suggestion = add an `if` if this is the condition of a chained `else if` statement
+
+parse_expected_expression_found_let = expected expression, found `let` statement
+
+parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
+    .suggestion = use `Fn` to refer to the trait
+
+parse_expected_identifier = expected identifier
+
+parse_expected_identifier_found_doc_comment = expected identifier, found doc comment
+parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
+parse_expected_identifier_found_keyword = expected identifier, found keyword
+parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
+parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
+parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
+parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
+parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}`
+parse_expected_identifier_found_str = expected identifier, found `{$token}`
+
+parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
+    .suggestion = add `mut` or `const` here
+
+parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
+parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
+parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
+parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
+parse_expected_semi_found_str = expected `;`, found `{$token}`
+
+parse_expected_statement_after_outer_attr = expected statement after outer attribute
+
+parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
+
+parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
+    .label = dash-separated idents are not valid
+    .suggestion = if the original crate name uses dashes you need to use underscores in the code
+
+parse_extern_item_cannot_be_const = extern items cannot be `const`
+    .suggestion = try using a static value
+    .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
+
+parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
+    .suggestion = remove the extra `impl`
+    .note = this is parsed as an `impl Trait` type, but a trait is expected at this position
+
+
+parse_field_expression_with_generic = field expressions cannot have generic arguments
+
+parse_float_literal_requires_integer_part = float literals must have an integer part
+    .suggestion = must have an integer part
+
+parse_float_literal_unsupported_base = {$base} float literal is not supported
+
+parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
+    .label = `async` because of this
+    .suggestion = remove the `async` qualifier
+
+parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
+    .label = `const` because of this
+    .suggestion = remove the `const` qualifier
+
+parse_fn_ptr_with_generics = function pointer types may not have generic parameters
+    .suggestion = consider moving the lifetime {$arity ->
+        [one] parameter
+        *[other] parameters
+    } to {$for_param_list_exists ->
+        [true] the
+        *[false] a
+    } `for` parameter list
+
+parse_forgot_paren = perhaps you forgot parentheses?
 
 parse_found_expr_would_be_stmt = expected expression, found `{$token}`
     .label = expected expression
 
-parse_leading_plus_not_supported = leading `+` is not supported
-    .label = unexpected `+`
-    .suggestion_remove_plus = try removing the `+`
+parse_function_body_equals_expr = function body cannot be `= expression;`
+    .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
 
-parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
-    .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters
-    .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly
+parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
+    .suggestion = surround the type parameters with angle brackets
 
-parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
+parse_generics_in_path = unexpected generic arguments in path
 
-parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
+parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+parse_if_expression_missing_condition = missing condition for `if` expression
+    .condition_label = expected condition here
+    .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
 
-parse_array_brackets_instead_of_braces = this is a block expression, not an array
-    .suggestion = to make an array, use square brackets instead of curly braces
+parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition
+    .add_then_block = add a block here
+    .condition_possibly_unfinished = this binary operation is possibly unfinished
 
-parse_match_arm_body_without_braces = `match` arm body without braces
-    .label_statements = {$num_statements ->
-            [one] this statement is not surrounded by a body
-           *[other] these statements are not surrounded by a body
-        }
-    .label_arrow = while parsing the `match` arm starting here
-    .suggestion_add_braces = surround the {$num_statements ->
-            [one] statement
-           *[other] statements
-        } with a body
-    .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
+parse_in_in_typo =
+    expected iterable, found keyword `in`
+    .suggestion = remove the duplicated `in`
+
+parse_inappropriate_default = {$article} {$descr} cannot be `default`
+    .label = `default` because of this
+    .note = only associated `fn`, `const`, and `type` items can be `default`
 
 parse_inclusive_range_extra_equals = unexpected `=` after inclusive range
     .suggestion_remove_eq = use `..=` instead
@@ -238,16 +306,88 @@
     .suggestion_open_range = use `..` instead
     .note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-parse_struct_literal_not_allowed_here = struct literals are not allowed here
-    .suggestion = surround the struct literal with parentheses
+parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
+    .suggestion = remove the parentheses
+
+parse_incorrect_semicolon =
+    expected item, found `;`
+    .suggestion = remove this semicolon
+    .help = {$name} declarations are not followed by a semicolon
+
+parse_incorrect_use_of_await =
+    incorrect use of `await`
+    .parentheses_suggestion = `await` is not a method call, remove the parentheses
+    .postfix_suggestion = `await` is a postfix operation
+
+parse_incorrect_visibility_restriction = incorrect visibility restriction
+    .help = some possible visibility restrictions are:
+            `pub(crate)`: visible only on the current crate
+            `pub(super)`: visible only in the current module's parent
+            `pub(in path::to::module)`: visible only on the specified path
+    .suggestion = make this visible only to module `{$inner_str}` with `in`
+
+parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+parse_inner_attr_not_permitted = an inner attribute is not permitted in this context
+    .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
+    .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
+
+parse_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute
+    .label_attr = not permitted following an outer attribute
+    .label_prev_attr = previous outer attribute
+    .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
+    .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
+
+parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment
+    .label_attr = not permitted following an outer doc comment
+    .label_prev_doc_comment = previous doc comment
+    .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
+    .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
+
+parse_inner_doc_comment_not_permitted = expected outer doc comment
+    .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+    .suggestion = you might have meant to write a regular comment
+    .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
+    .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
+
+parse_int_literal_too_large = integer literal is too large
+
+parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
+    .label = the `block` fragment is within this context
+
+parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}`
+    .label = {parse_invalid_char_in_escape_msg}
+
+parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
+    [true] numeric character
+    *[false] unicode
+    } escape
+
+parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
+    .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
+    .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
+
+parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
+parse_invalid_digit_literal = invalid digit for a base {$base} literal
+
+parse_invalid_dyn_keyword = invalid `dyn` keyword
+    .help = `dyn` is only needed at the start of a trait `+`-separated list
+    .suggestion = remove this keyword
+
+parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
+parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+    .label = invalid suffix `{$suffix}`
+    .help = valid suffixes are `f32` and `f64`
+
+parse_invalid_float_literal_width = invalid width `{$width}` for float literal
+    .help = valid widths are 32 and 64
+
+parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
+
+parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
+    .help = valid widths are 8, 16, 32, 64 and 128
 
 parse_invalid_interpolated_expression = invalid interpolated expression
 
-parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
-parse_octal_float_literal_not_supported = octal float literal is not supported
-parse_binary_float_literal_not_supported = binary float literal is not supported
-parse_not_supported = not supported
-
 parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
     .label = invalid suffix `{$suffix}`
 
@@ -257,207 +397,129 @@
     .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
     .tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
 
-parse_expected_builtin_ident = expected identifier after `builtin #`
+parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
+    .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
+    .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
+    .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
 
-parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}`
+parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
 
-parse_non_string_abi_literal = non-string ABI literal
-    .suggestion = specify the ABI with a string literal
+parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
+    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    .suggestion = try making the prefix lowercase
+
+parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
+    .label = invalid suffix `{$suffix}`
+    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+parse_invalid_unicode_escape = invalid unicode character escape
+    .label = invalid escape
+    .help = unicode escape must {$surrogate ->
+    [true] not be a surrogate
+    *[false] be at most 10FFFF
+    }
+
+parse_invalid_variable_declaration =
+    invalid variable declaration
+
+parse_kw_bad_case = keyword `{$kw}` is written in the wrong case
+    .suggestion = write it in the correct case
+
+parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item}
+parse_label_unexpected_token = unexpected token
+
+parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
+
+parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
+
+parse_leading_plus_not_supported = leading `+` is not supported
+    .label = unexpected `+`
+    .suggestion_remove_plus = try removing the `+`
+
+parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_`
+parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
+
+parse_left_arrow_operator = unexpected token: `<-`
+    .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
+
+parse_lifetime_after_mut = lifetime must precede `mut`
+    .suggestion = place the lifetime before `mut`
+
+parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
+    .suggestion = remove the lifetime annotation
+    .label = annotated with lifetime here
+
+parse_lone_slash = invalid trailing slash in literal
+    .label = {parse_lone_slash}
+
+parse_loop_else = `{$loop_kind}...else` loops are not supported
+    .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    .loop_keyword = `else` is attached to this loop
+
+parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
+    .suggestion = remove the visibility
+    .help = try adjusting the macro to put `{$vis}` inside the invocation
+
+parse_macro_invocation_with_qualified_path = macros cannot use qualified paths
+
+parse_macro_name_remove_bang = macro names aren't followed by a `!`
+    .suggestion = remove the `!`
+
+parse_macro_rules_missing_bang = expected `!` after `macro_rules`
+    .suggestion = add a `!`
+
+parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
+    .suggestion = try exporting the macro
+
+parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
+    .suggestion = missing condition and attribute
+    .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+parse_malformed_loop_label = malformed loop label
+    .suggestion = use the correct loop label format
+
+parse_match_arm_body_without_braces = `match` arm body without braces
+    .label_statements = {$num_statements ->
+            [one] this statement is not surrounded by a body
+           *[other] these statements are not surrounded by a body
+        }
+    .label_arrow = while parsing the `match` arm starting here
+    .suggestion_add_braces = surround the {$num_statements ->
+            [one] statement
+           *[other] statements
+        } with a body
+    .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
+
+parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
+    .suggestion = replace `fn` with `impl` here
+
+parse_maybe_recover_from_bad_qpath_stage_2 =
+    missing angle brackets in associated item path
+    .suggestion = try: `{$ty}`
+
+parse_maybe_recover_from_bad_type_plus =
+    expected a path on the left-hand side of `+`, not `{$ty}`
+
+parse_maybe_report_ambiguous_plus =
+    ambiguous `+` in a type
+    .suggestion = use parentheses to disambiguate
+
+parse_meta_bad_delim = wrong meta list delimiters
+parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
 
 parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}`
     .label_unmatched = mismatched closing delimiter
     .label_opening_candidate = closing delimiter possibly meant for this
     .label_unclosed = unclosed delimiter
 
-parse_incorrect_visibility_restriction = incorrect visibility restriction
-    .help = some possible visibility restrictions are:
-            `pub(crate)`: visible only on the current crate
-            `pub(super)`: visible only in the current module's parent
-            `pub(in path::to::module)`: visible only on the specified path
-    .suggestion = make this visible only to module `{$inner_str}` with `in`
+parse_missing_comma_after_match_arm = expected `,` following `match` arm
+    .suggestion = missing a comma here to end this `match` arm
 
-parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
+parse_missing_const_type = missing type for `{$kind}` item
+    .suggestion = provide a type for the item
 
-parse_expected_statement_after_outer_attr = expected statement after outer attribute
-
-parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything
-    .help = doc comments must come before what they document, if a comment was intended use `//`
-    .suggestion = missing comma here
-
-parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
-    .suggestion = remove `let`
-
-parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
-parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
-parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
-
-parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
-    .suggestion = initialize the variable
-    .help = if you meant to overwrite, remove the `let` binding
-
-parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
-    .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
-
-parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
-
-parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item}
-parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style
-
-parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment
-    .label_attr = not permitted following an outer doc comment
-    .label_prev_doc_comment = previous doc comment
-    .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
-    .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
-
-parse_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute
-    .label_attr = not permitted following an outer attribute
-    .label_prev_attr = previous outer attribute
-    .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
-    .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
-
-parse_inner_attr_not_permitted = an inner attribute is not permitted in this context
-    .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this}
-    .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer}
-
-parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
-parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
-
-parse_inner_doc_comment_not_permitted = expected outer doc comment
-    .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
-    .suggestion = you might have meant to write a regular comment
-    .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
-    .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
-
-parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
-parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
-parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}`
-parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
-parse_expected_identifier_found_str = expected identifier, found `{$token}`
-
-parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
-parse_expected_identifier_found_keyword = expected identifier, found keyword
-parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
-parse_expected_identifier_found_doc_comment = expected identifier, found doc comment
-parse_expected_identifier = expected identifier
-
-parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
-
-parse_sugg_remove_comma = remove this comma
-parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
-
-parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
-parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
-parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
-parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
-parse_expected_semi_found_str = expected `;`, found `{$token}`
-
-parse_sugg_change_this_to_semi = change this to `;`
-parse_sugg_add_semi = add `;` here
-parse_label_unexpected_token = unexpected token
-
-parse_unmatched_angle_brackets = {$num_extra_brackets ->
-        [one] unmatched angle bracket
-       *[other] unmatched angle brackets
-    }
-    .suggestion = {$num_extra_brackets ->
-            [one] remove extra angle bracket
-           *[other] remove extra angle brackets
-        }
-
-parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
-    .suggestion = surround the type parameters with angle brackets
-
-parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained
-    .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
-    .sugg_split_comparison = split the comparison into two
-    .sugg_parenthesize = parenthesize the comparison
-parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
-
-parse_question_mark_in_type = invalid `?` in type
-    .label = `?` is only allowed on expressions, not types
-    .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
-
-parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
-    .suggestion = remove parentheses in `for` loop
-
-parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
-    .label = doc comments are not allowed here
-
-parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type
-    .label = attributes are not allowed here
-
-parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
-    .suggestion = give this argument a name or use an underscore to ignore it
-
-parse_self_param_not_first = unexpected `self` parameter in function
-    .label = must be the first parameter of an associated function
-
-parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
-    .suggestion = enclose the `const` expression in braces
-
-parse_unexpected_const_param_declaration = unexpected `const` parameter declaration
-    .label = expected a `const` expression, not a parameter declaration
-    .suggestion = `const` parameters must be declared for the `impl`
-
-parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
-    .suggestion = the `const` keyword is only needed in the definition of the type
-
-parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
-    .suggestion = try switching the order
-
-parse_double_colon_in_bound = expected `:` followed by trait or lifetime
-    .suggestion = use single colon
-
-parse_fn_ptr_with_generics = function pointer types may not have generic parameters
-    .suggestion = consider moving the lifetime {$arity ->
-        [one] parameter
-        *[other] parameters
-    } to {$for_param_list_exists ->
-        [true] the
-        *[false] a
-    } `for` parameter list
-
-parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
-
-parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
-    .suggestion = replace `fn` with `impl` here
-
-parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
-    .suggestion = use `Fn` to refer to the trait
-
-parse_path_single_colon = path separator must be a double colon
-    .suggestion = use a double colon instead
-
-parse_colon_as_semi = statements are terminated with a semicolon
-    .suggestion = use a semicolon instead
-
-parse_type_ascription_removed =
-    if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
-
-parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
-    .label = unexpected where clause
-    .name_label = while parsing this tuple struct
-    .body_label = the struct body
-    .suggestion = move the body before the where clause
-
-parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
-    .label = to use `async fn`, switch to Rust 2018 or later
-
-parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
-
-parse_self_argument_pointer = cannot pass `self` by raw pointer
-    .label = cannot pass `self` by raw pointer
-
-parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
-    .label = the visibility
-    .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
-
-parse_default_not_followed_by_item = `default` is not followed by an item
-    .label = the `default` qualifier
-    .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
-
-parse_missing_struct_for_struct_definition = missing `struct` for struct definition
-    .suggestion = add `struct` here to parse `{$ident}` as a public struct
+parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
+    .suggestion = try adding an expression to the `for` loop
 
 parse_missing_fn_for_function_definition = missing `fn` for function definition
     .suggestion = add `fn` here to parse `{$ident}` as a public function
@@ -465,181 +527,29 @@
 parse_missing_fn_for_method_definition = missing `fn` for method definition
     .suggestion = add `fn` here to parse `{$ident}` as a public method
 
-parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
-    .suggestion = if you meant to call a macro, try
-    .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
+parse_missing_for_in_trait_impl = missing `for` in a trait impl
+    .suggestion = add `for` here
+
+parse_missing_in_in_for_loop = missing `in` in `for` loop
+    .use_in_not_of = try using `in` here instead
+    .add_in = try adding `in` here
+
+parse_missing_let_before_mut = missing keyword
+parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym}
+    .suggestion = add `+`
+
+parse_missing_semicolon_before_array = expected `;`, found `[`
+    .suggestion = consider adding `;` here
+
+parse_missing_struct_for_struct_definition = missing `struct` for struct definition
+    .suggestion = add `struct` here to parse `{$ident}` as a public struct
 
 parse_missing_trait_in_trait_impl = missing trait in a trait impl
     .suggestion_add_trait = add a trait here
     .suggestion_remove_for = for an inherent impl, drop this `for`
 
-parse_missing_for_in_trait_impl = missing `for` in a trait impl
-    .suggestion = add `for` here
-
-parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
-
-parse_non_item_in_item_list = non-item in item list
-    .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
-    .label_list_start = item list starts here
-    .label_non_item = non-item starts here
-    .label_list_end = item list ends here
-    .suggestion_remove_semicolon = consider removing this semicolon
-
-parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
-
-parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
-parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
-
-parse_associated_static_item_not_allowed = associated `static` items are not allowed
-
-parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
-    .label = dash-separated idents are not valid
-    .suggestion = if the original crate name uses dashes you need to use underscores in the code
-
-parse_extern_item_cannot_be_const = extern items cannot be `const`
-    .suggestion = try using a static value
-    .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
-
-parse_const_global_cannot_be_mutable = const globals cannot be mutable
-    .label = cannot be mutable
-    .suggestion = you might want to declare a static instead
-
-parse_missing_const_type = missing type for `{$kind}` item
-    .suggestion = provide a type for the item
-
-parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
-    .suggestion = replace `enum struct` with
-
-parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
-parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
-parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
-parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
-parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
-parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
-
-parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
-    .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
-
-parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
-    .label = lifetime parameters cannot have default values
-
-parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
-    .label = previous `where` clause starts here
-    .suggestion = consider joining the two `where` clauses into one
-
-parse_nonterminal_expected_item_keyword = expected an item keyword
-parse_nonterminal_expected_statement = expected a statement
-parse_nonterminal_expected_ident = expected ident, found `{$token}`
-parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
-
-parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
-parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
-parse_sugg_remove_leading_vert_in_pattern = remove the `|`
-parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
-
-parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
-
-parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
-    .suggestion = remove the `||`
-
-parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
-
-parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
-    .suggestion = use a single `|` to separate multiple alternative patterns
-
-parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
-    .suggestion = remove the `{$token}`
-
-parse_dotdotdot_rest_pattern = unexpected `...`
-    .label = not a valid pattern
-    .suggestion = for a rest pattern, use `..` instead of `...`
-
-parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
-    .label_pattern = pattern on the left, should be on the right
-    .label_binding = binding on the right, should be on the left
-    .suggestion = switch the order
-
-parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
-    .label_lhs = interpreted as a pattern, not a binding
-    .label_rhs = also a pattern
-    .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
-
-parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
-    .suggestion = add parentheses to clarify the precedence
-
-parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
-    .suggestion = remove the lifetime
-
-parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
-    .suggestion = try switching the order
-
-parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
-    .suggestion = add `mut` to each binding
-parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
-    .suggestion = remove the `mut` prefix
-parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
-
-parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
-    .suggestion = remove the additional `mut`s
-
-parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
-    .suggestion = use `..=` instead
-
-parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
-
-parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
-    .suggestion = to omit remaining fields, use `..`
-
-parse_expected_comma_after_pattern_field = expected `,`
-
-parse_return_types_use_thin_arrow = return types are denoted using `->`
-    .suggestion = use `->` instead
-
-parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
-
-parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
-    .suggestion = add `mut` or `const` here
-
-parse_lifetime_after_mut = lifetime must precede `mut`
-    .suggestion = place the lifetime before `mut`
-
-parse_dyn_after_mut = `mut` must precede `dyn`
-    .suggestion = place `mut` before `dyn`
-
-parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
-    .label = `const` because of this
-    .suggestion = remove the `const` qualifier
-
-parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
-    .label = `async` because of this
-    .suggestion = remove the `async` qualifier
-
-parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
-
-parse_invalid_dyn_keyword = invalid `dyn` keyword
-    .help = `dyn` is only needed at the start of a trait `+`-separated list
-    .suggestion = remove this keyword
-
-parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
-parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
-parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
-
-parse_unexpected_token_after_dot = unexpected token: `{$actual}`
-
-parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
-
-parse_cr_doc_comment = bare CR not allowed in {$block ->
-    [true] block doc-comment
-    *[false] doc-comment
-}
-
-parse_no_digits_literal = no valid digits found for number
-
-parse_invalid_digit_literal = invalid digit for a base {$base} literal
-
-parse_empty_exponent_float = expected at least one digit in exponent
-
-parse_float_literal_unsupported_base = {$base} float literal is not supported
+parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds
+    .suggestion = remove the `{$sigil}`
 
 parse_more_than_one_char = character literal may only contain one codepoint
     .followed_by = this `{$chr}` is followed by the combining {$len ->
@@ -654,73 +564,238 @@
         *[false] `str`
         } literal, use double quotes
 
+parse_multiple_skipped_lines = multiple lines skipped by escaped newline
+    .label = skipping everything up to and including this point
+
+parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
+    .label = previous `where` clause starts here
+    .suggestion = consider joining the two `where` clauses into one
+
+parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
+    .suggestion = add `mut` to each binding
+parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
+    .suggestion = remove the `mut` prefix
+parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
+
+parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
+    .suggestion = consider creating a new `{$kw_str}` definition instead of nesting
+
+parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
+
 parse_no_brace_unicode_escape = incorrect unicode escape sequence
     .label = {parse_no_brace_unicode_escape}
     .use_braces = format of unicode escape sequences uses braces
     .format_of_unicode = format of unicode escape sequences is `\u{"{...}"}`
 
-parse_invalid_unicode_escape = invalid unicode character escape
-    .label = invalid escape
-    .help = unicode escape must {$surrogate ->
-    [true] not be a surrogate
-    *[false] be at most 10FFFF
-    }
+parse_no_digits_literal = no valid digits found for number
 
-parse_escape_only_char = {$byte ->
-    [true] byte
-    *[false] character
-    } constant must be escaped: `{$escaped_msg}`
-    .escape = escape the character
+parse_non_item_in_item_list = non-item in item list
+    .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
+    .label_list_start = item list starts here
+    .label_non_item = non-item starts here
+    .label_list_end = item list ends here
+    .suggestion_remove_semicolon = consider removing this semicolon
 
-parse_bare_cr = {$double_quotes ->
-    [true] bare CR not allowed in string, use `\r` instead
-    *[false] character constant must be escaped: `\r`
-    }
-    .escape = escape the character
+parse_non_string_abi_literal = non-string ABI literal
+    .suggestion = specify the ABI with a string literal
 
-parse_bare_cr_in_raw_string = bare CR not allowed in raw string
+parse_nonterminal_expected_ident = expected ident, found `{$token}`
+parse_nonterminal_expected_item_keyword = expected an item keyword
+parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
 
-parse_too_short_hex_escape = numeric character escape is too short
+parse_nonterminal_expected_statement = expected a statement
+parse_not_supported = not supported
 
-parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}`
-    .label = {parse_invalid_char_in_escape_msg}
+parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
 
-parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
-    [true] numeric character
-    *[false] unicode
-    } escape
+parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
 
+parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
+
+parse_octal_float_literal_not_supported = octal float literal is not supported
+parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
+parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
 parse_out_of_range_hex_escape = out of range hex escape
     .label = must be a character in the range [\x00-\x7f]
 
-parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_`
-parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
+parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
+
+parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
+    .branch_label = the attributes are attached to this branch
+    .ctx_label = the branch belongs to this `{$ctx}`
+    .suggestion = remove the attributes
 
 parse_overlong_unicode_escape = overlong unicode escape
     .label = must have at most 6 hex digits
 
+parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
+    .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters
+    .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly
+
+parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
+    .suggestion = remove the parentheses
+
+parse_path_single_colon = path separator must be a double colon
+    .suggestion = use a double colon instead
+
+parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
+    .suggestion = give this argument a name or use an underscore to ignore it
+
+parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
+    .label_pattern = pattern on the left, should be on the right
+    .label_binding = binding on the right, should be on the left
+    .suggestion = switch the order
+
+parse_question_mark_in_type = invalid `?` in type
+    .label = `?` is only allowed on expressions, not types
+    .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
+
+parse_recover_import_as_use = expected item, found {$token_name}
+    .suggestion = items are imported using the `use` keyword
+
+parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
+    .suggestion = try switching the order
+
+parse_remove_let = expected pattern, found `let`
+    .suggestion = remove the unnecessary `let` keyword
+
+parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
+    .suggestion = remove the additional `mut`s
+
+parse_require_colon_after_labeled_expression = labeled expression must be followed by `:`
+    .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
+    .label = the label
+    .suggestion = add `:` after the label
+
+parse_return_types_use_thin_arrow = return types are denoted using `->`
+    .suggestion = use `->` instead
+
+parse_self_argument_pointer = cannot pass `self` by raw pointer
+    .label = cannot pass `self` by raw pointer
+
+parse_self_param_not_first = unexpected `self` parameter in function
+    .label = must be the first parameter of an associated function
+
+parse_shift_interpreted_as_generic =
+    `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift
+    .label_args = interpreted as generic arguments
+    .label_comparison = not interpreted as shift
+    .suggestion = try shifting the cast value
+
+parse_single_colon_import_path = expected `::`, found `:`
+    .suggestion = use double colon
+    .note = import paths are delimited using `::`
+
+parse_single_colon_struct_type = found single colon in a struct field type path
+    .suggestion = write a path separator here
+
+parse_struct_literal_body_without_path =
+    struct literal body without path
+    .suggestion = you might have forgotten to add the struct literal inside the block
+
+parse_struct_literal_needing_parens =
+    invalid struct literal
+    .suggestion = you might need to surround the struct literal in parentheses
+
+parse_struct_literal_not_allowed_here = struct literals are not allowed here
+    .suggestion = surround the struct literal with parentheses
+
+parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
+    .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding
+
+parse_sugg_add_semi = add `;` here
+parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style
+
+parse_sugg_change_this_to_semi = change this to `;`
+parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier
+
+parse_sugg_remove_comma = remove this comma
+parse_sugg_remove_leading_vert_in_pattern = remove the `|`
+parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+
+parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
+
+parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
+
+parse_switch_mut_let_order =
+    switch the order of `mut` and `let`
+parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
+
+parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
+    .suggestion = use `!` to perform bitwise not
+
+parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}
+
+parse_too_short_hex_escape = numeric character escape is too short
+
+parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
+    .suggestion = remove the `{$token}`
+
+parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
+parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
+
+parse_type_ascription_removed =
+    if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
+
 parse_unclosed_unicode_escape = unterminated unicode escape
     .label = missing a closing `{"}"}`
     .terminate = terminate the unicode escape
 
+parse_underscore_literal_suffix = underscore literal suffix is not allowed
+
+parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
+    .suggestion = the `const` keyword is only needed in the definition of the type
+
+parse_unexpected_const_param_declaration = unexpected `const` parameter declaration
+    .label = expected a `const` expression, not a parameter declaration
+    .suggestion = `const` parameters must be declared for the `impl`
+
+parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
+    .label = lifetime parameters cannot have default values
+
+parse_unexpected_if_with_if = unexpected `if` in the condition expression
+    .suggestion = remove the `if`
+
+parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
+    .suggestion = remove the lifetime
+
+parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
+    .suggestion = remove parentheses in `for` loop
+
+parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
+    .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
+
+parse_unexpected_token_after_dot = unexpected token: `{$actual}`
+
+parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
+    .suggestion_remove_label = consider removing the label
+    .suggestion_enclose_in_block = consider enclosing expression in a block
+
+parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier
+parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not
+parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not
+
+parse_unexpected_token_after_not_logical = use `!` to perform logical negation
+parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
+parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
+parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
+parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
+
+parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
+parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
+parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
+    .suggestion = remove the `||`
+
+parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
+    .suggestion = use a single `|` to separate multiple alternative patterns
+
 parse_unicode_escape_in_byte = unicode escape in byte string
     .label = {parse_unicode_escape_in_byte}
     .help = unicode escape sequences cannot be used as a byte or in a byte string
 
-parse_empty_unicode_escape = empty unicode escape
-    .label = this escape must have at least 1 hex digit
-
-parse_zero_chars = empty character literal
-    .label = {parse_zero_chars}
-
-parse_lone_slash = invalid trailing slash in literal
-    .label = {parse_lone_slash}
-
-parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
-    .label = {parse_unskipped_whitespace}
-
-parse_multiple_skipped_lines = multiple lines skipped by escaped newline
-    .label = skipping everything up to and including this point
+parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}`
 
 parse_unknown_prefix = prefix `{$prefix}` is unknown
     .label = unknown prefix
@@ -728,8 +803,6 @@
     .suggestion_br = use `br` for a raw byte string
     .suggestion_whitespace = consider inserting whitespace here
 
-parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}
-
 parse_unknown_start_of_token = unknown start of token: {$escaped}
     .sugg_quotes = Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not
     .sugg_other = Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not
@@ -739,94 +812,6 @@
         *[other] {$repeats} more times
     }
 
-parse_box_syntax_removed = `box_syntax` has been removed
-    .suggestion = use `Box::new()` instead
-
-parse_bad_return_type_notation_output =
-    return type not allowed with return type notation
-    .suggestion = remove the return type
-
-parse_bad_return_type_notation_dotdot =
-    return type notation uses `()` instead of `(..)` for elided arguments
-    .suggestion = remove the `..`
-
-parse_bad_assoc_type_bounds = bounds on associated types do not belong here
-    .label = belongs in `where` clause
-
-parse_attr_after_generic = trailing attribute after generic parameter
-    .label = attributes must go before parameters
-
-parse_attr_without_generics = attribute without generic parameters
-    .label = attributes are only permitted when preceding parameters
-
-parse_where_generics = generic parameters on `where` clauses are reserved for future use
-    .label = currently unsupported
-
-parse_generics_in_path = unexpected generic arguments in path
-
-parse_assoc_lifetime = associated lifetimes are not supported
-    .label = the lifetime is given here
-    .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
-
-parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
-
-parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds
-    .suggestion = remove the `{$sigil}`
-
-parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
-    .suggestion = remove the parentheses
-
-parse_const_bounds_missing_tilde = const bounds must start with `~`
-    .suggestion = add `~`
-
-parse_underscore_literal_suffix = underscore literal suffix is not allowed
-
-parse_expect_label_found_ident = expected a label, found an identifier
-    .suggestion = labels start with a tick
-
-parse_inappropriate_default = {$article} {$descr} cannot be `default`
-    .label = `default` because of this
-    .note = only associated `fn`, `const`, and `type` items can be `default`
-
-parse_recover_import_as_use = expected item, found {$token_name}
-    .suggestion = items are imported using the `use` keyword
-
-parse_single_colon_import_path = expected `::`, found `:`
-    .suggestion = use double colon
-    .note = import paths are delimited using `::`
-
-parse_bad_item_kind = {$descr} is not supported in {$ctx}
-    .help = consider moving the {$descr} out to a nearby module scope
-
-parse_single_colon_struct_type = found single colon in a struct field type path
-    .suggestion = write a path separator here
-
-parse_equals_struct_default = default values on `struct` fields aren't supported
-    .suggestion = remove this unsupported default value
-
-parse_macro_rules_missing_bang = expected `!` after `macro_rules`
-    .suggestion = add a `!`
-
-parse_macro_name_remove_bang = macro names aren't followed by a `!`
-    .suggestion = remove the `!`
-
-parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
-    .suggestion = try exporting the macro
-
-parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
-    .suggestion = remove the visibility
-    .help = try adjusting the macro to put `{$vis}` inside the invocation
-
-parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
-    .suggestion = consider creating a new `{$kw_str}` definition instead of nesting
-
-parse_function_body_equals_expr = function body cannot be `= expression;`
-    .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
-
-parse_box_not_pat = expected pattern, found {$descr}
-    .note = `box` is a reserved keyword
-    .suggestion = escape `box` to use it as an identifier
-
 parse_unmatched_angle = unmatched angle {$plural ->
     [true] brackets
     *[false] bracket
@@ -836,19 +821,39 @@
     *[false] bracket
     }
 
-parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym}
-    .suggestion = add `+`
+parse_unmatched_angle_brackets = {$num_extra_brackets ->
+        [one] unmatched angle bracket
+       *[other] unmatched angle brackets
+    }
+    .suggestion = {$num_extra_brackets ->
+            [one] remove extra angle bracket
+           *[other] remove extra angle brackets
+        }
 
-parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
-    .suggestion = remove the parentheses
+parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
+    .label = {parse_unskipped_whitespace}
 
-parse_kw_bad_case = keyword `{$kw}` is written in the wrong case
-    .suggestion = write it in the correct case
+parse_use_empty_block_not_semi = expected { "`{}`" }, found `;`
+    .suggestion = try using { "`{}`" } instead
 
-parse_meta_bad_delim = wrong meta list delimiters
-parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
-parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
+parse_use_eq_instead = unexpected `==`
+    .suggestion = try using `=` instead
 
-parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
-    .suggestion = missing condition and attribute
-    .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
+parse_use_let_not_var = write `let` instead of `var` to introduce a new variable
+
+parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
+    .label = the visibility
+    .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
+
+parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
+    .label = unexpected where clause
+    .name_label = while parsing this tuple struct
+    .body_label = the struct body
+    .suggestion = move the body before the where clause
+
+parse_where_generics = generic parameters on `where` clauses are reserved for future use
+    .label = currently unsupported
+
+parse_zero_chars = empty character literal
+    .label = {parse_zero_chars}
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index b6aeaf3..84494ea 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1520,6 +1520,16 @@
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_extra_impl_keyword_in_trait_impl)]
+pub(crate) struct ExtraImplKeywordInTraitImpl {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
+    pub extra_impl_kw: Span,
+    #[note]
+    pub impl_trait_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_bounds_not_allowed_on_trait_aliases)]
 pub(crate) struct BoundsNotAllowedOnTraitAliases {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 51e9048..c6e6b46 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -662,7 +662,7 @@
                 &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                 prefix_span,
                 ast::CRATE_NODE_ID,
-                &format!("prefix `{prefix}` is unknown"),
+                format!("prefix `{prefix}` is unknown"),
                 BuiltinLintDiagnostics::ReservedPrefix(prefix_span),
             );
         }
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index b0ab0f1..1e6ac54 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -72,7 +72,7 @@
     // Therefore, the absence of a literal `cfg` or `cfg_attr` guarantees that
     // we don't need to do any eager expansion.
     attrs.iter().any(|attr| {
-        attr.ident().map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
+        attr.ident().is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
     })
 }
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 3002f23..c145403 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -238,6 +238,7 @@
 
 impl<'a> Parser<'a> {
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -844,7 +845,7 @@
         //
         // `x.foo::<u32>>>(3)`
         let parsed_angle_bracket_args =
-            segment.args.as_ref().map_or(false, |args| args.is_angle_bracketed());
+            segment.args.as_ref().is_some_and(|args| args.is_angle_bracketed());
 
         debug!(
             "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
@@ -2609,7 +2610,7 @@
         let TyKind::Path(qself, path) = &ty.kind else { return Ok(()) };
         let qself_position = qself.as_ref().map(|qself| qself.position);
         for (i, segments) in path.segments.windows(2).enumerate() {
-            if qself_position.map(|pos| i < pos).unwrap_or(false) {
+            if qself_position.is_some_and(|pos| i < pos) {
                 continue;
             }
             if let [a, b] = segments {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 887e155..1b28f3c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1180,11 +1180,15 @@
                         self.restore_snapshot(snapshot);
                         let close_paren = self.prev_token.span;
                         let span = lo.to(close_paren);
+                        // filter shorthand fields
+                        let fields: Vec<_> =
+                            fields.into_iter().filter(|field| !field.is_shorthand).collect();
+
                         if !fields.is_empty() &&
                             // `token.kind` should not be compared here.
                             // This is because the `snapshot.token.kind` is treated as the same as
                             // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different.
-                            self.span_to_snippet(close_paren).map_or(false, |snippet| snippet == ")")
+                            self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
                         {
                             let mut replacement_err = errors::ParenthesesWithStructFields {
                                 span,
@@ -2074,7 +2078,7 @@
                     // Therefore, `token.kind` should not be compared here.
                     if snapshot
                         .span_to_snippet(snapshot.token.span)
-                        .map_or(false, |snippet| snippet == "]") =>
+                        .is_ok_and(|snippet| snippet == "]") =>
                 {
                     return Err(errors::MissingSemicolonBeforeArray {
                         open_delim: open_delim_span,
@@ -2769,7 +2773,7 @@
                 // We might have a `=>` -> `=` or `->` typo (issue #89396).
                 if TokenKind::FatArrow
                     .similar_tokens()
-                    .map_or(false, |similar_tokens| similar_tokens.contains(&this.token.kind))
+                    .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind))
                 {
                     err.span_suggestion(
                         this.token.span,
@@ -3055,7 +3059,7 @@
                 }
             };
 
-            let is_shorthand = parsed_field.as_ref().map_or(false, |f| f.is_shorthand);
+            let is_shorthand = parsed_field.as_ref().is_some_and(|f| f.is_shorthand);
             // A shorthand field can be turned into a full field with `:`.
             // We should point this out.
             self.check_or_expected(!is_shorthand, TokenType::Token(token::Colon));
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index e6d0f9f..cd779b0 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -453,6 +453,8 @@
         //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
         //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
         //     `<` const                - generic const parameter
+        //     `<` IDENT `?`            - RECOVERY for `impl<T ?Bound` missing a `:`, meant to
+        //                                avoid the `T?` to `Option<T>` recovery for types.
         // The only truly ambiguous case is
         //     `<` IDENT `>` `::` IDENT ...
         // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
@@ -463,6 +465,9 @@
                 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
                     && self.look_ahead(start + 2, |t| {
                         matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
+                        // Recovery-only branch -- this could be removed,
+                        // since it only affects diagnostics currently.
+                            || matches!(t.kind, token::Question)
                     })
                 || self.is_keyword_ahead(start + 1, &[kw::Const]))
     }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 840cfe9..3783ec4 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -603,10 +603,24 @@
                 let path = match ty_first.kind {
                     // This notably includes paths passed through `ty` macro fragments (#46438).
                     TyKind::Path(None, path) => path,
-                    _ => {
-                        self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
-                            span: ty_first.span,
-                        });
+                    other => {
+                        if let TyKind::ImplTrait(_, bounds) = other
+                            && let [bound] = bounds.as_slice()
+                        {
+                            // Suggest removing extra `impl` keyword:
+                            // `impl<T: Default> impl Default for Wrapper<T>`
+                            //                   ^^^^^
+                            let extra_impl_kw = ty_first.span.until(bound.span());
+                            self.sess
+                                .emit_err(errors::ExtraImplKeywordInTraitImpl {
+                                    extra_impl_kw,
+                                    impl_trait_span: ty_first.span
+                                });
+                        } else {
+                            self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
+                                span: ty_first.span,
+                            });
+                        }
                         err_path(ty_first.span)
                     }
                 };
@@ -685,7 +699,7 @@
                         // ```
                         && self
                             .span_to_snippet(self.prev_token.span)
-                            .map_or(false, |snippet| snippet == "}")
+                            .is_ok_and(|snippet| snippet == "}")
                         && self.token.kind == token::Semi;
                     let mut semicolon_span = self.token.span;
                     if !is_unnecessary_semicolon {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 0327912..54f9fc5 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -40,7 +40,8 @@
 
     /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of whether
     /// or not we have attributes
-    pub(crate) fn parse_stmt_without_recovery(
+    // Public for `cfg_eval` macro expansion.
+    pub fn parse_stmt_without_recovery(
         &mut self,
         capture_semi: bool,
         force_collect: ForceCollect,
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 982c461..928fdce 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -186,7 +186,7 @@
         suggestions.push(code);
     }
     if should_warn(name) {
-        sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, &msg);
+        sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg);
     } else {
         sess.span_diagnostic
             .struct_span_err(span, error_msg)
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 4068015..7f9222d 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -4,440 +4,66 @@
 -passes_see_issue =
     see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information
 
-passes_incorrect_do_not_recommend_location =
-    `#[do_not_recommend]` can only be placed on trait implementations
-
-passes_outer_crate_level_attr =
-    crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-
-passes_inner_crate_level_attr =
-    crate-level attribute should be in the root module
-
-passes_ignored_attr_with_macro =
-    `#[{$sym}]` is ignored on struct fields, match arms and macro defs
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "80564")}
-
-passes_ignored_attr =
-    `#[{$sym}]` is ignored on struct fields and match arms
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "80564")}
-
-passes_inline_ignored_function_prototype =
-    `#[inline]` is ignored on function prototypes
-
-passes_inline_ignored_constants =
-    `#[inline]` is ignored on constants
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "65833")}
-
-passes_inline_not_fn_or_closure =
-    attribute should be applied to function or closure
-    .label = not a function or closure
-
-passes_no_coverage_ignored_function_prototype =
-    `#[no_coverage]` is ignored on function prototypes
-
-passes_no_coverage_propagate =
-    `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
-
-passes_no_coverage_fn_defn =
-    `#[no_coverage]` may only be applied to function definitions
-
-passes_no_coverage_not_coverable =
-    `#[no_coverage]` must be applied to coverable code
-    .label = not coverable code
-
-passes_should_be_applied_to_fn =
-    attribute should be applied to a function definition
-    .label = {$on_crate ->
-        [true] cannot be applied to crates
-        *[false] not a function definition
-    }
-
-passes_naked_tracked_caller =
-    cannot use `#[track_caller]` with `#[naked]`
-
-passes_should_be_applied_to_struct_enum =
-    attribute should be applied to a struct or enum
-    .label = not a struct or enum
-
-passes_should_be_applied_to_trait =
-    attribute should be applied to a trait
-    .label = not a trait
-
-passes_target_feature_on_statement =
-    {passes_should_be_applied_to_fn}
-    .warn = {-passes_previously_accepted}
-    .label = {passes_should_be_applied_to_fn.label}
-
-passes_should_be_applied_to_static =
-    attribute should be applied to a static
-    .label = not a static
-
-passes_doc_expect_str =
-    doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
-
-passes_doc_alias_empty =
-    {$attr_str} attribute cannot have empty value
-
-passes_doc_alias_bad_char =
-    {$char_} character isn't allowed in {$attr_str}
-
-passes_doc_alias_start_end =
-    {$attr_str} cannot start or end with ' '
-
-passes_doc_alias_bad_location =
-    {$attr_str} isn't allowed on {$location}
-
-passes_doc_alias_not_an_alias =
-    {$attr_str} is the same as the item's name
-
-passes_doc_alias_duplicated = doc alias is duplicated
-    .label = first defined here
-
-passes_doc_alias_not_string_literal =
-    `#[doc(alias("a"))]` expects string literals
-
-passes_doc_alias_malformed =
-    doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
-
-passes_doc_keyword_empty_mod =
-    `#[doc(keyword = "...")]` should be used on empty modules
-
-passes_doc_keyword_not_mod =
-    `#[doc(keyword = "...")]` should be used on modules
-
-passes_doc_keyword_invalid_ident =
-    `{$doc_keyword}` is not a valid identifier
-
-passes_doc_fake_variadic_not_valid =
-    `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
-
-passes_doc_keyword_only_impl =
-    `#[doc(keyword = "...")]` should be used on impl blocks
-
-passes_doc_inline_conflict_first =
-    this attribute...
-
-passes_doc_inline_conflict_second =
-    {"."}..conflicts with this attribute
-
-passes_doc_inline_conflict =
-    conflicting doc inlining attributes
-    .help = remove one of the conflicting attributes
-
-passes_doc_inline_only_use =
-    this attribute can only be applied to a `use` item
-    .label = only applicable on `use` items
-    .not_a_use_item_label = not a `use` item
-    .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
-
-passes_doc_attr_not_crate_level =
-    `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
-
-passes_attr_crate_level =
-    this attribute can only be applied at the crate level
-    .suggestion = to apply to the crate, use an inner attribute
-    .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
-
-passes_doc_test_unknown =
-    unknown `doc(test)` attribute `{$path}`
-
-passes_doc_test_takes_list =
-    `#[doc(test(...)]` takes a list of attributes
-
-passes_doc_cfg_hide_takes_list =
-    `#[doc(cfg_hide(...)]` takes a list of attributes
-
-passes_doc_test_unknown_any =
-    unknown `doc` attribute `{$path}`
-
-passes_doc_test_unknown_spotlight =
-    unknown `doc` attribute `{$path}`
-    .note = `doc(spotlight)` was renamed to `doc(notable_trait)`
-    .suggestion = use `notable_trait` instead
-    .no_op_note = `doc(spotlight)` is now a no-op
-
-passes_doc_test_unknown_include =
-    unknown `doc` attribute `{$path}`
-    .suggestion = use `doc = include_str!` instead
-
-passes_doc_invalid =
-    invalid `doc` attribute
-
-passes_pass_by_value =
-    `pass_by_value` attribute should be applied to a struct, enum or type alias
-    .label = is not a struct, enum or type alias
-
-passes_allow_incoherent_impl =
-    `rustc_allow_incoherent_impl` attribute should be applied to impl items.
-    .label = the only currently supported targets are inherent methods
-
-passes_has_incoherent_inherent_impl =
-    `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
-    .label = only adts, extern types and traits are supported
-
-passes_both_ffi_const_and_pure =
-    `#[ffi_const]` function cannot be `#[ffi_pure]`
-
-passes_ffi_pure_invalid_target =
-    `#[ffi_pure]` may only be used on foreign functions
-
-passes_ffi_const_invalid_target =
-    `#[ffi_const]` may only be used on foreign functions
-
-passes_ffi_returns_twice_invalid_target =
-    `#[ffi_returns_twice]` may only be used on foreign functions
-
-passes_must_use_async =
-    `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
-    .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
-
-passes_must_use_no_effect =
-    `#[must_use]` has no effect when applied to {$article} {$target}
-
-passes_must_not_suspend =
-    `must_not_suspend` attribute should be applied to a struct, enum, or trait
-    .label = is not a struct, enum, or trait
-
-passes_cold =
-    {passes_should_be_applied_to_fn}
-    .warn = {-passes_previously_accepted}
-    .label = {passes_should_be_applied_to_fn.label}
-
-passes_link =
-    attribute should be applied to an `extern` block with non-Rust ABI
-    .warn = {-passes_previously_accepted}
-    .label = not an `extern` block
-
-passes_link_name =
-    attribute should be applied to a foreign function or static
-    .warn = {-passes_previously_accepted}
-    .label = not a foreign function or static
-    .help = try `#[link(name = "{$value}")]` instead
-
-passes_no_link =
-    attribute should be applied to an `extern crate` item
-    .label = not an `extern crate` item
-
-passes_export_name =
-    attribute should be applied to a free function, impl method or static
-    .label = not a free function, impl method or static
-
-passes_rustc_layout_scalar_valid_range_not_struct =
-    attribute should be applied to a struct
-    .label = not a struct
-
-passes_rustc_layout_scalar_valid_range_arg =
-    expected exactly one integer literal argument
-
-passes_rustc_legacy_const_generics_only =
-    #[rustc_legacy_const_generics] functions must only have const generics
-    .label = non-const generic parameter
-
-passes_rustc_legacy_const_generics_index =
-    #[rustc_legacy_const_generics] must have one index for each generic parameter
-    .label = generic parameters
-
-passes_rustc_legacy_const_generics_index_exceed =
-    index exceeds number of arguments
-    .label = there {$arg_count ->
-        [one] is
-        *[other] are
-    } only {$arg_count} {$arg_count ->
-        [one] argument
-        *[other] arguments
-    }
-
-passes_rustc_legacy_const_generics_index_negative =
-    arguments should be non-negative integers
-
-passes_rustc_dirty_clean =
-    attribute requires -Z query-dep-graph to be enabled
-
-passes_link_section =
-    attribute should be applied to a function or static
-    .warn = {-passes_previously_accepted}
-    .label = not a function or static
-
-passes_no_mangle_foreign =
-    `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
-    .warn = {-passes_previously_accepted}
-    .label = foreign {$foreign_item_kind}
-    .note = symbol names in extern blocks are not mangled
-    .suggestion = remove this attribute
-
-passes_no_mangle =
-    attribute should be applied to a free function, impl method or static
-    .warn = {-passes_previously_accepted}
-    .label = not a free function, impl method or static
-
-passes_repr_ident =
-    meta item in `repr` must be an identifier
-
-passes_repr_conflicting =
-    conflicting representation hints
-
-passes_used_static =
-    attribute must be applied to a `static` variable
-
-passes_used_compiler_linker =
-    `used(compiler)` and `used(linker)` can't be used together
-
-passes_allow_internal_unstable =
-    attribute should be applied to a macro
-    .label = not a macro
-
-passes_debug_visualizer_placement =
-    attribute should be applied to a module
-
-passes_debug_visualizer_invalid =
-    invalid argument
-    .note_1 = expected: `natvis_file = "..."`
-    .note_2 = OR
-    .note_3 = expected: `gdb_script_file = "..."`
-
-passes_debug_visualizer_unreadable =
-    couldn't read {$file}: {$error}
-
-passes_rustc_allow_const_fn_unstable =
-    attribute should be applied to `const fn`
-    .label = not a `const fn`
-
-passes_rustc_std_internal_symbol =
-    attribute should be applied to functions or statics
-    .label = not a function or static
-
-passes_const_trait =
-    attribute should be applied to a trait
-
-passes_stability_promotable =
-    attribute cannot be applied to an expression
-
-passes_deprecated =
-    attribute is ignored here
-
-passes_macro_use =
-    `#[{$name}]` only has an effect on `extern crate` and modules
-
-passes_macro_export =
-    `#[macro_export]` only has an effect on macro definitions
-
-passes_plugin_registrar =
-    `#[plugin_registrar]` only has an effect on functions
-
-passes_unused_empty_lints_note =
-    attribute `{$name}` with an empty list has no effect
-
-passes_unused_no_lints_note =
-    attribute `{$name}` without any lints has no effect
-
-passes_unused_default_method_body_const_note =
-    `default_method_body_is_const` has been replaced with `#[const_trait]` on traits
-
-passes_unused =
-    unused attribute
-    .suggestion = remove this attribute
-
-passes_non_exported_macro_invalid_attrs =
-    attribute should be applied to function or closure
-    .label = not a function or closure
-
-passes_unused_duplicate =
-    unused attribute
-    .suggestion = remove this attribute
-    .note = attribute also specified here
-    .warn = {-passes_previously_accepted}
-
-passes_unused_multiple =
-    multiple `{$name}` attributes
-    .suggestion = remove this attribute
-    .note = attribute also specified here
-
-passes_rustc_lint_opt_ty =
-    `#[rustc_lint_opt_ty]` should be applied to a struct
-    .label = not a struct
-
-passes_rustc_lint_opt_deny_field_access =
-    `#[rustc_lint_opt_deny_field_access]` should be applied to a field
-    .label = not a field
-
-passes_link_ordinal =
-    attribute should be applied to a foreign function or static
-    .label = not a foreign function or static
-
-passes_collapse_debuginfo =
-    `collapse_debuginfo` attribute should be applied to macro definitions
-    .label = not a macro definition
-
-passes_deprecated_annotation_has_no_effect =
-    this `#[deprecated]` annotation has no effect
-    .suggestion = remove the unnecessary deprecation attribute
-
-passes_unknown_external_lang_item =
-    unknown external lang item: `{$lang_item}`
-
-passes_missing_panic_handler =
-    `#[panic_handler]` function required, but not found
-
-passes_missing_lang_item =
-    language item required, but not found: `{$name}`
-    .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
-    .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
-
-passes_lang_item_on_incorrect_target =
-    `{$name}` language item must be applied to a {$expected_target}
-    .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
-
-passes_unknown_lang_item =
-    definition of an unknown language item: `{$name}`
-    .label = definition of unknown language item `{$name}`
-
-passes_invalid_attr_at_crate_level =
-    `{$name}` attribute cannot be used at crate level
-    .suggestion = perhaps you meant to use an outer attribute
-
-passes_duplicate_diagnostic_item_in_crate =
-    duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
-    .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
-
-passes_diagnostic_item_first_defined =
-    the diagnostic item is first defined here
-
 passes_abi =
     abi: {$abi}
 
 passes_align =
     align: {$align}
 
-passes_size =
-    size: {$size}
+passes_allow_incoherent_impl =
+    `rustc_allow_incoherent_impl` attribute should be applied to impl items.
+    .label = the only currently supported targets are inherent methods
 
-passes_homogeneous_aggregate =
-    homogeneous_aggregate: {$homogeneous_aggregate}
+passes_allow_internal_unstable =
+    attribute should be applied to a macro
+    .label = not a macro
 
-passes_layout_of =
-    layout_of({$normalized_ty}) = {$ty_layout}
+passes_attr_application_enum =
+    attribute should be applied to an enum
+    .label = not an enum
 
-passes_unrecognized_field =
-    unrecognized field name `{$name}`
+passes_attr_application_struct =
+    attribute should be applied to a struct
+    .label = not a struct
 
-passes_layout =
-    layout error: {$layout_error}
+passes_attr_application_struct_enum_function_method_union =
+    attribute should be applied to a struct, enum, function, associated function, or union
+    .label = not a struct, enum, function, associated function, or union
 
-passes_feature_stable_twice =
-    feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
+passes_attr_application_struct_enum_union =
+    attribute should be applied to a struct, enum, or union
+    .label = not a struct, enum, or union
 
-passes_feature_previously_declared =
-    feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
+passes_attr_application_struct_union =
+    attribute should be applied to a struct or union
+    .label = not a struct or union
 
-passes_expr_not_allowed_in_context =
-    {$expr} is not allowed in a `{$context}`
+passes_attr_crate_level =
+    this attribute can only be applied at the crate level
+    .suggestion = to apply to the crate, use an inner attribute
+    .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
 
-passes_const_impl_const_trait =
-    const `impl`s must be for traits marked with `#[const_trait]`
-    .note = this trait must be annotated with `#[const_trait]`
+passes_attr_only_in_functions =
+    `{$attr}` attribute can only be used on functions
+
+passes_attr_only_on_main =
+    `{$attr}` attribute can only be used on `fn main()`
+
+passes_attr_only_on_root_main =
+    `{$attr}` attribute can only be used on root `fn main()`
+
+passes_both_ffi_const_and_pure =
+    `#[ffi_const]` function cannot be `#[ffi_pure]`
+
+passes_break_inside_async_block =
+    `{$name}` inside of an `async` block
+    .label = cannot `{$name}` inside of an `async` block
+    .async_block_label = enclosing `async` block
+
+passes_break_inside_closure =
+    `{$name}` inside of a closure
+    .label = cannot `{$name}` inside of a closure
+    .closure_label = enclosing closure
 
 passes_break_non_loop =
     `break` with value from a `{$kind}` loop
@@ -446,105 +72,170 @@
     .suggestion = use `break` on its own without a value inside this `{$kind}` loop
     .break_expr_suggestion = alternatively, you might have meant to use the available loop label
 
+passes_cannot_inline_naked_function =
+    naked functions cannot be inlined
+
+passes_cannot_stabilize_deprecated =
+    an API can't be stabilized after it is deprecated
+    .label = invalid version
+    .item = the stability attribute annotates this item
+
+passes_change_fields_to_be_of_unit_type =
+    consider changing the { $num ->
+      [one] field
+     *[other] fields
+    } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num ->
+      [one] field
+     *[other] fields
+    }
+
+passes_cold =
+    {passes_should_be_applied_to_fn}
+    .warn = {-passes_previously_accepted}
+    .label = {passes_should_be_applied_to_fn.label}
+
+passes_collapse_debuginfo =
+    `collapse_debuginfo` attribute should be applied to macro definitions
+    .label = not a macro definition
+
+passes_const_impl_const_trait =
+    const `impl`s must be for traits marked with `#[const_trait]`
+    .note = this trait must be annotated with `#[const_trait]`
+
+passes_const_trait =
+    attribute should be applied to a trait
+
 passes_continue_labeled_block =
     `continue` pointing to a labeled block
     .label = labeled blocks cannot be `continue`'d
     .block_label = labeled block the `continue` points to
 
-passes_break_inside_closure =
-    `{$name}` inside of a closure
-    .label = cannot `{$name}` inside of a closure
-    .closure_label = enclosing closure
+passes_dead_codes =
+    { $multiple ->
+      *[true] multiple {$descr}s are
+       [false] { $num ->
+         [one] {$descr} {$name_list} is
+        *[other] {$descr}s {$name_list} are
+       }
+    } never {$participle}
 
-passes_break_inside_async_block =
-    `{$name}` inside of an `async` block
-    .label = cannot `{$name}` inside of an `async` block
-    .async_block_label = enclosing `async` block
+passes_debug_visualizer_invalid =
+    invalid argument
+    .note_1 = expected: `natvis_file = "..."`
+    .note_2 = OR
+    .note_3 = expected: `gdb_script_file = "..."`
 
-passes_outside_loop =
-    `{$name}` outside of a loop{$is_break ->
-        [true] {" or labeled block"}
-        *[false] {""}
-    }
-    .label = cannot `{$name}` outside of a loop{$is_break ->
-        [true] {" or labeled block"}
-        *[false] {""}
-    }
+passes_debug_visualizer_placement =
+    attribute should be applied to a module
 
-passes_unlabeled_in_labeled_block =
-    unlabeled `{$cf_type}` inside of a labeled block
-    .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
+passes_debug_visualizer_unreadable =
+    couldn't read {$file}: {$error}
 
-passes_unlabeled_cf_in_while_condition =
-    `break` or `continue` with no label in the condition of a `while` loop
-    .label = unlabeled `{$cf_type}` in the condition of a `while` loop
+passes_deprecated =
+    attribute is ignored here
 
-passes_cannot_inline_naked_function =
-    naked functions cannot be inlined
+passes_deprecated_annotation_has_no_effect =
+    this `#[deprecated]` annotation has no effect
+    .suggestion = remove the unnecessary deprecation attribute
 
-passes_undefined_naked_function_abi =
-    Rust ABI is unsupported in naked functions
+passes_deprecated_attribute =
+    deprecated attribute must be paired with either stable or unstable attribute
 
-passes_no_patterns =
-    patterns not allowed in naked function parameters
+passes_diagnostic_item_first_defined =
+    the diagnostic item is first defined here
 
-passes_params_not_allowed =
-    referencing function parameters is not allowed in naked functions
-    .help = follow the calling convention in asm block to use parameters
+passes_doc_alias_bad_char =
+    {$char_} character isn't allowed in {$attr_str}
 
-passes_naked_functions_asm_block =
-    naked functions must contain a single asm block
-    .label_multiple_asm = multiple asm blocks are unsupported in naked functions
-    .label_non_asm = non-asm is unsupported in naked functions
+passes_doc_alias_bad_location =
+    {$attr_str} isn't allowed on {$location}
 
-passes_naked_functions_operands =
-    only `const` and `sym` operands are supported in naked functions
+passes_doc_alias_duplicated = doc alias is duplicated
+    .label = first defined here
 
-passes_naked_functions_asm_options =
-    asm options unsupported in naked functions: {$unsupported_options}
+passes_doc_alias_empty =
+    {$attr_str} attribute cannot have empty value
 
-passes_naked_functions_must_use_noreturn =
-    asm in naked functions must use `noreturn` option
-    .suggestion = consider specifying that the asm block is responsible for returning from the function
+passes_doc_alias_malformed =
+    doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
 
-passes_attr_only_on_main =
-    `{$attr}` attribute can only be used on `fn main()`
+passes_doc_alias_not_an_alias =
+    {$attr_str} is the same as the item's name
 
-passes_attr_only_on_root_main =
-    `{$attr}` attribute can only be used on root `fn main()`
+passes_doc_alias_not_string_literal =
+    `#[doc(alias("a"))]` expects string literals
 
-passes_attr_only_in_functions =
-    `{$attr}` attribute can only be used on functions
+passes_doc_alias_start_end =
+    {$attr_str} cannot start or end with ' '
 
-passes_multiple_rustc_main =
-    multiple functions with a `#[rustc_main]` attribute
-    .first = first `#[rustc_main]` function
-    .additional = additional `#[rustc_main]` function
+passes_doc_attr_not_crate_level =
+    `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
 
-passes_multiple_start_functions =
-    multiple `start` functions
-    .label = multiple `start` functions
-    .previous = previous `#[start]` function here
+passes_doc_cfg_hide_takes_list =
+    `#[doc(cfg_hide(...)]` takes a list of attributes
 
-passes_extern_main =
-    the `main` function cannot be declared in an `extern` block
+passes_doc_expect_str =
+    doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
 
-passes_unix_sigpipe_values =
-    valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+passes_doc_fake_variadic_not_valid =
+    `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
 
-passes_no_main_function =
-    `main` function not found in crate `{$crate_name}`
-    .here_is_main = here is a function named `main`
-    .one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level
-    .consider_moving_main = consider moving the `main` function definitions
-    .main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename ->
-        [true] {" "}(in `{$filename}`)
-        *[false] {""}
-    }
-    .consider_adding_main_to_file = consider adding a `main` function to `{$filename}`
-    .consider_adding_main_at_crate = consider adding a `main` function at the crate level
-    .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
-    .non_function_main = non-function item at `crate::main` is found
+passes_doc_inline_conflict =
+    conflicting doc inlining attributes
+    .help = remove one of the conflicting attributes
+
+passes_doc_inline_conflict_first =
+    this attribute...
+
+passes_doc_inline_conflict_second =
+    {"."}..conflicts with this attribute
+
+passes_doc_inline_only_use =
+    this attribute can only be applied to a `use` item
+    .label = only applicable on `use` items
+    .not_a_use_item_label = not a `use` item
+    .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
+
+passes_doc_invalid =
+    invalid `doc` attribute
+
+passes_doc_keyword_empty_mod =
+    `#[doc(keyword = "...")]` should be used on empty modules
+
+passes_doc_keyword_invalid_ident =
+    `{$doc_keyword}` is not a valid identifier
+
+passes_doc_keyword_not_mod =
+    `#[doc(keyword = "...")]` should be used on modules
+
+passes_doc_keyword_only_impl =
+    `#[doc(keyword = "...")]` should be used on impl blocks
+
+passes_doc_test_takes_list =
+    `#[doc(test(...)]` takes a list of attributes
+
+passes_doc_test_unknown =
+    unknown `doc(test)` attribute `{$path}`
+
+passes_doc_test_unknown_any =
+    unknown `doc` attribute `{$path}`
+
+passes_doc_test_unknown_include =
+    unknown `doc` attribute `{$path}`
+    .suggestion = use `doc = include_str!` instead
+
+passes_doc_test_unknown_spotlight =
+    unknown `doc` attribute `{$path}`
+    .note = `doc(spotlight)` was renamed to `doc(notable_trait)`
+    .suggestion = use `notable_trait` instead
+    .no_op_note = `doc(spotlight)` is now a no-op
+
+passes_duplicate_diagnostic_item_in_crate =
+    duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
+    .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
+
+passes_duplicate_feature_err =
+    the feature `{$feature}` has already been declared
 
 passes_duplicate_lang_item =
     found duplicate lang item `{$lang_item_name}`
@@ -576,6 +267,66 @@
     .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
     .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
 
+passes_export_name =
+    attribute should be applied to a free function, impl method or static
+    .label = not a free function, impl method or static
+
+passes_expr_not_allowed_in_context =
+    {$expr} is not allowed in a `{$context}`
+
+passes_extern_main =
+    the `main` function cannot be declared in an `extern` block
+
+passes_feature_only_on_nightly =
+    `#![feature]` may not be used on the {$release_channel} release channel
+
+passes_feature_previously_declared =
+    feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
+
+passes_feature_stable_twice =
+    feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
+
+passes_ffi_const_invalid_target =
+    `#[ffi_const]` may only be used on foreign functions
+
+passes_ffi_pure_invalid_target =
+    `#[ffi_pure]` may only be used on foreign functions
+
+passes_ffi_returns_twice_invalid_target =
+    `#[ffi_returns_twice]` may only be used on foreign functions
+
+passes_has_incoherent_inherent_impl =
+    `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
+    .label = only adts, extern types and traits are supported
+
+passes_homogeneous_aggregate =
+    homogeneous_aggregate: {$homogeneous_aggregate}
+
+passes_ignored_attr =
+    `#[{$sym}]` is ignored on struct fields and match arms
+    .warn = {-passes_previously_accepted}
+    .note = {-passes_see_issue(issue: "80564")}
+
+passes_ignored_attr_with_macro =
+    `#[{$sym}]` is ignored on struct fields, match arms and macro defs
+    .warn = {-passes_previously_accepted}
+    .note = {-passes_see_issue(issue: "80564")}
+
+passes_ignored_derived_impls =
+    `{$name}` has {$trait_list_len ->
+      [one] a derived impl
+     *[other] derived impls
+    } for the {$trait_list_len ->
+      [one] trait {$trait_list}, but this is
+     *[other] traits {$trait_list}, but these are
+    } intentionally ignored during dead code analysis
+
+passes_implied_feature_not_exist =
+    feature `{$implied_by}` implying `{$feature}` does not exist
+
+passes_incorrect_do_not_recommend_location =
+    `#[do_not_recommend]` can only be placed on trait implementations
+
 passes_incorrect_target =
     `{$name}` language item must be applied to a {$kind} with {$at_least ->
         [true] at least {$num}
@@ -589,11 +340,189 @@
         *[other] arguments
     }
 
-passes_useless_assignment =
-    useless assignment of {$is_field_assign ->
-        [true] field
-        *[false] variable
-    } of type `{$ty}` to itself
+passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
+    .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
+
+passes_inline_ignored_constants =
+    `#[inline]` is ignored on constants
+    .warn = {-passes_previously_accepted}
+    .note = {-passes_see_issue(issue: "65833")}
+
+passes_inline_ignored_function_prototype =
+    `#[inline]` is ignored on function prototypes
+
+passes_inline_not_fn_or_closure =
+    attribute should be applied to function or closure
+    .label = not a function or closure
+
+passes_inner_crate_level_attr =
+    crate-level attribute should be in the root module
+
+passes_invalid_attr_at_crate_level =
+    `{$name}` attribute cannot be used at crate level
+    .suggestion = perhaps you meant to use an outer attribute
+
+passes_invalid_deprecation_version =
+    invalid deprecation version found
+    .label = invalid deprecation version
+    .item = the stability attribute annotates this item
+
+passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
+
+passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
+
+passes_invalid_stability =
+    invalid stability version found
+    .label = invalid stability version
+    .item = the stability attribute annotates this item
+
+passes_lang_item_on_incorrect_target =
+    `{$name}` language item must be applied to a {$expected_target}
+    .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
+
+passes_layout =
+    layout error: {$layout_error}
+
+passes_layout_of =
+    layout_of({$normalized_ty}) = {$ty_layout}
+
+passes_link =
+    attribute should be applied to an `extern` block with non-Rust ABI
+    .warn = {-passes_previously_accepted}
+    .label = not an `extern` block
+
+passes_link_name =
+    attribute should be applied to a foreign function or static
+    .warn = {-passes_previously_accepted}
+    .label = not a foreign function or static
+    .help = try `#[link(name = "{$value}")]` instead
+
+passes_link_ordinal =
+    attribute should be applied to a foreign function or static
+    .label = not a foreign function or static
+
+passes_link_section =
+    attribute should be applied to a function or static
+    .warn = {-passes_previously_accepted}
+    .label = not a function or static
+
+passes_macro_export =
+    `#[macro_export]` only has an effect on macro definitions
+
+passes_macro_use =
+    `#[{$name}]` only has an effect on `extern crate` and modules
+
+passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
+passes_missing_const_err =
+    attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+    .help = make the function or method const
+    .label = attribute specified here
+
+passes_missing_const_stab_attr =
+    {$descr} has missing const stability attribute
+
+passes_missing_lang_item =
+    language item required, but not found: `{$name}`
+    .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
+    .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
+
+passes_missing_panic_handler =
+    `#[panic_handler]` function required, but not found
+
+passes_missing_stability_attr =
+    {$descr} has missing stability attribute
+
+passes_multiple_rustc_main =
+    multiple functions with a `#[rustc_main]` attribute
+    .first = first `#[rustc_main]` function
+    .additional = additional `#[rustc_main]` function
+
+passes_multiple_start_functions =
+    multiple `start` functions
+    .label = multiple `start` functions
+    .previous = previous `#[start]` function here
+
+passes_must_not_suspend =
+    `must_not_suspend` attribute should be applied to a struct, enum, or trait
+    .label = is not a struct, enum, or trait
+
+passes_must_use_async =
+    `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
+    .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
+
+passes_must_use_no_effect =
+    `#[must_use]` has no effect when applied to {$article} {$target}
+
+passes_naked_functions_asm_block =
+    naked functions must contain a single asm block
+    .label_multiple_asm = multiple asm blocks are unsupported in naked functions
+    .label_non_asm = non-asm is unsupported in naked functions
+
+passes_naked_functions_asm_options =
+    asm options unsupported in naked functions: {$unsupported_options}
+
+passes_naked_functions_must_use_noreturn =
+    asm in naked functions must use `noreturn` option
+    .suggestion = consider specifying that the asm block is responsible for returning from the function
+
+passes_naked_functions_operands =
+    only `const` and `sym` operands are supported in naked functions
+
+passes_naked_tracked_caller =
+    cannot use `#[track_caller]` with `#[naked]`
+
+passes_no_coverage_fn_defn =
+    `#[no_coverage]` may only be applied to function definitions
+
+passes_no_coverage_ignored_function_prototype =
+    `#[no_coverage]` is ignored on function prototypes
+
+passes_no_coverage_not_coverable =
+    `#[no_coverage]` must be applied to coverable code
+    .label = not coverable code
+
+passes_no_coverage_propagate =
+    `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
+
+passes_no_link =
+    attribute should be applied to an `extern crate` item
+    .label = not an `extern crate` item
+
+passes_no_main_function =
+    `main` function not found in crate `{$crate_name}`
+    .here_is_main = here is a function named `main`
+    .one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level
+    .consider_moving_main = consider moving the `main` function definitions
+    .main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename ->
+        [true] {" "}(in `{$filename}`)
+        *[false] {""}
+    }
+    .consider_adding_main_to_file = consider adding a `main` function to `{$filename}`
+    .consider_adding_main_at_crate = consider adding a `main` function at the crate level
+    .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
+    .non_function_main = non-function item at `crate::main` is found
+
+passes_no_mangle =
+    attribute should be applied to a free function, impl method or static
+    .warn = {-passes_previously_accepted}
+    .label = not a free function, impl method or static
+
+passes_no_mangle_foreign =
+    `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
+    .warn = {-passes_previously_accepted}
+    .label = foreign {$foreign_item_kind}
+    .note = symbol names in extern blocks are not mangled
+    .suggestion = remove this attribute
+
+passes_no_patterns =
+    patterns not allowed in naked function parameters
+
+passes_non_exported_macro_invalid_attrs =
+    attribute should be applied to function or closure
+    .label = not a function or closure
+
+passes_object_lifetime_err =
+    {$repr}
 
 passes_only_has_effect_on =
     `#[{$attr_name}]` only has an effect on {$target_name ->
@@ -603,103 +532,22 @@
         *[unspecified] (unspecified--this is a compiler bug)
     }
 
-passes_object_lifetime_err =
-    {$repr}
+passes_outer_crate_level_attr =
+    crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
 
-passes_unrecognized_repr_hint =
-    unrecognized representation hint
-    .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
-
-passes_attr_application_enum =
-    attribute should be applied to an enum
-    .label = not an enum
-
-passes_attr_application_struct =
-    attribute should be applied to a struct
-    .label = not a struct
-
-passes_attr_application_struct_union =
-    attribute should be applied to a struct or union
-    .label = not a struct or union
-
-passes_attr_application_struct_enum_union =
-    attribute should be applied to a struct, enum, or union
-    .label = not a struct, enum, or union
-
-passes_attr_application_struct_enum_function_method_union =
-    attribute should be applied to a struct, enum, function, associated function, or union
-    .label = not a struct, enum, function, associated function, or union
-
-passes_transparent_incompatible =
-    transparent {$target} cannot have other repr hints
-
-passes_deprecated_attribute =
-    deprecated attribute must be paired with either stable or unstable attribute
-
-passes_useless_stability =
-    this stability annotation is useless
-    .label = useless stability annotation
-    .item = the stability attribute annotates this item
-
-passes_invalid_stability =
-    invalid stability version found
-    .label = invalid stability version
-    .item = the stability attribute annotates this item
-
-passes_cannot_stabilize_deprecated =
-    an API can't be stabilized after it is deprecated
-    .label = invalid version
-    .item = the stability attribute annotates this item
-
-passes_invalid_deprecation_version =
-    invalid deprecation version found
-    .label = invalid deprecation version
-    .item = the stability attribute annotates this item
-
-passes_missing_stability_attr =
-    {$descr} has missing stability attribute
-
-passes_missing_const_stab_attr =
-    {$descr} has missing const stability attribute
-
-passes_trait_impl_const_stable =
-    trait implementations cannot be const stable yet
-    .note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
-
-passes_feature_only_on_nightly =
-    `#![feature]` may not be used on the {$release_channel} release channel
-
-passes_unknown_feature =
-    unknown feature `{$feature}`
-
-passes_implied_feature_not_exist =
-    feature `{$implied_by}` implying `{$feature}` does not exist
-
-passes_duplicate_feature_err =
-    the feature `{$feature}` has already been declared
-
-passes_missing_const_err =
-    attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
-    .help = make the function or method const
-    .label = attribute specified here
-
-passes_dead_codes =
-    { $multiple ->
-      *[true] multiple {$descr}s are
-       [false] { $num ->
-         [one] {$descr} {$name_list} is
-        *[other] {$descr}s {$name_list} are
-       }
-    } never {$participle}
-
-passes_change_fields_to_be_of_unit_type =
-    consider changing the { $num ->
-      [one] field
-     *[other] fields
-    } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num ->
-      [one] field
-     *[other] fields
+passes_outside_loop =
+    `{$name}` outside of a loop{$is_break ->
+        [true] {" or labeled block"}
+        *[false] {""}
     }
+    .label = cannot `{$name}` outside of a loop{$is_break ->
+        [true] {" or labeled block"}
+        *[false] {""}
+    }
+
+passes_params_not_allowed =
+    referencing function parameters is not allowed in naked functions
+    .help = follow the calling convention in asm block to use parameters
 
 passes_parent_info =
     {$num ->
@@ -707,48 +555,154 @@
      *[other] {$descr}s
     } in this {$parent_descr}
 
-passes_ignored_derived_impls =
-    `{$name}` has {$trait_list_len ->
-      [one] a derived impl
-     *[other] derived impls
-    } for the {$trait_list_len ->
-      [one] trait {$trait_list}, but this is
-     *[other] traits {$trait_list}, but these are
-    } intentionally ignored during dead code analysis
+passes_pass_by_value =
+    `pass_by_value` attribute should be applied to a struct, enum or type alias
+    .label = is not a struct, enum or type alias
+
+passes_plugin_registrar =
+    `#[plugin_registrar]` only has an effect on functions
 
 passes_proc_macro_bad_sig = {$kind} has incorrect signature
 
+passes_repr_conflicting =
+    conflicting representation hints
+
+passes_repr_ident =
+    meta item in `repr` must be an identifier
+
+passes_rustc_allow_const_fn_unstable =
+    attribute should be applied to `const fn`
+    .label = not a `const fn`
+
+passes_rustc_dirty_clean =
+    attribute requires -Z query-dep-graph to be enabled
+
+passes_rustc_layout_scalar_valid_range_arg =
+    expected exactly one integer literal argument
+
+passes_rustc_layout_scalar_valid_range_not_struct =
+    attribute should be applied to a struct
+    .label = not a struct
+
+passes_rustc_legacy_const_generics_index =
+    #[rustc_legacy_const_generics] must have one index for each generic parameter
+    .label = generic parameters
+
+passes_rustc_legacy_const_generics_index_exceed =
+    index exceeds number of arguments
+    .label = there {$arg_count ->
+        [one] is
+        *[other] are
+    } only {$arg_count} {$arg_count ->
+        [one] argument
+        *[other] arguments
+    }
+
+passes_rustc_legacy_const_generics_index_negative =
+    arguments should be non-negative integers
+
+passes_rustc_legacy_const_generics_only =
+    #[rustc_legacy_const_generics] functions must only have const generics
+    .label = non-const generic parameter
+
+passes_rustc_lint_opt_deny_field_access =
+    `#[rustc_lint_opt_deny_field_access]` should be applied to a field
+    .label = not a field
+
+passes_rustc_lint_opt_ty =
+    `#[rustc_lint_opt_ty]` should be applied to a struct
+    .label = not a struct
+
+passes_rustc_std_internal_symbol =
+    attribute should be applied to functions or statics
+    .label = not a function or static
+
+passes_should_be_applied_to_fn =
+    attribute should be applied to a function definition
+    .label = {$on_crate ->
+        [true] cannot be applied to crates
+        *[false] not a function definition
+    }
+
+passes_should_be_applied_to_static =
+    attribute should be applied to a static
+    .label = not a static
+
+passes_should_be_applied_to_struct_enum =
+    attribute should be applied to a struct or enum
+    .label = not a struct or enum
+
+passes_should_be_applied_to_trait =
+    attribute should be applied to a trait
+    .label = not a trait
+
+passes_size =
+    size: {$size}
+
 passes_skipping_const_checks = skipping const checks
 
-passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
+passes_stability_promotable =
+    attribute cannot be applied to an expression
 
-passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
+passes_string_interpolation_only_works = string interpolation only works in `format!` invocations
+
+passes_target_feature_on_statement =
+    {passes_should_be_applied_to_fn}
+    .warn = {-passes_previously_accepted}
+    .label = {passes_should_be_applied_to_fn.label}
+
+passes_trait_impl_const_stable =
+    trait implementations cannot be const stable yet
+    .note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+
+passes_transparent_incompatible =
+    transparent {$target} cannot have other repr hints
+
+passes_undefined_naked_function_abi =
+    Rust ABI is unsupported in naked functions
+
+passes_unix_sigpipe_values =
+    valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+
+passes_unknown_external_lang_item =
+    unknown external lang item: `{$lang_item}`
+
+passes_unknown_feature =
+    unknown feature `{$feature}`
+
+passes_unknown_lang_item =
+    definition of an unknown language item: `{$name}`
+    .label = definition of unknown language item `{$name}`
+
+passes_unlabeled_cf_in_while_condition =
+    `break` or `continue` with no label in the condition of a `while` loop
+    .label = unlabeled `{$cf_type}` in the condition of a `while` loop
+
+passes_unlabeled_in_labeled_block =
+    unlabeled `{$cf_type}` inside of a labeled block
+    .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
+
+passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
+    .suggestion = if you are using features which are still unstable, change to using `{$implies}`
+    .suggestion_remove = if you are using features which are now stable, remove this line
+
+passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable
 
 passes_unreachable_due_to_uninhabited = unreachable {$descr}
     .label = unreachable {$descr}
     .label_orig = any code following this expression is unreachable
     .note = this expression has type `{$ty}`, which is uninhabited
 
-passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
-    .help = did you mean to capture by reference instead?
+passes_unrecognized_field =
+    unrecognized field name `{$name}`
 
-passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
-    .help = did you mean to capture by reference instead?
+passes_unrecognized_repr_hint =
+    unrecognized representation hint
+    .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
 
-passes_unused_var_remove_field = unused variable: `{$name}`
-passes_unused_var_remove_field_suggestion = try removing the field
-
-passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used
-    .note = consider using `_{$name}` instead
-
-passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable
-
-passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
-    .suggestion = if you are using features which are still unstable, change to using `{$implies}`
-    .suggestion_remove = if you are using features which are now stable, remove this line
-
-passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
-    .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
+passes_unused =
+    unused attribute
+    .suggestion = remove this attribute
 
 passes_unused_assign = value assigned to `{$name}` is never read
     .help = maybe it is overwritten before being read?
@@ -756,12 +710,58 @@
 passes_unused_assign_passed = value passed to `{$name}` is never read
     .help = maybe it is overwritten before being read?
 
-passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
-passes_string_interpolation_only_works = string interpolation only works in `format!` invocations
+passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
+    .help = did you mean to capture by reference instead?
+
+passes_unused_default_method_body_const_note =
+    `default_method_body_is_const` has been replaced with `#[const_trait]` on traits
+
+passes_unused_duplicate =
+    unused attribute
+    .suggestion = remove this attribute
+    .note = attribute also specified here
+    .warn = {-passes_previously_accepted}
+
+passes_unused_empty_lints_note =
+    attribute `{$name}` with an empty list has no effect
+
+passes_unused_multiple =
+    multiple `{$name}` attributes
+    .suggestion = remove this attribute
+    .note = attribute also specified here
+
+passes_unused_no_lints_note =
+    attribute `{$name}` without any lints has no effect
+
+passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used
+    .note = consider using `_{$name}` instead
+
+passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
+    .help = did you mean to capture by reference instead?
+
+passes_unused_var_remove_field = unused variable: `{$name}`
+passes_unused_var_remove_field_suggestion = try removing the field
+
+passes_unused_variable_try_ignore = unused variable: `{$name}`
+    .suggestion = try ignoring the field
 
 passes_unused_variable_try_prefix = unused variable: `{$name}`
     .label = unused variable
     .suggestion = if this is intentional, prefix it with an underscore
 
-passes_unused_variable_try_ignore = unused variable: `{$name}`
-    .suggestion = try ignoring the field
+passes_used_compiler_linker =
+    `used(compiler)` and `used(linker)` can't be used together
+
+passes_used_static =
+    attribute must be applied to a `static` variable
+
+passes_useless_assignment =
+    useless assignment of {$is_field_assign ->
+        [true] field
+        *[false] variable
+    } of type `{$ty}` to itself
+
+passes_useless_stability =
+    this stability annotation is useless
+    .label = useless stability annotation
+    .item = the stability attribute annotates this item
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 06aa273..c3189d1 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -8,7 +8,6 @@
 use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan};
-use rustc_expand::base::resolve_path;
 use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -19,9 +18,9 @@
 use rustc_hir::{MethodKind, Target, Unsafety};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::{
     CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
@@ -1817,7 +1816,7 @@
             || (is_simd && is_c)
             || (int_reprs == 1
                 && is_c
-                && item.map_or(false, |item| {
+                && item.is_some_and(|item| {
                     if let ItemLike::Item(item) = item {
                         return is_c_like_enum(item);
                     }
@@ -1916,6 +1915,10 @@
 
     /// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
     fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
+        // Here we only check that the #[debugger_visualizer] attribute is attached
+        // to nothing other than a module. All other checks are done in the
+        // `debugger_visualizer` query where they need to be done for decoding
+        // anyway.
         match target {
             Target::Mod => {}
             _ => {
@@ -1924,53 +1927,7 @@
             }
         }
 
-        let Some(hints) = attr.meta_item_list() else {
-            self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-            return false;
-        };
-
-        let hint = match hints.len() {
-            1 => &hints[0],
-            _ => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-                return false;
-            }
-        };
-
-        let Some(meta_item) = hint.meta_item() else {
-            self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-            return false;
-        };
-
-        let visualizer_path = match (meta_item.name_or_empty(), meta_item.value_str()) {
-            (sym::natvis_file, Some(value)) => value,
-            (sym::gdb_script_file, Some(value)) => value,
-            (_, _) => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: meta_item.span });
-                return false;
-            }
-        };
-
-        let file =
-            match resolve_path(&self.tcx.sess.parse_sess, visualizer_path.as_str(), attr.span) {
-                Ok(file) => file,
-                Err(mut err) => {
-                    err.emit();
-                    return false;
-                }
-            };
-
-        match std::fs::File::open(&file) {
-            Ok(_) => true,
-            Err(error) => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable {
-                    span: meta_item.span,
-                    file: &file,
-                    error,
-                });
-                false
-            }
-        }
+        true
     }
 
     /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
@@ -2138,7 +2095,7 @@
                 | sym::feature
                 | sym::repr
                 | sym::target_feature
-        ) && attr.meta_item_list().map_or(false, |list| list.is_empty())
+        ) && attr.meta_item_list().is_some_and(|list| list.is_empty())
         {
             errors::UnusedNote::EmptyList { name: attr.name_or_empty() }
         } else if matches!(
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 6742722..2357b0a 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -12,7 +12,7 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_span::{sym, Span, Symbol};
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 3ae5b45..7812dcd 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -12,7 +12,7 @@
 use rustc_hir::{Node, PatKind, TyKind};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 72371b9..3483f7d 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -1,60 +1,69 @@
 //! Detecting usage of the `#[debugger_visualizer]` attribute.
 
-use hir::CRATE_HIR_ID;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_ast::Attribute;
 use rustc_data_structures::sync::Lrc;
 use rustc_expand::base::resolve_path;
-use rustc_hir as hir;
-use rustc_hir::HirId;
-use rustc_middle::ty::TyCtxt;
-use rustc_middle::{query::LocalCrate, ty::query::Providers};
-use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType};
+use rustc_middle::{
+    middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType},
+    query::{LocalCrate, Providers},
+    ty::TyCtxt,
+};
+use rustc_session::Session;
+use rustc_span::sym;
 
-use crate::errors::DebugVisualizerUnreadable;
+use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable};
 
-fn check_for_debugger_visualizer(
-    tcx: TyCtxt<'_>,
-    hir_id: HirId,
-    debugger_visualizers: &mut FxHashSet<DebuggerVisualizerFile>,
-) {
-    let attrs = tcx.hir().attrs(hir_id);
-    for attr in attrs {
+impl DebuggerVisualizerCollector<'_> {
+    fn check_for_debugger_visualizer(&mut self, attr: &Attribute) {
         if attr.has_name(sym::debugger_visualizer) {
-            let Some(list) = attr.meta_item_list() else {
-                continue
+            let Some(hints) = attr.meta_item_list() else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let meta_item = match list.len() {
-                1 => match list[0].meta_item() {
-                    Some(meta_item) => meta_item,
-                    _ => continue,
-                },
-                _ => continue,
+            let hint = if hints.len() == 1 {
+                &hints[0]
+            } else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let visualizer_type = match meta_item.name_or_empty() {
-                sym::natvis_file => DebuggerVisualizerType::Natvis,
-                sym::gdb_script_file => DebuggerVisualizerType::GdbPrettyPrinter,
-                _ => continue,
+            let Some(meta_item) = hint.meta_item() else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let file = match meta_item.value_str() {
-                Some(value) => {
-                    match resolve_path(&tcx.sess.parse_sess, value.as_str(), attr.span) {
-                        Ok(file) => file,
-                        _ => continue,
+            let (visualizer_type, visualizer_path) =
+                match (meta_item.name_or_empty(), meta_item.value_str()) {
+                    (sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value),
+                    (sym::gdb_script_file, Some(value)) => {
+                        (DebuggerVisualizerType::GdbPrettyPrinter, value)
                     }
-                }
-                None => continue,
-            };
+                    (_, _) => {
+                        self.sess.emit_err(DebugVisualizerInvalid { span: meta_item.span });
+                        return;
+                    }
+                };
+
+            let file =
+                match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) {
+                    Ok(file) => file,
+                    Err(mut err) => {
+                        err.emit();
+                        return;
+                    }
+                };
 
             match std::fs::read(&file) {
                 Ok(contents) => {
-                    debugger_visualizers
-                        .insert(DebuggerVisualizerFile::new(Lrc::from(contents), visualizer_type));
+                    self.visualizers.push(DebuggerVisualizerFile::new(
+                        Lrc::from(contents),
+                        visualizer_type,
+                        file,
+                    ));
                 }
                 Err(error) => {
-                    tcx.sess.emit_err(DebugVisualizerUnreadable {
+                    self.sess.emit_err(DebugVisualizerUnreadable {
                         span: meta_item.span,
                         file: &file,
                         error,
@@ -65,29 +74,30 @@
     }
 }
 
+struct DebuggerVisualizerCollector<'a> {
+    sess: &'a Session,
+    visualizers: Vec<DebuggerVisualizerFile>,
+}
+
+impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> {
+    fn visit_attribute(&mut self, attr: &'ast Attribute) {
+        self.check_for_debugger_visualizer(attr);
+        rustc_ast::visit::walk_attribute(self, attr);
+    }
+}
+
 /// Traverses and collects the debugger visualizers for a specific crate.
 fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> {
-    // Initialize the collector.
-    let mut debugger_visualizers = FxHashSet::default();
+    let resolver_and_krate = tcx.resolver_for_lowering(()).borrow();
+    let krate = &*resolver_and_krate.1;
 
-    // Collect debugger visualizers in this crate.
-    tcx.hir().for_each_module(|id| {
-        check_for_debugger_visualizer(
-            tcx,
-            tcx.hir().local_def_id_to_hir_id(id),
-            &mut debugger_visualizers,
-        )
-    });
+    let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() };
+    rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate);
 
-    // Collect debugger visualizers on the crate attributes.
-    check_for_debugger_visualizer(tcx, CRATE_HIR_ID, &mut debugger_visualizers);
-
-    // Extract out the found debugger_visualizer items.
-    let mut visualizers = debugger_visualizers.into_iter().collect::<Vec<_>>();
-
-    // Sort the visualizers so we always get a deterministic query result.
-    visualizers.sort();
-    visualizers
+    // We are collecting visualizers in AST-order, which is deterministic,
+    // so we don't need to do any explicit sorting in order to get a
+    // deterministic query result
+    visitor.visualizers
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index eb6ea67..d8b9f4f 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -13,7 +13,7 @@
 use rustc_hir::diagnostic_items::DiagnosticItems;
 use rustc_hir::OwnerId;
 use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index e3e4b73..ffd8f77 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -4,7 +4,7 @@
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{sigpipe, CrateType, EntryFnType};
 use rustc_session::parse::feature_err;
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index fdd0e5d..476394f 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -22,7 +22,7 @@
 use rustc_session::cstore::ExternCrate;
 use rustc_span::{symbol::kw::Empty, Span};
 
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 pub(crate) enum Duplicate {
     Plain,
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 8b7338e..0da4b29 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -22,7 +22,7 @@
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 mod check_attr;
 mod check_const;
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index f4da1aa..44174b1 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -9,7 +9,7 @@
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::lib_features::LibFeatures;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::Symbol;
 use rustc_span::{sym, Span};
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 6758024..63b1578 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -94,7 +94,7 @@
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
 use rustc_index::IndexVec;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index b4cf19e..73cfe68 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -6,7 +6,7 @@
 use rustc_hir::{Destination, Movability, Node};
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::hygiene::DesugaringKind;
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index cf8d930..a849d61 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -6,7 +6,7 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, InlineAsmOperand, StmtKind};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index a5f7b07..160528e 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -13,7 +13,7 @@
 use rustc_hir::Node;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::middle::privacy::{self, Level};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::CrateType;
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 9615f28..b81b7ad 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -16,7 +16,8 @@
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
-use rustc_middle::ty::{query::Providers, TyCtxt};
+use rustc_middle::query::Providers;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::lint;
 use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
 use rustc_span::symbol::{sym, Symbol};
@@ -553,10 +554,8 @@
 
         let is_const = self.tcx.is_const_fn(def_id.to_def_id())
             || self.tcx.is_const_trait_impl_raw(def_id.to_def_id());
-        let is_stable = self
-            .tcx
-            .lookup_stability(def_id)
-            .map_or(false, |stability| stability.level.is_stable());
+        let is_stable =
+            self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
         let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none();
         let is_reachable = self.effective_visibilities.is_reachable(def_id);
 
@@ -771,7 +770,7 @@
                     // needs to have an error emitted.
                     if features.const_trait_impl
                         && *constness == hir::Constness::Const
-                        && const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
+                        && const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
                     {
                         self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
                     }
@@ -808,15 +807,12 @@
             );
 
             let is_allowed_through_unstable_modules = |def_id| {
-                self.tcx
-                    .lookup_stability(def_id)
-                    .map(|stab| match stab.level {
-                        StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
-                            allowed_through_unstable_modules
-                        }
-                        _ => false,
-                    })
-                    .unwrap_or(false)
+                self.tcx.lookup_stability(def_id).is_some_and(|stab| match stab.level {
+                    StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
+                        allowed_through_unstable_modules
+                    }
+                    _ => false,
+                })
             };
 
             if item_is_allowed && !is_allowed_through_unstable_modules(def_id) {
diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs
index 605cf0a..d87df70 100644
--- a/compiler/rustc_passes/src/upvars.rs
+++ b/compiler/rustc_passes/src/upvars.rs
@@ -5,7 +5,7 @@
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self, HirId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl
index a26d1b2..b68e8a7 100644
--- a/compiler/rustc_privacy/messages.ftl
+++ b/compiler/rustc_privacy/messages.ftl
@@ -2,22 +2,22 @@
 privacy_field_is_private_is_update_syntax_label = field `{$field_name}` is private
 privacy_field_is_private_label = private field
 
-privacy_item_is_private = {$kind} `{$descr}` is private
-    .label = private {$kind}
-privacy_unnamed_item_is_private = {$kind} is private
-    .label = private {$kind}
+privacy_from_private_dep_in_public_interface =
+    {$kind} `{$descr}` from private dependency '{$krate}' in public interface
 
 privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interface
     .label = can't leak {$vis_descr} {$kind}
     .visibility_label = `{$descr}` declared as {$vis_descr}
 
-privacy_report_effective_visibility = {$descr}
-
-privacy_from_private_dep_in_public_interface =
-    {$kind} `{$descr}` from private dependency '{$krate}' in public interface
-
+privacy_item_is_private = {$kind} `{$descr}` is private
+    .label = private {$kind}
 privacy_private_in_public_lint =
     {$vis_descr} {$kind} `{$descr}` in public interface (error {$kind ->
         [trait] E0445
         *[other] E0446
     })
+
+privacy_report_effective_visibility = {$descr}
+
+privacy_unnamed_item_is_private = {$kind} is private
+    .label = private {$kind}
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index d6eb546..65dfdf3 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -25,9 +25,9 @@
 use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
+use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{self, Const, GenericParamDefKind};
 use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -38,7 +38,7 @@
 
 use std::marker::PhantomData;
 use std::ops::ControlFlow;
-use std::{cmp, fmt, mem};
+use std::{fmt, mem};
 
 use errors::{
     FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
@@ -408,8 +408,9 @@
         min(find.tcx.local_visibility(def_id), find.min, find.tcx)
     }
 }
-impl VisibilityLike for Option<Level> {
-    const MAX: Self = Some(Level::Direct);
+
+impl VisibilityLike for Option<EffectiveVisibility> {
+    const MAX: Self = Some(EffectiveVisibility::from_vis(ty::Visibility::Public));
     // Type inference is very smart sometimes.
     // It can make an impl reachable even some components of its type or trait are unreachable.
     // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
@@ -421,7 +422,13 @@
     // (which require reaching the `DefId`s in them).
     const SHALLOW: bool = true;
     fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
-        cmp::min(find.effective_visibilities.public_at_level(def_id), find.min)
+        if let Some(min) = find.min {
+            return find
+                .effective_visibilities
+                .effective_vis(def_id)
+                .map(|eff_vis| min.min(*eff_vis, find.tcx));
+        }
+        None
     }
 }
 
@@ -447,57 +454,90 @@
     ///     n::p::f()
     /// }
     macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>,
-    /// Previous visibility level; `None` means unreachable.
-    prev_level: Option<Level>,
+    /// Preliminary pass for marking all underlying types of `impl Trait`s as reachable.
+    impl_trait_pass: bool,
     /// Has something changed in the level map?
     changed: bool,
 }
 
 struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
-    level: Option<Level>,
+    effective_vis: EffectiveVisibility,
     item_def_id: LocalDefId,
     ev: &'a mut EmbargoVisitor<'tcx>,
+    level: Level,
 }
 
 impl<'tcx> EmbargoVisitor<'tcx> {
-    fn get(&self, def_id: LocalDefId) -> Option<Level> {
-        self.effective_visibilities.public_at_level(def_id)
+    fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
+        self.effective_visibilities.effective_vis(def_id).copied()
     }
 
-    /// Updates node level and returns the updated level.
-    fn update(&mut self, def_id: LocalDefId, level: Option<Level>) -> Option<Level> {
-        let old_level = self.get(def_id);
-        // Visibility levels can only grow.
-        if level > old_level {
-            self.effective_visibilities.set_public_at_level(
+    // Updates node effective visibility.
+    fn update(
+        &mut self,
+        def_id: LocalDefId,
+        inherited_effective_vis: EffectiveVisibility,
+        level: Level,
+    ) {
+        let nominal_vis = self.tcx.local_visibility(def_id);
+        self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
+    }
+
+    fn update_eff_vis(
+        &mut self,
+        def_id: LocalDefId,
+        inherited_effective_vis: EffectiveVisibility,
+        nominal_vis: Option<ty::Visibility>,
+        level: Level,
+    ) {
+        let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
+        if Some(private_vis) != nominal_vis {
+            self.changed |= self.effective_visibilities.update(
                 def_id,
-                || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)),
-                level.unwrap(),
+                nominal_vis,
+                || private_vis,
+                inherited_effective_vis,
+                level,
+                self.tcx,
             );
-            self.changed = true;
-            level
-        } else {
-            old_level
         }
     }
 
     fn reach(
         &mut self,
         def_id: LocalDefId,
-        level: Option<Level>,
+        effective_vis: EffectiveVisibility,
     ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
         ReachEverythingInTheInterfaceVisitor {
-            level: cmp::min(level, Some(Level::Reachable)),
+            effective_vis,
             item_def_id: def_id,
             ev: self,
+            level: Level::Reachable,
+        }
+    }
+
+    fn reach_through_impl_trait(
+        &mut self,
+        def_id: LocalDefId,
+        effective_vis: EffectiveVisibility,
+    ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
+        ReachEverythingInTheInterfaceVisitor {
+            effective_vis,
+            item_def_id: def_id,
+            ev: self,
+            level: Level::ReachableThroughImplTrait,
         }
     }
 
     // We have to make sure that the items that macros might reference
     // are reachable, since they might be exported transitively.
-    fn update_reachability_from_macro(&mut self, local_def_id: LocalDefId, md: &MacroDef) {
+    fn update_reachability_from_macro(
+        &mut self,
+        local_def_id: LocalDefId,
+        md: &MacroDef,
+        macro_ev: EffectiveVisibility,
+    ) {
         // Non-opaque macros cannot make other items more accessible than they already are.
-
         let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
         let attrs = self.tcx.hir().attrs(hir_id);
         if attr::find_transparency(attrs, md.macro_rules).0 != Transparency::Opaque {
@@ -510,7 +550,7 @@
             return;
         }
 
-        if self.get(local_def_id).is_none() {
+        if self.effective_visibilities.public_at_level(local_def_id).is_none() {
             return;
         }
 
@@ -519,7 +559,7 @@
         let mut module_def_id = macro_module_def_id;
         loop {
             let changed_reachability =
-                self.update_macro_reachable(module_def_id, macro_module_def_id);
+                self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
             if changed_reachability || module_def_id == CRATE_DEF_ID {
                 break;
             }
@@ -533,21 +573,33 @@
         &mut self,
         module_def_id: LocalDefId,
         defining_mod: LocalDefId,
+        macro_ev: EffectiveVisibility,
     ) -> bool {
         if self.macro_reachable.insert((module_def_id, defining_mod)) {
-            self.update_macro_reachable_mod(module_def_id, defining_mod);
+            self.update_macro_reachable_mod(module_def_id, defining_mod, macro_ev);
             true
         } else {
             false
         }
     }
 
-    fn update_macro_reachable_mod(&mut self, module_def_id: LocalDefId, defining_mod: LocalDefId) {
+    fn update_macro_reachable_mod(
+        &mut self,
+        module_def_id: LocalDefId,
+        defining_mod: LocalDefId,
+        macro_ev: EffectiveVisibility,
+    ) {
         let module = self.tcx.hir().get_module(module_def_id).0;
         for item_id in module.item_ids {
             let def_kind = self.tcx.def_kind(item_id.owner_id);
             let vis = self.tcx.local_visibility(item_id.owner_id.def_id);
-            self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod);
+            self.update_macro_reachable_def(
+                item_id.owner_id.def_id,
+                def_kind,
+                vis,
+                defining_mod,
+                macro_ev,
+            );
         }
         for child in self.tcx.module_children_local(module_def_id) {
             // FIXME: Use module children for the logic above too.
@@ -556,7 +608,7 @@
                 && let Res::Def(def_kind, def_id) = child.res
                 && let Some(def_id) = def_id.as_local() {
                 let vis = self.tcx.local_visibility(def_id);
-                self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod);
+                self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
             }
         }
     }
@@ -567,16 +619,14 @@
         def_kind: DefKind,
         vis: ty::Visibility,
         module: LocalDefId,
+        macro_ev: EffectiveVisibility,
     ) {
-        let level = Some(Level::Reachable);
-        if vis.is_public() {
-            self.update(def_id, level);
-        }
+        self.update(def_id, macro_ev, Level::Reachable);
         match def_kind {
             // No type privacy, so can be directly marked as reachable.
             DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => {
                 if vis.is_accessible_from(module, self.tcx) {
-                    self.update(def_id, level);
+                    self.update(def_id, macro_ev, Level::Reachable);
                 }
             }
 
@@ -588,7 +638,7 @@
                 let item = self.tcx.hir().expect_item(def_id);
                 if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind {
                     if vis.is_accessible_from(module, self.tcx) {
-                        self.update(def_id, level);
+                        self.update(def_id, macro_ev, Level::Reachable);
                     }
                 }
             }
@@ -599,26 +649,24 @@
             // the module, however may be reachable.
             DefKind::Mod => {
                 if vis.is_accessible_from(module, self.tcx) {
-                    self.update_macro_reachable(def_id, module);
+                    self.update_macro_reachable(def_id, module, macro_ev);
                 }
             }
 
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
-                if vis.is_public() {
-                    let item = self.tcx.hir().expect_item(def_id);
-                    if let hir::ItemKind::Struct(ref struct_def, _)
-                    | hir::ItemKind::Union(ref struct_def, _) = item.kind
-                    {
-                        for field in struct_def.fields() {
-                            let field_vis = self.tcx.local_visibility(field.def_id);
-                            if field_vis.is_accessible_from(module, self.tcx) {
-                                self.reach(field.def_id, level).ty();
-                            }
+                let item = self.tcx.hir().expect_item(def_id);
+                if let hir::ItemKind::Struct(ref struct_def, _)
+                | hir::ItemKind::Union(ref struct_def, _) = item.kind
+                {
+                    for field in struct_def.fields() {
+                        let field_vis = self.tcx.local_visibility(field.def_id);
+                        if field_vis.is_accessible_from(module, self.tcx) {
+                            self.reach(field.def_id, macro_ev).ty();
                         }
-                    } else {
-                        bug!("item {:?} with DefKind {:?}", item, def_kind);
                     }
+                } else {
+                    bug!("item {:?} with DefKind {:?}", item, def_kind);
                 }
             }
 
@@ -653,127 +701,53 @@
 }
 
 impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    /// We want to visit items in the context of their containing
-    /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let item_level = match item.kind {
-            hir::ItemKind::Impl { .. } => {
-                let impl_level = Option::<Level>::of_impl(
-                    item.owner_id.def_id,
-                    self.tcx,
-                    &self.effective_visibilities,
-                );
-                self.update(item.owner_id.def_id, impl_level)
-            }
-            _ => self.get(item.owner_id.def_id),
-        };
-
-        // Update levels of nested things.
-        match item.kind {
-            hir::ItemKind::Enum(ref def, _) => {
-                for variant in def.variants {
-                    let variant_level = self.update(variant.def_id, item_level);
-                    if let Some(ctor_def_id) = variant.data.ctor_def_id() {
-                        self.update(ctor_def_id, item_level);
-                    }
-                    for field in variant.data.fields() {
-                        self.update(field.def_id, variant_level);
-                    }
-                }
-            }
-            hir::ItemKind::Impl(ref impl_) => {
-                for impl_item_ref in impl_.items {
-                    if impl_.of_trait.is_some()
-                        || self.tcx.visibility(impl_item_ref.id.owner_id).is_public()
-                    {
-                        self.update(impl_item_ref.id.owner_id.def_id, item_level);
-                    }
-                }
-            }
-            hir::ItemKind::Trait(.., trait_item_refs) => {
-                for trait_item_ref in trait_item_refs {
-                    self.update(trait_item_ref.id.owner_id.def_id, item_level);
-                }
-            }
-            hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
-                if let Some(ctor_def_id) = def.ctor_def_id() {
-                    self.update(ctor_def_id, item_level);
-                }
-                for field in def.fields() {
-                    let vis = self.tcx.visibility(field.def_id);
-                    if vis.is_public() {
-                        self.update(field.def_id, item_level);
-                    }
-                }
-            }
-            hir::ItemKind::Macro(ref macro_def, _) => {
-                self.update_reachability_from_macro(item.owner_id.def_id, macro_def);
-            }
-            hir::ItemKind::ForeignMod { items, .. } => {
-                for foreign_item in items {
-                    if self.tcx.visibility(foreign_item.id.owner_id).is_public() {
-                        self.update(foreign_item.id.owner_id.def_id, item_level);
-                    }
-                }
-            }
-
-            hir::ItemKind::OpaqueTy(..)
-            | hir::ItemKind::Use(..)
-            | hir::ItemKind::Static(..)
-            | hir::ItemKind::Const(..)
-            | hir::ItemKind::GlobalAsm(..)
-            | hir::ItemKind::TyAlias(..)
-            | hir::ItemKind::Mod(..)
-            | hir::ItemKind::TraitAlias(..)
-            | hir::ItemKind::Fn(..)
-            | hir::ItemKind::ExternCrate(..) => {}
+        if self.impl_trait_pass
+            && let hir::ItemKind::OpaqueTy(ref opaque) = item.kind
+            && !opaque.in_trait {
+            // FIXME: This is some serious pessimization intended to workaround deficiencies
+            // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
+            // reachable if they are returned via `impl Trait`, even from private functions.
+            let pub_ev = EffectiveVisibility::from_vis(ty::Visibility::Public);
+            self.reach_through_impl_trait(item.owner_id.def_id, pub_ev)
+                .generics()
+                .predicates()
+                .ty();
+            return;
         }
 
-        // Mark all items in interfaces of reachable items as reachable.
+        // Update levels of nested things and mark all items
+        // in interfaces of reachable items as reachable.
+        let item_ev = self.get(item.owner_id.def_id);
         match item.kind {
-            // The interface is empty.
-            hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {}
-            // All nested items are checked by `visit_item`.
-            hir::ItemKind::Mod(..) => {}
-            // Handled in `rustc_resolve`.
-            hir::ItemKind::Use(..) => {}
-            // The interface is empty.
-            hir::ItemKind::GlobalAsm(..) => {}
-            hir::ItemKind::OpaqueTy(ref opaque) => {
-                // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general)
-                // Since rustdoc never needs to do codegen and doesn't care about link-time reachability,
-                // mark this as unreachable.
-                // See https://github.com/rust-lang/rust/issues/75100
-                if !opaque.in_trait && !self.tcx.sess.opts.actually_rustdoc {
-                    // FIXME: This is some serious pessimization intended to workaround deficiencies
-                    // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
-                    // reachable if they are returned via `impl Trait`, even from private functions.
-                    let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait));
-                    self.reach(item.owner_id.def_id, exist_level).generics().predicates().ty();
+            // The interface is empty, and no nested items.
+            hir::ItemKind::Use(..)
+            | hir::ItemKind::ExternCrate(..)
+            | hir::ItemKind::GlobalAsm(..) => {}
+            // The interface is empty, and all nested items are processed by `visit_item`.
+            hir::ItemKind::Mod(..) | hir::ItemKind::OpaqueTy(..) => {}
+            hir::ItemKind::Macro(ref macro_def, _) => {
+                if let Some(item_ev) = item_ev {
+                    self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev);
                 }
             }
-            // Visit everything.
             hir::ItemKind::Const(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Fn(..)
             | hir::ItemKind::TyAlias(..) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates().ty();
+                if let Some(item_ev) = item_ev {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();
                 }
             }
             hir::ItemKind::Trait(.., trait_item_refs) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if let Some(item_ev) = item_ev {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
 
                     for trait_item_ref in trait_item_refs {
+                        self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable);
+
                         let tcx = self.tcx;
-                        let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_level);
+                        let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_ev);
                         reach.generics().predicates();
 
                         if trait_item_ref.kind == AssocItemKind::Type
@@ -787,98 +761,94 @@
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if let Some(item_ev) = item_ev {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                 }
             }
-            // Visit everything except for private impl items.
             hir::ItemKind::Impl(ref impl_) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level)
+                if let Some(item_ev) = Option::<EffectiveVisibility>::of_impl(
+                    item.owner_id.def_id,
+                    self.tcx,
+                    &self.effective_visibilities,
+                ) {
+                    self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
+
+                    self.reach(item.owner_id.def_id, item_ev)
                         .generics()
                         .predicates()
                         .ty()
                         .trait_ref();
 
                     for impl_item_ref in impl_.items {
-                        let impl_item_level = self.get(impl_item_ref.id.owner_id.def_id);
-                        if impl_item_level.is_some() {
-                            self.reach(impl_item_ref.id.owner_id.def_id, impl_item_level)
-                                .generics()
-                                .predicates()
-                                .ty();
+                        let def_id = impl_item_ref.id.owner_id.def_id;
+                        let nominal_vis =
+                            impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
+                        self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct);
+
+                        if let Some(impl_item_ev) = self.get(def_id) {
+                            self.reach(def_id, impl_item_ev).generics().predicates().ty();
                         }
                     }
                 }
             }
-
-            // Visit everything, but enum variants have their own levels.
             hir::ItemKind::Enum(ref def, _) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if let Some(item_ev) = item_ev {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                 }
                 for variant in def.variants {
-                    let variant_level = self.get(variant.def_id);
-                    if variant_level.is_some() {
+                    if let Some(item_ev) = item_ev {
+                        self.update(variant.def_id, item_ev, Level::Reachable);
+                    }
+
+                    if let Some(variant_ev) = self.get(variant.def_id) {
+                        if let Some(ctor_def_id) = variant.data.ctor_def_id() {
+                            self.update(ctor_def_id, variant_ev, Level::Reachable);
+                        }
                         for field in variant.data.fields() {
-                            self.reach(field.def_id, variant_level).ty();
+                            self.update(field.def_id, variant_ev, Level::Reachable);
+                            self.reach(field.def_id, variant_ev).ty();
                         }
                         // Corner case: if the variant is reachable, but its
                         // enum is not, make the enum reachable as well.
-                        self.reach(item.owner_id.def_id, variant_level).ty();
+                        self.reach(item.owner_id.def_id, variant_ev).ty();
                     }
                     if let Some(ctor_def_id) = variant.data.ctor_def_id() {
-                        let ctor_level = self.get(ctor_def_id);
-                        if ctor_level.is_some() {
-                            self.reach(item.owner_id.def_id, ctor_level).ty();
+                        if let Some(ctor_ev) = self.get(ctor_def_id) {
+                            self.reach(item.owner_id.def_id, ctor_ev).ty();
                         }
                     }
                 }
             }
-            // Visit everything, but foreign items have their own levels.
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
-                    let foreign_item_level = self.get(foreign_item.id.owner_id.def_id);
-                    if foreign_item_level.is_some() {
-                        self.reach(foreign_item.id.owner_id.def_id, foreign_item_level)
+                    if let Some(foreign_item_ev) = self.get(foreign_item.id.owner_id.def_id) {
+                        self.reach(foreign_item.id.owner_id.def_id, foreign_item_ev)
                             .generics()
                             .predicates()
                             .ty();
                     }
                 }
             }
-            // Visit everything except for private fields.
             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if let Some(item_ev) = item_ev {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                     for field in struct_def.fields() {
-                        let field_level = self.get(field.def_id);
-                        if field_level.is_some() {
-                            self.reach(field.def_id, field_level).ty();
+                        self.update(field.def_id, item_ev, Level::Reachable);
+                        if let Some(field_ev) = self.get(field.def_id) {
+                            self.reach(field.def_id, field_ev).ty();
                         }
                     }
                 }
                 if let Some(ctor_def_id) = struct_def.ctor_def_id() {
-                    let ctor_level = self.get(ctor_def_id);
-                    if ctor_level.is_some() {
-                        self.reach(item.owner_id.def_id, ctor_level).ty();
+                    if let Some(item_ev) = item_ev {
+                        self.update(ctor_def_id, item_ev, Level::Reachable);
+                    }
+                    if let Some(ctor_ev) = self.get(ctor_def_id) {
+                        self.reach(item.owner_id.def_id, ctor_ev).ty();
                     }
                 }
             }
         }
-
-        let orig_level = mem::replace(&mut self.prev_level, item_level);
-        intravisit::walk_item(self, item);
-        self.prev_level = orig_level;
-    }
-
-    fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) {
-        // Blocks can have public items, for example impls, but they always
-        // start as completely private regardless of publicity of a function,
-        // constant, type, field, etc., in which this block resides.
-        let orig_level = mem::replace(&mut self.prev_level, None);
-        intravisit::walk_block(self, b);
-        self.prev_level = orig_level;
     }
 }
 
@@ -932,11 +902,7 @@
         _descr: &dyn fmt::Display,
     ) -> ControlFlow<Self::BreakTy> {
         if let Some(def_id) = def_id.as_local() {
-            if let (ty::Visibility::Public, _) | (_, Some(Level::ReachableThroughImplTrait)) =
-                (self.tcx().visibility(def_id.to_def_id()), self.level)
-            {
-                self.ev.update(def_id, self.level);
-            }
+            self.ev.update_eff_vis(def_id, self.effective_vis, None, self.level);
         }
         ControlFlow::Continue(())
     }
@@ -2164,13 +2130,24 @@
         tcx,
         effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
         macro_reachable: Default::default(),
-        prev_level: Some(Level::Direct),
+        // HACK(jynelson): trying to infer the type of `impl Trait` breaks `async-std` (and
+        // `pub async fn` in general). Since rustdoc never needs to do codegen and doesn't
+        // care about link-time reachability, keep them unreachable (issue #75100).
+        impl_trait_pass: !tcx.sess.opts.actually_rustdoc,
         changed: false,
     };
 
     visitor.effective_visibilities.check_invariants(tcx, true);
+    if visitor.impl_trait_pass {
+        // Underlying types of `impl Trait`s are marked as reachable unconditionally,
+        // so this pass doesn't need to be a part of the fixed point iteration below.
+        tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
+        visitor.impl_trait_pass = false;
+        visitor.changed = false;
+    }
+
     loop {
-        tcx.hir().walk_toplevel_module(&mut visitor);
+        tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
         if visitor.changed {
             visitor.changed = false;
         } else {
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index b107a3f..e596993 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -7,6 +7,8 @@
 
 
 [dependencies]
+memoffset = { version = "0.6.0", features = ["unstable_const"] }
+field-offset = "0.3.5"
 measureme = "10.0.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 82b335f..4cf0f13 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -3,28 +3,42 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 // this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
 #![feature(const_mut_refs)]
+#![feature(const_refs_to_cell)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
+#![allow(rustc::potential_query_instability, unused_parens)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_middle;
 
-use crate::plumbing::{encode_all_query_results, try_mark_green};
+use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
+use field_offset::offset_of;
+use rustc_data_structures::stable_hasher::HashStable;
+use rustc_data_structures::sync::AtomicU64;
 use rustc_middle::arena::Arena;
+use rustc_middle::dep_graph::DepNodeIndex;
 use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
 use rustc_middle::query::erase::{erase, restore, Erase};
-use rustc_middle::query::AsLocalKey;
-use rustc_middle::ty::query::{
-    query_keys, query_provided, query_provided_to_value, query_storage, query_values,
+use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
+use rustc_middle::query::plumbing::{
+    DynamicQuery, QueryKeyStringCache, QuerySystem, QuerySystemFns,
 };
-use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine, QuerySystemFns};
+use rustc_middle::query::AsLocalKey;
+use rustc_middle::query::{
+    queries, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
+};
 use rustc_middle::ty::TyCtxt;
 use rustc_query_system::dep_graph::SerializedDepNodeIndex;
+use rustc_query_system::ich::StableHashingContext;
+use rustc_query_system::query::{
+    get_query_incr, get_query_non_incr, HashResult, QueryCache, QueryConfig, QueryInfo, QueryMap,
+    QueryMode, QueryState,
+};
+use rustc_query_system::HandleCycleError;
 use rustc_query_system::Value;
 use rustc_span::Span;
 
@@ -32,31 +46,182 @@
 mod plumbing;
 pub use crate::plumbing::QueryCtxt;
 
-pub use rustc_query_system::query::QueryConfig;
-use rustc_query_system::query::*;
-
 mod profiling_support;
 pub use self::profiling_support::alloc_self_profile_query_strings;
 
-/// This is implemented per query and restoring query values from their erased state.
-trait QueryConfigRestored<'tcx>: QueryConfig<QueryCtxt<'tcx>> + Default {
-    type RestoredValue;
+struct DynamicConfig<
+    'tcx,
+    C: QueryCache,
+    const ANON: bool,
+    const DEPTH_LIMIT: bool,
+    const FEEDABLE: bool,
+> {
+    dynamic: &'tcx DynamicQuery<'tcx, C>,
+}
 
-    fn restore(value: <Self as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue;
+impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy
+    for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
+{
+}
+impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone
+    for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
+{
+    fn clone(&self) -> Self {
+        DynamicConfig { dynamic: self.dynamic }
+    }
+}
+
+impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
+    QueryConfig<QueryCtxt<'tcx>> for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
+where
+    for<'a> C::Key: HashStable<StableHashingContext<'a>>,
+{
+    type Key = C::Key;
+    type Value = C::Value;
+    type Cache = C;
+
+    #[inline(always)]
+    fn name(self) -> &'static str {
+        self.dynamic.name
+    }
+
+    #[inline(always)]
+    fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
+        (self.dynamic.cache_on_disk)(tcx, key)
+    }
+
+    #[inline(always)]
+    fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, DepKind>
+    where
+        QueryCtxt<'tcx>: 'a,
+    {
+        self.dynamic.query_state.apply(&qcx.tcx.query_system.states)
+    }
+
+    #[inline(always)]
+    fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
+    where
+        'tcx: 'a,
+    {
+        self.dynamic.query_cache.apply(&qcx.tcx.query_system.caches)
+    }
+
+    #[inline(always)]
+    fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
+        (self.dynamic.execute_query)(tcx, key)
+    }
+
+    #[inline(always)]
+    fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
+        (self.dynamic.compute)(qcx.tcx, key)
+    }
+
+    #[inline(always)]
+    fn try_load_from_disk(
+        self,
+        qcx: QueryCtxt<'tcx>,
+        key: &Self::Key,
+        prev_index: SerializedDepNodeIndex,
+        index: DepNodeIndex,
+    ) -> Option<Self::Value> {
+        if self.dynamic.can_load_from_disk {
+            (self.dynamic.try_load_from_disk)(qcx.tcx, key, prev_index, index)
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn loadable_from_disk(
+        self,
+        qcx: QueryCtxt<'tcx>,
+        key: &Self::Key,
+        index: SerializedDepNodeIndex,
+    ) -> bool {
+        (self.dynamic.loadable_from_disk)(qcx.tcx, key, index)
+    }
+
+    fn value_from_cycle_error(
+        self,
+        tcx: TyCtxt<'tcx>,
+        cycle: &[QueryInfo<DepKind>],
+    ) -> Self::Value {
+        (self.dynamic.value_from_cycle_error)(tcx, cycle)
+    }
+
+    #[inline(always)]
+    fn format_value(self) -> fn(&Self::Value) -> String {
+        self.dynamic.format_value
+    }
+
+    #[inline(always)]
+    fn anon(self) -> bool {
+        ANON
+    }
+
+    #[inline(always)]
+    fn eval_always(self) -> bool {
+        self.dynamic.eval_always
+    }
+
+    #[inline(always)]
+    fn depth_limit(self) -> bool {
+        DEPTH_LIMIT
+    }
+
+    #[inline(always)]
+    fn feedable(self) -> bool {
+        FEEDABLE
+    }
+
+    #[inline(always)]
+    fn dep_kind(self) -> DepKind {
+        self.dynamic.dep_kind
+    }
+
+    #[inline(always)]
+    fn handle_cycle_error(self) -> HandleCycleError {
+        self.dynamic.handle_cycle_error
+    }
+
+    #[inline(always)]
+    fn hash_result(self) -> HashResult<Self::Value> {
+        self.dynamic.hash_result
+    }
+}
+
+/// This is implemented per query. It allows restoring query values from their erased state
+/// and constructing a QueryConfig.
+trait QueryConfigRestored<'tcx> {
+    type RestoredValue;
+    type Config: QueryConfig<QueryCtxt<'tcx>>;
+
+    fn config(tcx: TyCtxt<'tcx>) -> Self::Config;
+    fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value)
+    -> Self::RestoredValue;
+}
+
+pub fn query_system<'tcx>(
+    local_providers: Providers,
+    extern_providers: ExternProviders,
+    on_disk_cache: Option<OnDiskCache<'tcx>>,
+    incremental: bool,
+) -> QuerySystem<'tcx> {
+    QuerySystem {
+        states: Default::default(),
+        arenas: Default::default(),
+        caches: Default::default(),
+        dynamic_queries: dynamic_queries(),
+        on_disk_cache,
+        fns: QuerySystemFns {
+            engine: engine(incremental),
+            local_providers,
+            extern_providers,
+            encode_query_results: encode_all_query_results,
+            try_mark_green: try_mark_green,
+        },
+        jobs: AtomicU64::new(1),
+    }
 }
 
 rustc_query_append! { define_queries! }
-
-pub fn query_system_fns<'tcx>(
-    local_providers: Providers,
-    extern_providers: ExternProviders,
-) -> QuerySystemFns<'tcx> {
-    QuerySystemFns {
-        engine: engine(),
-        local_providers,
-        extern_providers,
-        query_structs: make_dep_kind_array!(query_structs).to_vec(),
-        encode_query_results: encode_all_query_results,
-        try_mark_green: try_mark_green,
-    }
-}
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 9f8ac7c..244f0e8 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -4,6 +4,7 @@
 
 use crate::rustc_middle::dep_graph::DepContext;
 use crate::rustc_middle::ty::TyEncoder;
+use crate::QueryConfigRestored;
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::Lock;
 use rustc_errors::Diagnostic;
@@ -80,8 +81,8 @@
     fn try_collect_active_jobs(self) -> Option<QueryMap<DepKind>> {
         let mut jobs = QueryMap::default();
 
-        for query in &self.query_system.fns.query_structs {
-            (query.try_collect_active_jobs)(self.tcx, &mut jobs);
+        for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() {
+            collect(self.tcx, &mut jobs);
         }
 
         Some(jobs)
@@ -182,10 +183,8 @@
     encoder: &mut CacheEncoder<'_, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
 ) {
-    for query in &tcx.query_system.fns.query_structs {
-        if let Some(encode) = query.encode_query_results {
-            encode(tcx, encoder, query_result_index);
-        }
+    for encode in super::ENCODE_QUERY_RESULTS.iter().copied().filter_map(|e| e) {
+        encode(tcx, encoder, query_result_index);
     }
 }
 
@@ -265,14 +264,14 @@
 }
 
 macro_rules! call_provider {
-    ([][$qcx:expr, $name:ident, $key:expr]) => {{
-        ($qcx.query_system.fns.local_providers.$name)($qcx, $key)
+    ([][$tcx:expr, $name:ident, $key:expr]) => {{
+        ($tcx.query_system.fns.local_providers.$name)($tcx, $key)
     }};
-    ([(separate_provide_extern) $($rest:tt)*][$qcx:expr, $name:ident, $key:expr]) => {{
+    ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
         if let Some(key) = $key.as_local_key() {
-            ($qcx.query_system.fns.local_providers.$name)($qcx, key)
+            ($tcx.query_system.fns.local_providers.$name)($tcx, key)
         } else {
-            ($qcx.query_system.fns.extern_providers.$name)($qcx, $key)
+            ($tcx.query_system.fns.extern_providers.$name)($tcx, $key)
         }
     }};
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
@@ -341,7 +340,7 @@
 }
 
 pub(crate) fn encode_query_results<'a, 'tcx, Q>(
-    query: Q,
+    query: Q::Config,
     qcx: QueryCtxt<'tcx>,
     encoder: &mut CacheEncoder<'a, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
@@ -392,12 +391,26 @@
 
 pub(crate) fn try_load_from_disk<'tcx, V>(
     tcx: TyCtxt<'tcx>,
-    id: SerializedDepNodeIndex,
+    prev_index: SerializedDepNodeIndex,
+    index: DepNodeIndex,
 ) -> Option<V>
 where
     V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
 {
-    tcx.query_system.on_disk_cache.as_ref()?.try_load_query_result(tcx, id)
+    let on_disk_cache = tcx.query_system.on_disk_cache.as_ref()?;
+
+    let prof_timer = tcx.prof.incr_cache_loading();
+
+    // The call to `with_query_deserialization` enforces that no new `DepNodes`
+    // are created during deserialization. See the docs of that method for more
+    // details.
+    let value = tcx
+        .dep_graph
+        .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
+
+    prof_timer.finish_with_query_invocation_id(index.into());
+
+    value
 }
 
 fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
@@ -434,10 +447,9 @@
 
 pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
 where
-    Q: QueryConfig<QueryCtxt<'tcx>> + Default,
-    Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+    Q: QueryConfigRestored<'tcx>,
 {
-    let fingerprint_style = Q::Key::fingerprint_style();
+    let fingerprint_style = <Q::Config as QueryConfig<QueryCtxt<'tcx>>>::Key::fingerprint_style();
 
     if is_anon || !fingerprint_style.reconstructible() {
         return DepKindStruct {
@@ -453,13 +465,25 @@
         is_anon,
         is_eval_always,
         fingerprint_style,
-        force_from_dep_node: Some(|tcx, dep_node| force_from_dep_node(Q::default(), tcx, dep_node)),
+        force_from_dep_node: Some(|tcx, dep_node| {
+            force_from_dep_node(Q::config(tcx), tcx, dep_node)
+        }),
         try_load_from_on_disk_cache: Some(|tcx, dep_node| {
-            try_load_from_on_disk_cache(Q::default(), tcx, dep_node)
+            try_load_from_on_disk_cache(Q::config(tcx), tcx, dep_node)
         }),
     }
 }
 
+macro_rules! item_if_cached {
+    ([] $tokens:tt) => {};
+    ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => {
+        $($tokens)*
+    };
+    ([$other:tt $($modifiers:tt)*] $tokens:tt) => {
+        item_if_cached! { [$($modifiers)*] $tokens }
+    };
+}
+
 macro_rules! expand_if_cached {
     ([], $tokens:expr) => {{
         None
@@ -472,193 +496,226 @@
     };
 }
 
+/// Don't show the backtrace for query system by default
+/// use `RUST_BACKTRACE=full` to show all the backtraces
+#[inline(never)]
+pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
+where
+    F: FnOnce() -> T,
+{
+    let result = f();
+    std::hint::black_box(());
+    result
+}
+
 // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
 // invoked by `rustc_query_append`.
 macro_rules! define_queries {
     (
      $($(#[$attr:meta])*
         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
-        mod get_query {
-            use super::*;
 
-            $(
-                #[inline(always)]
-                #[tracing::instrument(level = "trace", skip(tcx))]
-                pub(super) fn $name<'tcx>(
+        pub(crate) mod query_impl { $(pub mod $name {
+            use super::super::*;
+            use std::marker::PhantomData;
+
+            pub mod get_query_incr {
+                use super::*;
+
+                // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
+                // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
+                #[inline(never)]
+                pub fn __rust_end_short_backtrace<'tcx>(
                     tcx: TyCtxt<'tcx>,
                     span: Span,
-                    key: query_keys::$name<'tcx>,
+                    key: queries::$name::Key<'tcx>,
                     mode: QueryMode,
-                ) -> Option<Erase<query_values::$name<'tcx>>> {
-                    get_query(
-                        queries::$name::default(),
+                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
+                    get_query_incr(
+                        QueryType::config(tcx),
                         QueryCtxt::new(tcx),
                         span,
                         key,
                         mode
                     )
                 }
-            )*
-        }
-
-        pub(crate) fn engine() -> QueryEngine {
-            QueryEngine {
-                $($name: get_query::$name,)*
             }
-        }
 
-        #[allow(nonstandard_style)]
-        mod queries {
-            use std::marker::PhantomData;
+            pub mod get_query_non_incr {
+                use super::*;
 
-            $(
-                #[derive(Copy, Clone, Default)]
-                pub struct $name<'tcx> {
-                    data: PhantomData<&'tcx ()>
+                #[inline(never)]
+                pub fn __rust_end_short_backtrace<'tcx>(
+                    tcx: TyCtxt<'tcx>,
+                    span: Span,
+                    key: queries::$name::Key<'tcx>,
+                    __mode: QueryMode,
+                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
+                    Some(get_query_non_incr(
+                        QueryType::config(tcx),
+                        QueryCtxt::new(tcx),
+                        span,
+                        key,
+                    ))
                 }
-            )*
-        }
-
-        $(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
-            type Key = query_keys::$name<'tcx>;
-            type Value = Erase<query_values::$name<'tcx>>;
-
-            #[inline(always)]
-            fn name(self) -> &'static str {
-                stringify!($name)
             }
 
-            #[inline]
-            fn format_value(self) -> fn(&Self::Value) -> String {
-                |value| format!("{:?}", restore::<query_values::$name<'tcx>>(*value))
+            pub fn dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> {
+                DynamicQuery {
+                    name: stringify!($name),
+                    eval_always: is_eval_always!([$($modifiers)*]),
+                    dep_kind: dep_graph::DepKind::$name,
+                    handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
+                    query_state: offset_of!(QueryStates<'tcx> => $name),
+                    query_cache: offset_of!(QueryCaches<'tcx> => $name),
+                    cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
+                    execute_query: |tcx, key| erase(tcx.$name(key)),
+                    compute: |tcx, key| {
+                        __rust_begin_short_backtrace(||
+                            queries::$name::provided_to_erased(
+                                tcx,
+                                call_provider!([$($modifiers)*][tcx, $name, key])
+                            )
+                        )
+                    },
+                    can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
+                    try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
+                        |tcx, key, prev_index, index| {
+                            if ::rustc_middle::query::cached::$name(tcx, key) {
+                                let value = $crate::plumbing::try_load_from_disk::<
+                                    queries::$name::ProvidedValue<'tcx>
+                                >(
+                                    tcx,
+                                    prev_index,
+                                    index,
+                                );
+                                value.map(|value| queries::$name::provided_to_erased(tcx, value))
+                            } else {
+                                None
+                            }
+                        }
+                    } {
+                        |_tcx, _key, _prev_index, _index| None
+                    }),
+                    value_from_cycle_error: |tcx, cycle| {
+                        let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle);
+                        erase(result)
+                    },
+                    loadable_from_disk: |_tcx, _key, _index| {
+                        should_ever_cache_on_disk!([$($modifiers)*] {
+                            ::rustc_middle::query::cached::$name(_tcx, _key) &&
+                                $crate::plumbing::loadable_from_disk(_tcx, _index)
+                        } {
+                            false
+                        })
+                    },
+                    hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
+                    format_value: |value| format!("{:?}", restore::<queries::$name::Value<'tcx>>(*value)),
+                }
             }
 
-            #[inline]
-            fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
-                ::rustc_middle::query::cached::$name(tcx, key)
+            #[derive(Copy, Clone, Default)]
+            pub struct QueryType<'tcx> {
+                data: PhantomData<&'tcx ()>
             }
 
-            type Cache = query_storage::$name<'tcx>;
+            impl<'tcx> QueryConfigRestored<'tcx> for QueryType<'tcx> {
+                type RestoredValue = queries::$name::Value<'tcx>;
+                type Config = DynamicConfig<
+                    'tcx,
+                    queries::$name::Storage<'tcx>,
+                    { is_anon!([$($modifiers)*]) },
+                    { depth_limit!([$($modifiers)*]) },
+                    { feedable!([$($modifiers)*]) },
+                >;
 
-            #[inline(always)]
-            fn query_state<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
-                where QueryCtxt<'tcx>: 'a
-            {
-                &tcx.query_system.states.$name
+                #[inline(always)]
+                fn config(tcx: TyCtxt<'tcx>) -> Self::Config {
+                    DynamicConfig {
+                        dynamic: &tcx.query_system.dynamic_queries.$name,
+                    }
+                }
+
+                #[inline(always)]
+                fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
+                    restore::<queries::$name::Value<'tcx>>(value)
+                }
             }
 
-            #[inline(always)]
-            fn query_cache<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
-                where 'tcx:'a
-            {
-                &tcx.query_system.caches.$name
+            pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap<DepKind>) {
+                let make_query = |tcx, key| {
+                    let kind = rustc_middle::dep_graph::DepKind::$name;
+                    let name = stringify!($name);
+                    $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
+                };
+                tcx.query_system.states.$name.try_collect_active_jobs(
+                    tcx,
+                    make_query,
+                    qmap,
+                ).unwrap();
             }
 
-            fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
-                erase(tcx.$name(key))
-            }
-
-            #[inline]
-            #[allow(unused_variables)]
-            fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
-                query_provided_to_value::$name(
-                    qcx.tcx,
-                    call_provider!([$($modifiers)*][qcx.tcx, $name, key])
+            pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) {
+                $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
+                    tcx,
+                    stringify!($name),
+                    &tcx.query_system.caches.$name,
+                    string_cache,
                 )
             }
 
-            #[inline]
-            fn try_load_from_disk(
-                self,
-                _qcx: QueryCtxt<'tcx>,
-                _key: &Self::Key
-            ) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self::Value> {
-                should_ever_cache_on_disk!([$($modifiers)*] {
-                    if ::rustc_middle::query::cached::$name(_qcx.tcx, _key) {
-                        Some(|qcx: QueryCtxt<'tcx>, dep_node| {
-                            let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
-                                qcx.tcx,
-                                dep_node
-                            );
-                            value.map(|value| query_provided_to_value::$name(qcx.tcx, value))
-                        })
-                    } else {
-                        None
-                    }
-                } {
-                    None
-                })
-            }
+            item_if_cached! { [$($modifiers)*] {
+                pub fn encode_query_results<'tcx>(
+                    tcx: TyCtxt<'tcx>,
+                    encoder: &mut CacheEncoder<'_, 'tcx>,
+                    query_result_index: &mut EncodedDepNodeIndex
+                ) {
+                    $crate::plumbing::encode_query_results::<query_impl::$name::QueryType<'tcx>>(
+                        query_impl::$name::QueryType::config(tcx),
+                        QueryCtxt::new(tcx),
+                        encoder,
+                        query_result_index,
+                    )
+                }
+            }}
+        })*}
 
-            #[inline]
-            fn loadable_from_disk(
-                self,
-                _qcx: QueryCtxt<'tcx>,
-                _key: &Self::Key,
-                _index: SerializedDepNodeIndex,
-            ) -> bool {
-                should_ever_cache_on_disk!([$($modifiers)*] {
-                    self.cache_on_disk(_qcx.tcx, _key) &&
-                        $crate::plumbing::loadable_from_disk(_qcx.tcx, _index)
-                } {
-                    false
-                })
+        pub(crate) fn engine(incremental: bool) -> QueryEngine {
+            if incremental {
+                QueryEngine {
+                    $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
+                }
+            } else {
+                QueryEngine {
+                    $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
+                }
             }
+        }
 
-            #[inline]
-            fn value_from_cycle_error(
-                self,
-                tcx: TyCtxt<'tcx>,
-                cycle: &[QueryInfo<DepKind>],
-            ) -> Self::Value {
-                let result: query_values::$name<'tcx> = Value::from_cycle_error(tcx, cycle);
-                erase(result)
+        pub fn dynamic_queries<'tcx>() -> DynamicQueries<'tcx> {
+            DynamicQueries {
+                $(
+                    $name: query_impl::$name::dynamic_query(),
+                )*
             }
+        }
 
-            #[inline(always)]
-            fn anon(self) -> bool {
-                is_anon!([$($modifiers)*])
-            }
+        // These arrays are used for iteration and can't be indexed by `DepKind`.
 
-            #[inline(always)]
-            fn eval_always(self) -> bool {
-                is_eval_always!([$($modifiers)*])
-            }
+        const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>)] =
+            &[$(query_impl::$name::try_collect_active_jobs),*];
 
-            #[inline(always)]
-            fn depth_limit(self) -> bool {
-                depth_limit!([$($modifiers)*])
-            }
+        const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
+            for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
+        ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
 
-            #[inline(always)]
-            fn feedable(self) -> bool {
-                feedable!([$($modifiers)*])
-            }
-
-            #[inline(always)]
-            fn dep_kind(self) -> rustc_middle::dep_graph::DepKind {
-                dep_graph::DepKind::$name
-            }
-
-            #[inline(always)]
-            fn handle_cycle_error(self) -> rustc_query_system::HandleCycleError {
-                handle_cycle_error!([$($modifiers)*])
-            }
-
-            #[inline(always)]
-            fn hash_result(self) -> rustc_query_system::query::HashResult<Self::Value> {
-                hash_result!([$($modifiers)*][query_values::$name<'tcx>])
-            }
-        })*
-
-        $(impl<'tcx> QueryConfigRestored<'tcx> for queries::$name<'tcx> {
-            type RestoredValue = query_values::$name<'tcx>;
-
-            #[inline(always)]
-            fn restore(value: <Self as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
-                restore::<query_values::$name<'tcx>>(value)
-            }
-        })*
+        const ENCODE_QUERY_RESULTS: &[
+            Option<for<'tcx> fn(
+                TyCtxt<'tcx>,
+                &mut CacheEncoder<'_, 'tcx>,
+                &mut EncodedDepNodeIndex)
+            >
+        ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
 
         #[allow(nonstandard_style)]
         mod query_callbacks {
@@ -718,71 +775,13 @@
             }
 
             $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
-                $crate::plumbing::query_callback::<queries::$name<'tcx>>(
+                $crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
                     is_anon!([$($modifiers)*]),
                     is_eval_always!([$($modifiers)*]),
                 )
             })*
         }
 
-        mod query_structs {
-            use super::*;
-            use rustc_middle::ty::query::QueryStruct;
-            use rustc_middle::ty::query::QueryKeyStringCache;
-            use rustc_middle::dep_graph::DepKind;
-
-            pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
-                fn noop_try_collect_active_jobs(_: TyCtxt<'_>, _: &mut QueryMap<DepKind>) -> Option<()> {
-                    None
-                }
-                fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
-
-                QueryStruct {
-                    try_collect_active_jobs: noop_try_collect_active_jobs,
-                    alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
-                    encode_query_results: None,
-                }
-            }
-
-            pub(super) use dummy_query_struct as Null;
-            pub(super) use dummy_query_struct as Red;
-            pub(super) use dummy_query_struct as TraitSelect;
-            pub(super) use dummy_query_struct as CompileCodegenUnit;
-            pub(super) use dummy_query_struct as CompileMonoItem;
-
-            $(
-            pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
-                try_collect_active_jobs: |tcx, qmap| {
-                    let make_query = |tcx, key| {
-                        let kind = rustc_middle::dep_graph::DepKind::$name;
-                        let name = stringify!($name);
-                        $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
-                    };
-                    tcx.query_system.states.$name.try_collect_active_jobs(
-                        tcx,
-                        make_query,
-                        qmap,
-                    )
-                },
-                alloc_self_profile_query_strings: |tcx, string_cache| {
-                    $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
-                        tcx,
-                        stringify!($name),
-                        &tcx.query_system.caches.$name,
-                        string_cache,
-                    )
-                },
-                encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
-                    $crate::plumbing::encode_query_results::<super::queries::$name<'tcx>>(
-                        super::queries::$name::default(),
-                        QueryCtxt::new(tcx),
-                        encoder,
-                        query_result_index,
-                    )
-                ),
-            }})*
-        }
-
         pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
             arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
         }
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 7d9306f..fbc6db9 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -2,7 +2,7 @@
 use rustc_data_structures::profiling::SelfProfiler;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
-use rustc_middle::ty::query::QueryKeyStringCache;
+use rustc_middle::query::plumbing::QueryKeyStringCache;
 use rustc_middle::ty::TyCtxt;
 use rustc_query_system::query::QueryCache;
 use std::fmt::Debug;
@@ -243,7 +243,7 @@
 
     let mut string_cache = QueryKeyStringCache::new();
 
-    for query in &tcx.query_system.fns.query_structs {
-        (query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
+    for alloc in super::ALLOC_SELF_PROFILE_QUERY_STRINGS.iter() {
+        alloc(tcx, &mut string_cache)
     }
 }
diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl
index 0d01123..49b423d 100644
--- a/compiler/rustc_query_system/messages.ftl
+++ b/compiler/rustc_query_system/messages.ftl
@@ -1,4 +1,20 @@
-query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
+query_system_cycle = cycle detected when {$stack_bottom}
+
+query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
+
+query_system_cycle_recursive_ty_alias = type aliases cannot be recursive
+query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle
+query_system_cycle_recursive_ty_alias_help2 = see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
+
+query_system_cycle_stack_middle = ...which requires {$desc}...
+
+query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle
+
+query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again
+
+query_system_cycle_usage = cycle used when {$usage}
+
+query_system_cycle_which_requires = ...which requires {$desc}...
 
 query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node}
     .help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile
@@ -6,25 +22,9 @@
 query_system_increment_compilation_note1 = Please follow the instructions below to create a bug report with the provided information
 query_system_increment_compilation_note2 = See <https://github.com/rust-lang/rust/issues/84970> for more information
 
-query_system_cycle = cycle detected when {$stack_bottom}
-
-query_system_cycle_usage = cycle used when {$usage}
-
-query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again
-
-query_system_cycle_stack_middle = ...which requires {$desc}...
-
-query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle
-
-query_system_cycle_recursive_ty_alias = type aliases cannot be recursive
-query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle
-query_system_cycle_recursive_ty_alias_help2 = see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
-
-query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
-
-query_system_cycle_which_requires = ...which requires {$desc}...
+query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
 
 query_system_query_overflow = queries overflow the depth limit!
     .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
 
-query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
+query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 8de4d06..c0d7386 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -656,7 +656,7 @@
     /// current compilation session. Used in various assertions
     #[inline]
     pub fn is_index_green(&self, prev_index: SerializedDepNodeIndex) -> bool {
-        self.colors.get(prev_index).map_or(false, |c| c.is_green())
+        self.colors.get(prev_index).is_some_and(|c| c.is_green())
     }
 
     #[inline]
@@ -677,7 +677,7 @@
 impl<K: DepKind> DepGraph<K> {
     #[inline]
     pub fn dep_node_exists(&self, dep_node: &DepNode<K>) -> bool {
-        self.data.as_ref().map_or(false, |data| data.dep_node_exists(dep_node))
+        self.data.as_ref().is_some_and(|data| data.dep_node_exists(dep_node))
     }
 
     /// Checks whether a previous work product exists for `v` and, if
@@ -955,7 +955,7 @@
     /// Returns true if the given node has been marked as green during the
     /// current compilation session. Used in various assertions
     pub fn is_green(&self, dep_node: &DepNode<K>) -> bool {
-        self.node_color(dep_node).map_or(false, |c| c.is_green())
+        self.node_color(dep_node).is_some_and(|c| c.is_green())
     }
 
     /// This method loads all on-disk cacheable query results into memory, so
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 8865ecf..e673d5b 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -24,7 +24,7 @@
             .iter()
             .filter(|attr| {
                 !attr.is_doc_comment()
-                    && !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
+                    && !attr.ident().is_some_and(|ident| hcx.is_ignored_attr(ident.name))
             })
             .collect();
 
@@ -38,7 +38,7 @@
 impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
     fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) {
         // Make sure that these have been filtered out.
-        debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name)));
+        debug_assert!(!attr.ident().is_some_and(|ident| self.is_ignored_attr(ident.name)));
         debug_assert!(!attr.is_doc_comment());
 
         let ast::Attribute { kind, id: _, style, span } = attr;
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index bb9ea50..7e47d70 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -4,6 +4,7 @@
 use crate::error::HandleCycleError;
 use crate::ich::StableHashingContext;
 use crate::query::caches::QueryCache;
+use crate::query::DepNodeIndex;
 use crate::query::{QueryContext, QueryInfo, QueryState};
 
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -12,8 +13,6 @@
 
 pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
 
-pub type TryLoadFromDisk<Qcx, V> = Option<fn(Qcx, SerializedDepNodeIndex) -> Option<V>>;
-
 pub trait QueryConfig<Qcx: QueryContext>: Copy {
     fn name(self) -> &'static str;
 
@@ -43,7 +42,13 @@
 
     fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value;
 
-    fn try_load_from_disk(self, qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self::Value>;
+    fn try_load_from_disk(
+        self,
+        tcx: Qcx,
+        key: &Self::Key,
+        prev_index: SerializedDepNodeIndex,
+        index: DepNodeIndex,
+    ) -> Option<Self::Value>;
 
     fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
 
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 5f2ec65..f45f7ca 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -22,7 +22,7 @@
     rustc_data_structures::fx::FxHashSet,
     rustc_data_structures::sync::Lock,
     rustc_data_structures::sync::Lrc,
-    rustc_data_structures::{jobserver, OnDrop},
+    rustc_data_structures::{defer, jobserver},
     rustc_span::DUMMY_SP,
     std::iter,
     std::process,
@@ -530,7 +530,7 @@
 /// all active queries for cycles before finally resuming all the waiters at once.
 #[cfg(parallel_compiler)]
 pub fn deadlock<D: DepKind>(query_map: QueryMap<D>, registry: &rayon_core::Registry) {
-    let on_panic = OnDrop(|| {
+    let on_panic = defer(|| {
         eprintln!("deadlock handler panicked, aborting process");
         process::abort();
     });
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index fa1f51b..f7619d7 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -12,7 +12,7 @@
 };
 
 mod config;
-pub use self::config::{HashResult, QueryConfig, TryLoadFromDisk};
+pub use self::config::{HashResult, QueryConfig};
 
 use crate::dep_graph::DepKind;
 use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 3b17c66..730e4c8 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -312,7 +312,7 @@
 }
 
 #[inline(never)]
-fn try_execute_query<Q, Qcx>(
+fn try_execute_query<Q, Qcx, const INCR: bool>(
     query: Q,
     qcx: Qcx,
     span: Span,
@@ -355,7 +355,7 @@
             // Drop the lock before we start executing the query
             drop(state_lock);
 
-            execute_job(query, qcx, state, key, id, dep_node)
+            execute_job::<_, _, INCR>(query, qcx, state, key, id, dep_node)
         }
         Entry::Occupied(mut entry) => {
             match entry.get_mut() {
@@ -383,7 +383,7 @@
 }
 
 #[inline(always)]
-fn execute_job<Q, Qcx>(
+fn execute_job<Q, Qcx, const INCR: bool>(
     query: Q,
     qcx: Qcx,
     state: &QueryState<Q::Key, Qcx::DepKind>,
@@ -398,9 +398,19 @@
     // Use `JobOwner` so the query will be poisoned if executing it panics.
     let job_owner = JobOwner { state, key };
 
-    let (result, dep_node_index) = match qcx.dep_context().dep_graph().data() {
-        None => execute_job_non_incr(query, qcx, key, id),
-        Some(data) => execute_job_incr(query, qcx, data, key, dep_node, id),
+    debug_assert_eq!(qcx.dep_context().dep_graph().is_fully_enabled(), INCR);
+
+    let (result, dep_node_index) = if INCR {
+        execute_job_incr(
+            query,
+            qcx,
+            qcx.dep_context().dep_graph().data().unwrap(),
+            key,
+            dep_node,
+            id,
+        )
+    } else {
+        execute_job_non_incr(query, qcx, key, id)
     };
 
     let cache = query.query_cache(qcx);
@@ -423,16 +433,22 @@
                 (hasher(&mut hcx, &cached_result), hasher(&mut hcx, &result))
             });
             let formatter = query.format_value();
-            debug_assert_eq!(
-                old_hash,
-                new_hash,
-                "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
-                computed={:#?}\nfed={:#?}",
-                query.dep_kind(),
-                key,
-                formatter(&result),
-                formatter(&cached_result),
-            );
+            if old_hash != new_hash {
+                // We have an inconsistency. This can happen if one of the two
+                // results is tainted by errors. In this case, delay a bug to
+                // ensure compilation is doomed.
+                qcx.dep_context().sess().delay_span_bug(
+                    DUMMY_SP,
+                    format!(
+                        "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
+                        computed={:#?}\nfed={:#?}",
+                        query.dep_kind(),
+                        key,
+                        formatter(&result),
+                        formatter(&cached_result),
+                    ),
+                );
+            }
         }
     }
     job_owner.complete(cache, result, dep_node_index);
@@ -564,59 +580,44 @@
 
     // First we try to load the result from the on-disk cache.
     // Some things are never cached on disk.
-    if let Some(try_load_from_disk) = query.try_load_from_disk(qcx, &key) {
-        let prof_timer = qcx.dep_context().profiler().incr_cache_loading();
-
-        // The call to `with_query_deserialization` enforces that no new `DepNodes`
-        // are created during deserialization. See the docs of that method for more
-        // details.
-        let result = qcx
-            .dep_context()
-            .dep_graph()
-            .with_query_deserialization(|| try_load_from_disk(qcx, prev_dep_node_index));
-
-        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-        if let Some(result) = result {
-            if std::intrinsics::unlikely(
-                qcx.dep_context().sess().opts.unstable_opts.query_dep_graph,
-            ) {
-                dep_graph_data.mark_debug_loaded_from_disk(*dep_node)
-            }
-
-            let prev_fingerprint = dep_graph_data.prev_fingerprint_of(prev_dep_node_index);
-            // If `-Zincremental-verify-ich` is specified, re-hash results from
-            // the cache and make sure that they have the expected fingerprint.
-            //
-            // If not, we still seek to verify a subset of fingerprints loaded
-            // from disk. Re-hashing results is fairly expensive, so we can't
-            // currently afford to verify every hash. This subset should still
-            // give us some coverage of potential bugs though.
-            let try_verify = prev_fingerprint.split().1.as_u64() % 32 == 0;
-            if std::intrinsics::unlikely(
-                try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
-            ) {
-                incremental_verify_ich(
-                    *qcx.dep_context(),
-                    dep_graph_data,
-                    &result,
-                    prev_dep_node_index,
-                    query.hash_result(),
-                    query.format_value(),
-                );
-            }
-
-            return Some((result, dep_node_index));
+    if let Some(result) = query.try_load_from_disk(qcx, key, prev_dep_node_index, dep_node_index) {
+        if std::intrinsics::unlikely(qcx.dep_context().sess().opts.unstable_opts.query_dep_graph) {
+            dep_graph_data.mark_debug_loaded_from_disk(*dep_node)
         }
 
-        // We always expect to find a cached result for things that
-        // can be forced from `DepNode`.
-        debug_assert!(
-            !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
-            "missing on-disk cache entry for reconstructible {dep_node:?}"
-        );
+        let prev_fingerprint = dep_graph_data.prev_fingerprint_of(prev_dep_node_index);
+        // If `-Zincremental-verify-ich` is specified, re-hash results from
+        // the cache and make sure that they have the expected fingerprint.
+        //
+        // If not, we still seek to verify a subset of fingerprints loaded
+        // from disk. Re-hashing results is fairly expensive, so we can't
+        // currently afford to verify every hash. This subset should still
+        // give us some coverage of potential bugs though.
+        let try_verify = prev_fingerprint.split().1.as_u64() % 32 == 0;
+        if std::intrinsics::unlikely(
+            try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
+        ) {
+            incremental_verify_ich(
+                *qcx.dep_context(),
+                dep_graph_data,
+                &result,
+                prev_dep_node_index,
+                query.hash_result(),
+                query.format_value(),
+            );
+        }
+
+        return Some((result, dep_node_index));
     }
 
+    // We always expect to find a cached result for things that
+    // can be forced from `DepNode`.
+    debug_assert!(
+        !query.cache_on_disk(*qcx.dep_context(), key)
+            || !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
+        "missing on-disk cache entry for {dep_node:?}"
+    );
+
     // Sanity check for the logic in `ensure`: if the node is green and the result loadable,
     // we should actually be able to load it.
     debug_assert!(
@@ -799,7 +800,18 @@
 }
 
 #[inline(always)]
-pub fn get_query<Q, Qcx>(
+pub fn get_query_non_incr<Q, Qcx>(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value
+where
+    Q: QueryConfig<Qcx>,
+    Qcx: QueryContext,
+{
+    debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
+
+    ensure_sufficient_stack(|| try_execute_query::<Q, Qcx, false>(query, qcx, span, key, None).0)
+}
+
+#[inline(always)]
+pub fn get_query_incr<Q, Qcx>(
     query: Q,
     qcx: Qcx,
     span: Span,
@@ -810,6 +822,8 @@
     Q: QueryConfig<Qcx>,
     Qcx: QueryContext,
 {
+    debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled());
+
     let dep_node = if let QueryMode::Ensure { check_cache } = mode {
         let (must_run, dep_node) = ensure_must_run(query, qcx, &key, check_cache);
         if !must_run {
@@ -820,8 +834,9 @@
         None
     };
 
-    let (result, dep_node_index) =
-        ensure_sufficient_stack(|| try_execute_query(query, qcx, span, key, dep_node));
+    let (result, dep_node_index) = ensure_sufficient_stack(|| {
+        try_execute_query::<_, _, true>(query, qcx, span, key, dep_node)
+    });
     if let Some(dep_node_index) = dep_node_index {
         qcx.dep_context().dep_graph().read_index(dep_node_index)
     }
@@ -846,5 +861,7 @@
 
     debug_assert!(!query.anon());
 
-    ensure_sufficient_stack(|| try_execute_query(query, qcx, DUMMY_SP, key, Some(dep_node)));
+    ensure_sufficient_stack(|| {
+        try_execute_query::<_, _, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
+    });
 }
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 1c16d85..46da0aa 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -7,7 +7,7 @@
 
 [dependencies]
 bitflags = "1.2.1"
-pulldown-cmark = { version = "0.9.2", default-features = false }
+pulldown-cmark = { version = "0.9.3", default-features = false }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 345255c..539b88a 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -1,134 +1,38 @@
-resolve_parent_module_reset_for_binding =
-    parent module is reset for binding
+resolve_accessible_unsure = not sure whether the path is accessible or not
+    .note = the type may have associated items, but we are currently not checking them
+
+resolve_add_as_non_derive =
+    add as non-Derive macro
+    `#[{$macro_path}]`
 
 resolve_ampersand_used_without_explicit_lifetime_name =
     `&` without an explicit lifetime name cannot be used here
     .note = explicit lifetime name needed here
 
-resolve_underscore_lifetime_name_cannot_be_used_here =
-    `'_` cannot be used here
-    .note = `'_` is a reserved lifetime name
-
-resolve_crate_may_not_be_imported =
-    `$crate` may not be imported
-
-resolve_crate_root_imports_must_be_named_explicitly =
-    crate root imports need to be explicitly named: `use crate as name;`
-
-resolve_generic_params_from_outer_function =
-    can't use generic parameters from outer function
-    .label = use of generic parameter from outer function
-    .suggestion = try using a local generic parameter instead
-
-resolve_self_type_implicitly_declared_by_impl =
-    `Self` type implicitly declared here, by this `impl`
-
-resolve_cannot_use_self_type_here =
-    can't use `Self` here
-
-resolve_use_a_type_here_instead =
-    use a type here instead
-
-resolve_type_param_from_outer_fn =
-    type parameter from outer function
-
-resolve_const_param_from_outer_fn =
-    const parameter from outer function
-
-resolve_try_using_local_generic_parameter =
-    try using a local generic parameter instead
-
-resolve_try_adding_local_generic_param_on_method =
-    try adding a local generic parameter in this method instead
-
-resolve_help_try_using_local_generic_param =
-    try using a local generic parameter instead
-
-resolve_name_is_already_used_as_generic_parameter =
-    the name `{$name}` is already used for a generic parameter in this item's generic parameters
-    .label = already used
-    .first_use_of_name = first use of `{$name}`
-
-resolve_method_not_member_of_trait =
-    method `{$method}` is not a member of trait `{$trait_}`
-    .label = not a member of trait `{$trait_}`
-
-resolve_associated_fn_with_similar_name_exists =
-    there is an associated function with a similar name
-
-resolve_type_not_member_of_trait =
-    type `{$type_}` is not a member of trait `{$trait_}`
-    .label = not a member of trait `{$trait_}`
-
-resolve_associated_type_with_similar_name_exists =
-    there is an associated type with a similar name
-
-resolve_const_not_member_of_trait =
-    const `{$const_}` is not a member of trait `{$trait_}`
-    .label = not a member of trait `{$trait_}`
+resolve_ancestor_only =
+    visibilities can only be restricted to ancestor modules
 
 resolve_associated_const_with_similar_name_exists =
     there is an associated constant with a similar name
 
-resolve_variable_bound_with_different_mode =
-    variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
-    .label = bound in different ways
-    .first_binding_span = first binding
+resolve_associated_fn_with_similar_name_exists =
+    there is an associated function with a similar name
 
-resolve_ident_bound_more_than_once_in_parameter_list =
-    identifier `{$identifier}` is bound more than once in this parameter list
-    .label = used as parameter more than once
-
-resolve_ident_bound_more_than_once_in_same_pattern =
-    identifier `{$identifier}` is bound more than once in the same pattern
-    .label = used in a pattern more than once
-
-resolve_undeclared_label =
-    use of undeclared label `{$name}`
-    .label = undeclared label `{$name}`
-
-resolve_label_with_similar_name_reachable =
-    a label with a similar name is reachable
-
-resolve_try_using_similarly_named_label =
-    try using similarly named label
-
-resolve_unreachable_label_with_similar_name_exists =
-    a label with a similar name exists but is unreachable
-
-resolve_self_import_can_only_appear_once_in_the_list =
-    `self` import can only appear once in an import list
-    .label = can only appear once in an import list
-
-resolve_self_import_only_in_import_list_with_non_empty_prefix =
-    `self` import can only appear in an import list with a non-empty prefix
-    .label = can only appear in an import list with a non-empty prefix
-
-resolve_cannot_capture_dynamic_environment_in_fn_item =
-    can't capture dynamic environment in a fn item
-    .help = use the `|| {"{"} ... {"}"}` closure form instead
+resolve_associated_type_with_similar_name_exists =
+    there is an associated type with a similar name
 
 resolve_attempt_to_use_non_constant_value_in_constant =
     attempt to use a non-constant value in a constant
 
-resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
-    consider using `{$suggestion}` instead of `{$current}`
-
 resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion =
     non-constant value
 
+resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
+    consider using `{$suggestion}` instead of `{$current}`
+
 resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
     this would need to be a `{$suggestion}`
 
-resolve_self_imports_only_allowed_within =
-    `self` imports are only allowed within a {"{"} {"}"} list
-
-resolve_self_imports_only_allowed_within_suggestion =
-    consider importing the module directly
-
-resolve_self_imports_only_allowed_within_multipart_suggestion =
-    alternatively, use the multi-path `use` syntax to import `self`
-
 resolve_binding_shadows_something_unacceptable =
     {$shadowing_binding}s cannot shadow {$shadowed_binding}s
     .label = cannot be named the same as {$article} {$shadowed_binding}
@@ -137,26 +41,105 @@
 resolve_binding_shadows_something_unacceptable_suggestion =
     try specify the pattern arguments
 
-resolve_forward_declared_generic_param =
-    generic parameters with a default cannot use forward declared identifiers
-    .label = defaulted generic parameters cannot be forward declared
+resolve_cannot_capture_dynamic_environment_in_fn_item =
+    can't capture dynamic environment in a fn item
+    .help = use the `|| {"{"} ... {"}"}` closure form instead
 
-resolve_param_in_ty_of_const_param =
-    the type of const parameters must not depend on other generic parameters
-    .label = the type must not depend on the parameter `{$name}`
+resolve_cannot_use_self_type_here =
+    can't use `Self` here
 
-resolve_type_param_in_ty_of_const_param =
-    type parameters may not be used in the type of const parameters
+resolve_const_not_member_of_trait =
+    const `{$const_}` is not a member of trait `{$trait_}`
+    .label = not a member of trait `{$trait_}`
+
+resolve_const_param_from_outer_fn =
+    const parameter from outer function
+
+resolve_const_param_in_enum_discriminant =
+    const parameters may not be used in enum discriminant values
+
+resolve_const_param_in_non_trivial_anon_const =
+    const parameters may only be used as standalone arguments, i.e. `{$name}`
 
 resolve_const_param_in_ty_of_const_param =
     const parameters may not be used in the type of const parameters
 
+resolve_crate_may_not_be_imported =
+    `$crate` may not be imported
+
+resolve_crate_root_imports_must_be_named_explicitly =
+    crate root imports need to be explicitly named: `use crate as name;`
+
+resolve_expected_found =
+    expected module, found {$res} `{$path_str}`
+    .label = not a module
+
+resolve_forward_declared_generic_param =
+    generic parameters with a default cannot use forward declared identifiers
+    .label = defaulted generic parameters cannot be forward declared
+
+resolve_generic_params_from_outer_function =
+    can't use generic parameters from outer function
+    .label = use of generic parameter from outer function
+    .suggestion = try using a local generic parameter instead
+
+resolve_help_try_using_local_generic_param =
+    try using a local generic parameter instead
+
+resolve_ident_bound_more_than_once_in_parameter_list =
+    identifier `{$identifier}` is bound more than once in this parameter list
+    .label = used as parameter more than once
+
+resolve_ident_bound_more_than_once_in_same_pattern =
+    identifier `{$identifier}` is bound more than once in the same pattern
+    .label = used in a pattern more than once
+
+resolve_imported_crate = `$crate` may not be imported
+
+resolve_indeterminate =
+    cannot determine resolution for the visibility
+
+resolve_invalid_asm_sym =
+    invalid `sym` operand
+    .label = is a local variable
+    .help = `sym` operands must refer to either a function or a static
+
+resolve_label_with_similar_name_reachable =
+    a label with a similar name is reachable
+
+resolve_lifetime_param_in_enum_discriminant =
+    lifetime parameters may not be used in enum discriminant values
+
+resolve_lifetime_param_in_non_trivial_anon_const =
+    lifetime parameters may not be used in const expressions
+
 resolve_lifetime_param_in_ty_of_const_param =
     lifetime parameters may not be used in the type of const parameters
 
-resolve_self_in_generic_param_default =
-    generic parameters cannot use `Self` in their defaults
-    .label = `Self` in generic parameter default
+resolve_lowercase_self =
+    attempt to use a non-constant value in a constant
+    .suggestion = try using `Self`
+
+resolve_macro_expected_found =
+    expected {$expected}, found {$found} `{$macro_path}`
+
+resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
+
+resolve_method_not_member_of_trait =
+    method `{$method}` is not a member of trait `{$trait_}`
+    .label = not a member of trait `{$trait_}`
+
+resolve_module_only =
+    visibility must resolve to a module
+
+resolve_name_is_already_used_as_generic_parameter =
+    the name `{$name}` is already used for a generic parameter in this item's generic parameters
+    .label = already used
+    .first_use_of_name = first use of `{$name}`
+
+resolve_param_in_enum_discriminant =
+    generic parameters may not be used in enum discriminant values
+    .label = cannot perform const operation using `{$name}`
 
 resolve_param_in_non_trivial_anon_const =
     generic parameters may not be used in const operations
@@ -165,43 +148,50 @@
 resolve_param_in_non_trivial_anon_const_help =
     use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-resolve_type_param_in_non_trivial_anon_const =
-    type parameters may not be used in const expressions
+resolve_param_in_ty_of_const_param =
+    the type of const parameters must not depend on other generic parameters
+    .label = the type must not depend on the parameter `{$name}`
 
-resolve_const_param_in_non_trivial_anon_const =
-    const parameters may only be used as standalone arguments, i.e. `{$name}`
+resolve_parent_module_reset_for_binding =
+    parent module is reset for binding
 
-resolve_lifetime_param_in_non_trivial_anon_const =
-    lifetime parameters may not be used in const expressions
+resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
+    .help = you can define integration tests in a directory named `tests`
 
-resolve_unreachable_label =
-    use of unreachable label `{$name}`
-    .label = unreachable label `{$name}`
-    .label_definition_span = unreachable label defined here
-    .note = labels are unreachable through functions, closures, async blocks and modules
+resolve_relative_2018 =
+    relative paths are not supported in visibilities in 2018 edition or later
+    .suggestion = try
 
-resolve_unreachable_label_suggestion_use_similarly_named =
-    try using similarly named label
+resolve_remove_surrounding_derive =
+    remove from the surrounding `derive()`
 
-resolve_unreachable_label_similar_name_reachable =
-    a label with a similar name is reachable
+resolve_self_import_can_only_appear_once_in_the_list =
+    `self` import can only appear once in an import list
+    .label = can only appear once in an import list
 
-resolve_unreachable_label_similar_name_unreachable =
-    a label with a similar name exists but is also unreachable
+resolve_self_import_only_in_import_list_with_non_empty_prefix =
+    `self` import can only appear in an import list with a non-empty prefix
+    .label = can only appear in an import list with a non-empty prefix
 
-resolve_trait_impl_mismatch =
-    item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
-    .label = does not match trait
-    .label_trait_item = item in trait
+resolve_self_imports_only_allowed_within =
+    `self` imports are only allowed within a {"{"} {"}"} list
 
-resolve_invalid_asm_sym =
-    invalid `sym` operand
-    .label = is a local variable
-    .help = `sym` operands must refer to either a function or a static
+resolve_self_imports_only_allowed_within_multipart_suggestion =
+    alternatively, use the multi-path `use` syntax to import `self`
 
-resolve_lowercase_self =
-    attempt to use a non-constant value in a constant
-    .suggestion = try using `Self`
+resolve_self_imports_only_allowed_within_suggestion =
+    consider importing the module directly
+
+resolve_self_in_generic_param_default =
+    generic parameters cannot use `Self` in their defaults
+    .label = `Self` in generic parameter default
+
+resolve_self_type_implicitly_declared_by_impl =
+    `Self` type implicitly declared here, by this `impl`
+
+resolve_tool_module_imported =
+    cannot use a tool module through an import
+    .note = the tool module imported here
 
 resolve_trait_impl_duplicate =
     duplicate definitions with name `{$name}`:
@@ -209,56 +199,66 @@
     .old_span_label = previous definition here
     .trait_item_span = item in trait
 
-resolve_relative_2018 =
-    relative paths are not supported in visibilities in 2018 edition or later
-    .suggestion = try
+resolve_trait_impl_mismatch =
+    item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
+    .label = does not match trait
+    .label_trait_item = item in trait
 
-resolve_ancestor_only =
-    visibilities can only be restricted to ancestor modules
+resolve_try_adding_local_generic_param_on_method =
+    try adding a local generic parameter in this method instead
 
-resolve_expected_found =
-    expected module, found {$res} `{$path_str}`
-    .label = not a module
+resolve_try_using_local_generic_parameter =
+    try using a local generic parameter instead
 
-resolve_indeterminate =
-    cannot determine resolution for the visibility
+resolve_try_using_similarly_named_label =
+    try using similarly named label
 
-resolve_tool_module_imported =
-    cannot use a tool module through an import
-    .note = the tool module imported here
+resolve_type_not_member_of_trait =
+    type `{$type_}` is not a member of trait `{$trait_}`
+    .label = not a member of trait `{$trait_}`
 
-resolve_module_only =
-    visibility must resolve to a module
-
-resolve_macro_expected_found =
-    expected {$expected}, found {$found} `{$macro_path}`
-
-resolve_remove_surrounding_derive =
-    remove from the surrounding `derive()`
-
-resolve_add_as_non_derive =
-    add as non-Derive macro
-    `#[{$macro_path}]`
-
-resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
-    .help = you can define integration tests in a directory named `tests`
-
-resolve_imported_crate = `$crate` may not be imported
-
-resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
-
-resolve_accessible_unsure = not sure whether the path is accessible or not
-    .note = the type may have associated items, but we are currently not checking them
-
-resolve_param_in_enum_discriminant =
-    generic parameters may not be used in enum discriminant values
-    .label = cannot perform const operation using `{$name}`
+resolve_type_param_from_outer_fn =
+    type parameter from outer function
 
 resolve_type_param_in_enum_discriminant =
     type parameters may not be used in enum discriminant values
 
-resolve_const_param_in_enum_discriminant =
-    const parameters may not be used in enum discriminant values
+resolve_type_param_in_non_trivial_anon_const =
+    type parameters may not be used in const expressions
 
-resolve_lifetime_param_in_enum_discriminant =
-    lifetime parameters may not be used in enum discriminant values
+resolve_type_param_in_ty_of_const_param =
+    type parameters may not be used in the type of const parameters
+
+resolve_undeclared_label =
+    use of undeclared label `{$name}`
+    .label = undeclared label `{$name}`
+
+resolve_underscore_lifetime_name_cannot_be_used_here =
+    `'_` cannot be used here
+    .note = `'_` is a reserved lifetime name
+
+resolve_unreachable_label =
+    use of unreachable label `{$name}`
+    .label = unreachable label `{$name}`
+    .label_definition_span = unreachable label defined here
+    .note = labels are unreachable through functions, closures, async blocks and modules
+
+resolve_unreachable_label_similar_name_reachable =
+    a label with a similar name is reachable
+
+resolve_unreachable_label_similar_name_unreachable =
+    a label with a similar name exists but is also unreachable
+
+resolve_unreachable_label_suggestion_use_similarly_named =
+    try using similarly named label
+
+resolve_unreachable_label_with_similar_name_exists =
+    a label with a similar name exists but is unreachable
+
+resolve_use_a_type_here_instead =
+    use a type here instead
+
+resolve_variable_bound_with_different_mode =
+    variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
+    .label = bound in different ways
+    .first_binding_span = first binding
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 2438b3a..7277773 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -9,12 +9,9 @@
 use crate::imports::{Import, ImportKind};
 use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
-use crate::{
-    errors, Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot,
-};
-use crate::{
-    MacroData, NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError,
-};
+use crate::{errors, BindingKey, MacroData};
+use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
 use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
@@ -72,7 +69,7 @@
         T: ToNameBinding<'a>,
     {
         let binding = def.to_name_binding(self.arenas);
-        let key = self.new_key(ident, ns);
+        let key = self.new_disambiguated_key(ident, ns);
         if let Err(old_binding) = self.try_define(parent, key, binding) {
             self.report_conflict(parent, ident, ns, old_binding, &binding);
         }
@@ -132,7 +129,7 @@
                     expn_id,
                     self.def_span(def_id),
                     // FIXME: Account for `#[no_implicit_prelude]` attributes.
-                    parent.map_or(false, |module| module.no_implicit_prelude),
+                    parent.is_some_and(|module| module.no_implicit_prelude),
                 ));
             }
         }
@@ -379,7 +376,7 @@
             ImportKind::Single { target, type_ns_only, .. } => {
                 self.r.per_ns(|this, ns| {
                     if !type_ns_only || ns == TypeNS {
-                        let key = this.new_key(target, ns);
+                        let key = BindingKey::new(target, ns);
                         let mut resolution = this.resolution(current_module, key).borrow_mut();
                         resolution.add_single_import(import);
                     }
@@ -876,6 +873,11 @@
                     let msg = "macro-expanded `extern crate` items cannot \
                                        shadow names passed with `--extern`";
                     self.r.tcx.sess.span_err(item.span, msg);
+                    // `return` is intended to discard this binding because it's an
+                    // unregistered ambiguity error which would result in a panic
+                    // caused by inconsistency `path_res`
+                    // more details: https://github.com/rust-lang/rust/pull/111761
+                    return;
                 }
             }
             let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 17c4a6b..dc35c8b 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -117,16 +117,11 @@
         match item.kind {
             ast::UseTreeKind::Simple(Some(ident)) => {
                 if ident.name == kw::Underscore
-                    && !self
-                        .r
-                        .import_res_map
-                        .get(&id)
-                        .map(|per_ns| {
-                            per_ns.iter().filter_map(|res| res.as_ref()).any(|res| {
-                                matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
-                            })
+                    && !self.r.import_res_map.get(&id).is_some_and(|per_ns| {
+                        per_ns.iter().filter_map(|res| res.as_ref()).any(|res| {
+                            matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
                         })
-                        .unwrap_or(false)
+                    })
                 {
                     self.unused_import(self.base_id).add(id);
                 }
@@ -469,7 +464,7 @@
                 .r
                 .extern_prelude
                 .get(&extern_crate.ident)
-                .map_or(false, |entry| !entry.introduced_by_item)
+                .is_some_and(|entry| !entry.introduced_by_item)
             {
                 continue;
             }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 6675b8e..8c6ac82 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -28,10 +28,10 @@
 use rustc_span::{BytePos, Span, SyntaxContext};
 use thin_vec::ThinVec;
 
-use crate::errors as errs;
 use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::path_names_to_string;
+use crate::{errors as errs, BindingKey};
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize};
 use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
@@ -550,7 +550,7 @@
 
                 let sm = self.tcx.sess.source_map();
                 let def_id = match outer_res {
-                    Res::SelfTyParam { .. } | Res::SelfCtor(_) => {
+                    Res::SelfTyParam { .. } => {
                         err.span_label(span, "can't use `Self` here");
                         return err;
                     }
@@ -1832,8 +1832,18 @@
             }
             (msg, None)
         } else if ident.name == kw::SelfUpper {
-            ("`Self` is only available in impls, traits, and type definitions".to_string(), None)
-        } else if ident.name.as_str().chars().next().map_or(false, |c| c.is_ascii_uppercase()) {
+            // As mentioned above, `opt_ns` being `None` indicates a module path in import.
+            // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an
+            // impl
+            if opt_ns.is_none() {
+                ("`Self` cannot be used in imports".to_string(), None)
+            } else {
+                (
+                    "`Self` is only available in impls, traits, and type definitions".to_string(),
+                    None,
+                )
+            }
+        } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
             // Check whether the name refers to an item in the value namespace.
             let binding = if let Some(ribs) = ribs {
                 self.resolve_ident_in_lexical_scope(
@@ -2081,7 +2091,8 @@
         }
 
         let resolutions = self.resolutions(crate_module).borrow();
-        let resolution = resolutions.get(&self.new_key(ident, MacroNS))?;
+        let binding_key = BindingKey::new(ident, MacroNS);
+        let resolution = resolutions.get(&binding_key)?;
         let binding = resolution.borrow().binding()?;
         if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
             let module_name = crate_module.kind.name().unwrap();
@@ -2154,7 +2165,7 @@
                 let is_definitely_crate = import
                     .module_path
                     .first()
-                    .map_or(false, |f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
+                    .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
 
                 // Add the import to the start, with a `{` if required.
                 let start_point = source_map.start_point(after_crate_name);
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 8706718..7393bdb 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -199,7 +199,7 @@
         let tcx = self.r.tcx;
         self.changed |= self.import_effective_visibilities.update(
             binding,
-            nominal_vis,
+            Some(nominal_vis),
             || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_import(binding)),
             inherited_eff_vis,
             parent_id.level(),
@@ -213,7 +213,7 @@
         let tcx = self.r.tcx;
         self.changed |= self.def_effective_visibilities.update(
             def_id,
-            nominal_vis,
+            Some(nominal_vis),
             || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_def(def_id)),
             inherited_eff_vis,
             parent_id.level(),
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 755acdd..945c7ce 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -18,6 +18,7 @@
     ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
 };
 use crate::macros::{sub_namespace_match, MacroRulesScope};
+use crate::BindingKey;
 use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
 use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
@@ -865,7 +866,7 @@
             }
         };
 
-        let key = self.new_key(ident, ns);
+        let key = BindingKey::new(ident, ns);
         let resolution =
             self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
 
@@ -1174,10 +1175,7 @@
                     return Res::Err;
                 }
             }
-            Res::Def(DefKind::TyParam, _)
-            | Res::SelfTyParam { .. }
-            | Res::SelfTyAlias { .. }
-            | Res::SelfCtor(_) => {
+            Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
                 for rib in ribs {
                     let has_generic_params: HasGenericParams = match rib.kind {
                         RibKind::Normal
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 9e44295..7c4c05d 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -405,17 +405,18 @@
         t
     }
 
-    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
-    // also mark such failed imports as used to avoid duplicate diagnostics.
-    fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
+    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
+    // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
+    fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) {
         if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
-            if target_bindings.iter().any(|binding| binding.get().is_some()) {
+            if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
+            {
                 return; // Has resolution, do not create the dummy binding
             }
             let dummy_binding = self.dummy_binding;
             let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
-                let key = this.new_key(target, ns);
+                let key = BindingKey::new(target, ns);
                 let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
             });
             self.record_use(target, dummy_binding, false);
@@ -474,7 +475,7 @@
 
             // If this import is unresolved then create a dummy import
             // resolution for it so that later resolve stages won't complain.
-            self.import_dummy_binding(import);
+            self.import_dummy_binding(import, is_indeterminate);
 
             if let Some(err) = unresolved_import_error {
                 if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
@@ -712,7 +713,7 @@
                                 .span_label(import.span, "cannot be imported directly")
                                 .emit();
                         }
-                        let key = this.new_key(target, ns);
+                        let key = BindingKey::new(target, ns);
                         this.update_resolution(parent, key, |_, resolution| {
                             resolution.single_imports.remove(&Interned::new_unchecked(import));
                         });
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 44e277c..e061190 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -6,6 +6,7 @@
 //! If you wonder why there's no `early.rs`, that's because it's split into three files -
 //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`.
 
+use crate::BindingKey;
 use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
@@ -16,7 +17,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
 use rustc_hir::def::Namespace::{self, *};
-use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
+use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_bound_vars::Set1;
@@ -2967,7 +2968,7 @@
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         let Some((module, _)) = &self.current_trait_ref else { return; };
         ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
-        let key = self.r.new_key(ident, ns);
+        let key = BindingKey::new(ident, ns);
         let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
         debug!(?binding);
         if binding.is_none() {
@@ -2978,7 +2979,7 @@
                 TypeNS => ValueNS,
                 _ => ns,
             };
-            let key = self.r.new_key(ident, ns);
+            let key = BindingKey::new(ident, ns);
             binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
             debug!(?binding);
         }
@@ -3543,10 +3544,6 @@
         //
         // Similar thing, for types, happens in `report_errors` above.
         let report_errors_for_call = |this: &mut Self, parent_err: Spanned<ResolutionError<'a>>| {
-            if !source.is_call() {
-                return Some(parent_err);
-            }
-
             // Before we start looking for candidates, we have to get our hands
             // on the type user is trying to perform invocation on; basically:
             // we're transforming `HashMap::new` into just `HashMap`.
@@ -4290,12 +4287,12 @@
         }
     }
 
-    fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> bool {
+    fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
         // FIXME: This caching may be incorrect in case of multiple `macro_rules`
         // items with the same name in the same module.
         // Also hygiene is not considered.
         let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
-        let res = doc_link_resolutions
+        let res = *doc_link_resolutions
             .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
             .or_default()
             .entry((Symbol::intern(path_str), ns))
@@ -4310,8 +4307,7 @@
                     return None;
                 }
                 res
-            })
-            .is_some();
+            });
         self.r.doc_link_resolutions = doc_link_resolutions;
         res
     }
@@ -4346,8 +4342,10 @@
             let mut any_resolved = false;
             let mut need_assoc = false;
             for ns in [TypeNS, ValueNS, MacroNS] {
-                if self.resolve_and_cache_rustdoc_path(&path_str, ns) {
-                    any_resolved = true;
+                if let Some(res) = self.resolve_and_cache_rustdoc_path(&path_str, ns) {
+                    // Rustdoc ignores tool attribute resolutions and attempts
+                    // to resolve their prefixes for diagnostics.
+                    any_resolved = !matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Tool));
                 } else if ns != MacroNS {
                     need_assoc = true;
                 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c9131d8..df65825 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -197,8 +197,7 @@
                             .sess
                             .source_map()
                             .span_to_snippet(span)
-                            .map(|snippet| snippet.ends_with(')'))
-                            .unwrap_or(false)
+                            .is_ok_and(|snippet| snippet.ends_with(')'))
                     }
                     Res::Def(
                         DefKind::Ctor(..) | DefKind::AssocFn | DefKind::Const | DefKind::AssocConst,
@@ -722,7 +721,7 @@
         if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
             && res
                 .opt_def_id()
-                .map_or(false, |id| id.is_local() || is_in_same_file(span, sugg_span))
+                .is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
         {
             err.span_label(
                 sugg_span,
@@ -856,7 +855,7 @@
             // The current function has a `self` parameter, but we were unable to resolve
             // a reference to `self`. This can only happen if the `self` identifier we
             // are resolving came from a different hygiene context.
-            if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) {
+            if fn_kind.decl().inputs.get(0).is_some_and(|p| p.is_self()) {
                 err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
             } else {
                 let doesnt = if is_assoc_fn {
@@ -1632,7 +1631,7 @@
                             .tcx
                             .fn_arg_names(def_id)
                             .first()
-                            .map_or(false, |ident| ident.name == kw::SelfLower),
+                            .is_some_and(|ident| ident.name == kw::SelfLower),
                     };
                     if has_self {
                         return Some(AssocSuggestion::MethodWithSelf { called });
@@ -1931,10 +1930,9 @@
                 let def_id = self.r.tcx.parent(ctor_def_id);
                 match kind {
                     CtorKind::Const => false,
-                    CtorKind::Fn => !self
-                        .r
-                        .field_def_ids(def_id)
-                        .map_or(false, |field_ids| field_ids.is_empty()),
+                    CtorKind::Fn => {
+                        !self.r.field_def_ids(def_id).is_some_and(|field_ids| field_ids.is_empty())
+                    }
                 }
             };
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index c12dc2f..3d2bd84 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -47,6 +47,7 @@
 use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
+use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
@@ -84,6 +85,7 @@
 
 fluent_messages! { "../messages.ftl" }
 
+#[derive(Debug)]
 enum Weak {
     Yes,
     No,
@@ -104,7 +106,7 @@
 /// A specific scope in which a name can be looked up.
 /// This enum is currently used only for early resolution (imports and macros),
 /// but not for late resolution yet.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 enum Scope<'a> {
     DeriveHelpers(LocalExpnId),
     DeriveHelpersCompat,
@@ -468,6 +470,13 @@
     disambiguator: u32,
 }
 
+impl BindingKey {
+    fn new(ident: Ident, ns: Namespace) -> Self {
+        let ident = ident.normalize_to_macros_2_0();
+        BindingKey { ident, ns, disambiguator: 0 }
+    }
+}
+
 type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution<'a>>>>;
 
 /// One node in the tree of modules.
@@ -942,6 +951,7 @@
     empty_module: Module<'a>,
     module_map: FxHashMap<DefId, Module<'a>>,
     binding_parent_modules: FxHashMap<Interned<'a, NameBinding<'a>>, Module<'a>>,
+
     underscore_disambiguator: u32,
 
     /// Maps glob imports to the names of items actually imported.
@@ -1467,7 +1477,7 @@
     }
 
     fn is_builtin_macro(&mut self, res: Res) -> bool {
-        self.get_macro(res).map_or(false, |macro_data| macro_data.ext.builtin_name.is_some())
+        self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name.is_some())
     }
 
     fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
@@ -1594,7 +1604,7 @@
         import_ids
     }
 
-    fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
+    fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
         let ident = ident.normalize_to_macros_2_0();
         let disambiguator = if ident.name == kw::Underscore {
             self.underscore_disambiguator += 1;
@@ -2026,6 +2036,6 @@
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.registered_tools = macros::registered_tools;
 }
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 4da43c6..df5c16a 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -823,8 +823,7 @@
                 let is_allowed = |feature| {
                     self.active_features.contains(&feature) || span.allows_unstable(feature)
                 };
-                let allowed_by_implication =
-                    implied_by.map(|feature| is_allowed(feature)).unwrap_or(false);
+                let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
                 if !is_allowed(feature) && !allowed_by_implication {
                     let lint_buffer = &mut self.lint_buffer;
                     let soft_handler =
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 6b559cb..0ffc537 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,4 +1,4 @@
-use crate::leb128::{self, largest_max_leb128_len};
+use crate::leb128;
 use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fs::File;
 use std::io::{self, Write};
@@ -14,6 +14,9 @@
 
 pub type FileEncodeResult = Result<usize, io::Error>;
 
+/// The size of the buffer in `FileEncoder`.
+const BUF_SIZE: usize = 8192;
+
 /// `FileEncoder` encodes data to file via fixed-size buffer.
 ///
 /// There used to be a `MemEncoder` type that encoded all the data into a
@@ -35,26 +38,12 @@
 
 impl FileEncoder {
     pub fn new<P: AsRef<Path>>(path: P) -> io::Result<Self> {
-        const DEFAULT_BUF_SIZE: usize = 8192;
-        FileEncoder::with_capacity(path, DEFAULT_BUF_SIZE)
-    }
-
-    pub fn with_capacity<P: AsRef<Path>>(path: P, capacity: usize) -> io::Result<Self> {
-        // Require capacity at least as large as the largest LEB128 encoding
-        // here, so that we don't have to check or handle this on every write.
-        assert!(capacity >= largest_max_leb128_len());
-
-        // Require capacity small enough such that some capacity checks can be
-        // done using guaranteed non-overflowing add rather than sub, which
-        // shaves an instruction off those code paths (on x86 at least).
-        assert!(capacity <= usize::MAX - largest_max_leb128_len());
-
         // Create the file for reading and writing, because some encoders do both
         // (e.g. the metadata encoder when -Zmeta-stats is enabled)
         let file = File::options().read(true).write(true).create(true).truncate(true).open(path)?;
 
         Ok(FileEncoder {
-            buf: Box::new_uninit_slice(capacity),
+            buf: Box::new_uninit_slice(BUF_SIZE),
             buffered: 0,
             flushed: 0,
             file,
@@ -160,18 +149,10 @@
     }
 
     #[inline]
-    fn capacity(&self) -> usize {
-        self.buf.len()
-    }
-
-    #[inline]
     fn write_one(&mut self, value: u8) {
-        // We ensure this during `FileEncoder` construction.
-        debug_assert!(self.capacity() >= 1);
-
         let mut buffered = self.buffered;
 
-        if std::intrinsics::unlikely(buffered >= self.capacity()) {
+        if std::intrinsics::unlikely(buffered + 1 > BUF_SIZE) {
             self.flush();
             buffered = 0;
         }
@@ -187,13 +168,12 @@
 
     #[inline]
     fn write_all(&mut self, buf: &[u8]) {
-        let capacity = self.capacity();
         let buf_len = buf.len();
 
-        if std::intrinsics::likely(buf_len <= capacity) {
+        if std::intrinsics::likely(buf_len <= BUF_SIZE) {
             let mut buffered = self.buffered;
 
-            if std::intrinsics::unlikely(buf_len > capacity - buffered) {
+            if std::intrinsics::unlikely(buffered + buf_len > BUF_SIZE) {
                 self.flush();
                 buffered = 0;
             }
@@ -271,13 +251,11 @@
         fn $this_fn(&mut self, v: $int_ty) {
             const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>();
 
-            // We ensure this during `FileEncoder` construction.
-            debug_assert!(self.capacity() >= MAX_ENCODED_LEN);
-
             let mut buffered = self.buffered;
 
-            // This can't overflow. See assertion in `FileEncoder::with_capacity`.
-            if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > self.capacity()) {
+            // This can't overflow because BUF_SIZE and MAX_ENCODED_LEN are both
+            // quite small.
+            if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > BUF_SIZE) {
                 self.flush();
                 buffered = 0;
             }
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index a8fe560..5a0b8f9 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -1,13 +1,20 @@
-session_incorrect_cgu_reuse_type =
-    CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
-    [one] {"at least "}
-    *[other] {""}
-    }`{$expected_reuse}`
+session_binary_float_literal_not_supported = binary float literal is not supported
+session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
+
+session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
+
+session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
 
 session_cgu_not_recorded =
     CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
 
-session_feature_gate_error = {$explain}
+session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
+
+session_crate_name_empty = crate name must not be empty
+
+session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
+
+session_expr_parentheses_needed = parentheses are required to parse this as an expression
 
 session_feature_diagnostic_for_issue =
     see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information
@@ -15,66 +22,33 @@
 session_feature_diagnostic_help =
     add `#![feature({$feature})]` to the crate attributes to enable
 
-session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
-
-session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
-
-session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
-
-session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
-
-session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
-
-session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
-
-session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
-
-session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
-
-session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
-
-session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`
-
-session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
-
-session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
-
-session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
-
-session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
-
-session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
-
-session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
-
-session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
-
-session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
-
-session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
-
-session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
+session_feature_gate_error = {$explain}
 
 session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
 
-session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
+session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+session_incorrect_cgu_reuse_type =
+    CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
+    [one] {"at least "}
+    *[other] {""}
+    }`{$expected_reuse}`
 
-session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
+session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
 
-session_crate_name_empty = crate name must not be empty
+session_int_literal_too_large = integer literal is too large
+    .note = value exceeds limit of `{$limit}`
 
 session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
 
-session_expr_parentheses_needed = parentheses are required to parse this as an expression
+session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+    .label = invalid suffix `{$suffix}`
+    .help = valid suffixes are `f32` and `f64`
 
-session_skipping_const_checks = skipping const checks
-session_unleashed_feature_help_named = skipping check for `{$gate}` feature
-session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
+session_invalid_float_literal_width = invalid width `{$width}` for float literal
+    .help = valid widths are 32 and 64
 
-session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
-session_octal_float_literal_not_supported = octal float literal is not supported
-session_binary_float_literal_not_supported = binary float literal is not supported
-session_not_supported = not supported
+session_invalid_int_literal_width = invalid width `{$width}` for integer literal
+    .help = valid widths are 8, 16, 32, 64 and 128
 
 session_invalid_literal_suffix = suffixes on {$kind} literals are invalid
     .label = invalid suffix `{$suffix}`
@@ -87,19 +61,45 @@
     .label = invalid suffix `{$suffix}`
     .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
 
-session_invalid_float_literal_width = invalid width `{$width}` for float literal
-    .help = valid widths are 32 and 64
+session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
 
-session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
-    .label = invalid suffix `{$suffix}`
-    .help = valid suffixes are `f32` and `f64`
+session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
 
-session_int_literal_too_large = integer literal is too large
-    .note = value exceeds limit of `{$limit}`
-
-session_invalid_int_literal_width = invalid width `{$width}` for integer literal
-    .help = valid widths are 8, 16, 32, 64 and 128
-
-session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
+session_not_supported = not supported
 
 session_nul_in_c_str = null characters in C string literals are not supported
+
+session_octal_float_literal_not_supported = octal float literal is not supported
+session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
+
+session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist.
+
+session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist.
+
+session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
+
+session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
+
+session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
+
+session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
+
+session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
+
+session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
+
+session_skipping_const_checks = skipping const checks
+session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
+
+session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
+
+session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
+
+session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
+
+session_unleashed_feature_help_named = skipping check for `{$gate}` feature
+session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
+
+session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
+
+session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e2b8d3e..6c8c8e4 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -421,7 +421,7 @@
     GoodPath,
 }
 
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, Debug)]
 pub enum ResolveDocLinks {
     /// Do not resolve doc links.
     None,
@@ -1319,7 +1319,7 @@
     let (target, target_warnings) = target_result.unwrap_or_else(|e| {
         early_error(
             opts.error_format,
-            &format!(
+            format!(
                 "Error loading target specification: {}. \
                  Run `rustc --print target-list` for a list of built-in targets",
                 e
@@ -1327,15 +1327,14 @@
         )
     });
     for warning in target_warnings.warning_messages() {
-        early_warn(opts.error_format, &warning)
+        early_warn(opts.error_format, warning)
     }
 
     if !matches!(target.pointer_width, 16 | 32 | 64) {
         early_error(
             opts.error_format,
-            &format!(
-                "target specification was invalid: \
-             unrecognized target-pointer-width {}",
+            format!(
+                "target specification was invalid: unrecognized target-pointer-width {}",
                 target.pointer_width
             ),
         )
@@ -1599,7 +1598,7 @@
 
     let lint_cap = matches.opt_str("cap-lints").map(|cap| {
         lint::Level::from_str(&cap)
-            .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`")))
+            .unwrap_or_else(|| early_error(error_format, format!("unknown lint level: `{cap}`")))
     });
 
     (lint_opts, describe_lints, lint_cap)
@@ -1616,7 +1615,7 @@
 
         Some(arg) => early_error(
             ErrorOutputType::default(),
-            &format!(
+            format!(
                 "argument for `--color` must be auto, \
                  always or never (instead was `{arg}`)"
             ),
@@ -1691,7 +1690,7 @@
                 "future-incompat" => json_future_incompat = true,
                 s => early_error(
                     ErrorOutputType::default(),
-                    &format!("unknown `--json` option `{s}`"),
+                    format!("unknown `--json` option `{s}`"),
                 ),
             }
         }
@@ -1729,7 +1728,7 @@
 
             Some(arg) => early_error(
                 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
-                &format!(
+                format!(
                     "argument for `--error-format` must be `human`, `json` or \
                      `short` (instead was `{arg}`)"
                 ),
@@ -1763,7 +1762,7 @@
         Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
             early_error(
                 ErrorOutputType::default(),
-                &format!(
+                format!(
                     "argument for `--edition` must be one of: \
                      {EDITION_NAME_LIST}. (instead was `{arg}`)"
                 ),
@@ -1782,7 +1781,7 @@
         } else {
             format!("edition {edition} is unstable and only available with -Z unstable-options")
         };
-        early_error(ErrorOutputType::default(), &msg)
+        early_error(ErrorOutputType::default(), msg)
     }
 
     edition
@@ -1827,7 +1826,7 @@
                 let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
                     early_error(
                         error_format,
-                        &format!(
+                        format!(
                             "unknown emission type: `{shorthand}` - expected one of: {display}",
                             display = OutputType::shorthands_display(),
                         ),
@@ -1866,7 +1865,7 @@
                     for ot in &incompatible {
                         early_warn(
                             error_format,
-                            &format!(
+                            format!(
                                 "`--emit={ot}` with `-o` incompatible with \
                                  `-C codegen-units=N` for N > 1",
                             ),
@@ -1908,7 +1907,7 @@
     error_format: ErrorOutputType,
 ) -> Vec<PrintRequest> {
     let mut prints = Vec::<PrintRequest>::new();
-    if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
+    if cg.target_cpu.as_ref().is_some_and(|s| s == "help") {
         prints.push(PrintRequest::TargetCPUs);
         cg.target_cpu = None;
     };
@@ -1970,7 +1969,7 @@
                 let prints = prints.join(", ");
                 early_error(
                     error_format,
-                    &format!("unknown print request `{req}`. Valid print requests are: {prints}"),
+                    format!("unknown print request `{req}`. Valid print requests are: {prints}"),
                 );
             }
         }
@@ -1987,7 +1986,7 @@
         Some(target) if target.ends_with(".json") => {
             let path = Path::new(&target);
             TargetTriple::from_path(path).unwrap_or_else(|_| {
-                early_error(error_format, &format!("target file {path:?} does not exist"))
+                early_error(error_format, format!("target file {path:?} does not exist"))
             })
         }
         Some(target) => TargetTriple::TargetTriple(target),
@@ -2028,7 +2027,7 @@
             arg => {
                 early_error(
                     error_format,
-                    &format!(
+                    format!(
                         "optimization level needs to be \
                             between 0-3, s or z (instead was `{arg}`)"
                     ),
@@ -2059,7 +2058,7 @@
         Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
         Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
         Some(s) => {
-            early_error(error_format, &format!("unexpected incremental state assertion value: {s}"))
+            early_error(error_format, format!("unexpected incremental state assertion value: {s}"))
         }
         None => None,
     }
@@ -2086,13 +2085,13 @@
                 } else {
                     ", the `-Z unstable-options` flag must also be passed to use it"
                 };
-                early_error(error_format, &format!("library kind `link-arg` is unstable{why}"))
+                early_error(error_format, format!("library kind `link-arg` is unstable{why}"))
             }
             NativeLibKind::LinkArg
         }
         _ => early_error(
             error_format,
-            &format!(
+            format!(
                 "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
             ),
         ),
@@ -2127,16 +2126,13 @@
                 } else {
                     ", the `-Z unstable-options` flag must also be passed to use it"
                 };
-                early_error(
-                    error_format,
-                    &format!("linking modifier `{modifier}` is unstable{why}"),
-                )
+                early_error(error_format, format!("linking modifier `{modifier}` is unstable{why}"))
             }
         };
         let assign_modifier = |dst: &mut Option<bool>| {
             if dst.is_some() {
                 let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
-                early_error(error_format, &msg)
+                early_error(error_format, msg)
             } else {
                 *dst = Some(value);
             }
@@ -2173,7 +2169,7 @@
             // string, like `modifiers = ""`.
             _ => early_error(
                 error_format,
-                &format!(
+                format!(
                     "unknown linking modifier `{modifier}`, expected one \
                      of: bundle, verbatim, whole-archive, as-needed"
                 ),
@@ -2303,7 +2299,7 @@
                     }
                     "nounused" => nounused_dep = true,
                     "force" => force = true,
-                    _ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
+                    _ => early_error(error_format, format!("unknown --extern option `{opt}`")),
                 }
             }
         }
@@ -2369,7 +2365,7 @@
 
     let unparsed_crate_types = matches.opt_strs("crate-type");
     let crate_types = parse_crate_types_from_list(unparsed_crate_types)
-        .unwrap_or_else(|e| early_error(error_format, &e));
+        .unwrap_or_else(|e| early_error(error_format, e));
 
     let mut unstable_opts = UnstableOptions::build(matches, error_format);
     let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
@@ -2597,7 +2593,7 @@
     };
 
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
-        early_error(error_format, &format!("Current directory is invalid: {e}"));
+        early_error(error_format, format!("Current directory is invalid: {e}"));
     });
 
     let remap = FilePathMapping::new(remap_path_prefix.clone());
@@ -2669,7 +2665,7 @@
         "mir-cfg" => MirCFG,
         name => early_error(
             efmt,
-            &format!(
+            format!(
                 "argument to `unpretty` must be one of `normal`, `identified`, \
                             `expanded`, `expanded,identified`, `expanded,hygiene`, \
                             `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
@@ -2747,7 +2743,7 @@
             if opt.name != "Z" && !has_z_unstable_option {
                 early_error(
                     ErrorOutputType::default(),
-                    &format!(
+                    format!(
                         "the `-Z unstable-options` flag must also be passed to enable \
                          the flag `{}`",
                         opt.name
@@ -2760,11 +2756,10 @@
             match opt.stability {
                 OptionStability::Unstable => {
                     let msg = format!(
-                        "the option `{}` is only accepted on the \
-                         nightly compiler",
+                        "the option `{}` is only accepted on the nightly compiler",
                         opt.name
                     );
-                    early_error(ErrorOutputType::default(), &msg);
+                    early_error(ErrorOutputType::default(), msg);
                 }
                 OptionStability::Stable => {}
             }
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index dd172180..dc475e8 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,7 +6,8 @@
 use crate::utils::NativeLibKind;
 use crate::Session;
 use rustc_ast as ast;
-use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock};
+use rustc_data_structures::owned_slice::OwnedSlice;
+use rustc_data_structures::sync::{self, AppendOnlyIndexVec, RwLock};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
 use rustc_span::hygiene::{ExpnHash, ExpnId};
@@ -203,11 +204,11 @@
 /// metadata in library -- this trait just serves to decouple rustc_metadata from
 /// the archive reader, which depends on LLVM.
 pub trait MetadataLoader: std::fmt::Debug {
-    fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
-    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
+    fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
+    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
 }
 
-pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync;
+pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync;
 
 /// A store of Rust crates, through which their metadata can be accessed.
 ///
@@ -252,7 +253,7 @@
     fn import_source_files(&self, sess: &Session, cnum: CrateNum);
 }
 
-pub type CrateStoreDyn = dyn CrateStore + sync::Sync + sync::Send;
+pub type CrateStoreDyn = dyn CrateStore + sync::DynSync + sync::DynSend;
 
 pub struct Untracked {
     pub cstore: RwLock<Box<CrateStoreDyn>>,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 5976b9a..2c4c4a7 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -329,21 +329,21 @@
                     match value {
                         None => early_error(
                             error_format,
-                            &format!(
+                            format!(
                                 "{0} option `{1}` requires {2} ({3} {1}=<value>)",
                                 outputname, key, type_desc, prefix
                             ),
                         ),
                         Some(value) => early_error(
                             error_format,
-                            &format!(
+                            format!(
                                 "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected"
                             ),
                         ),
                     }
                 }
             }
-            None => early_error(error_format, &format!("unknown {outputname} option: `{key}`")),
+            None => early_error(error_format, format!("unknown {outputname} option: `{key}`")),
         }
     }
     return op;
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 5cc9c62..7b396dd 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -289,7 +289,7 @@
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
@@ -307,7 +307,7 @@
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         diagnostic: BuiltinLintDiagnostics,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index a988d7f..bbe52db 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -211,6 +211,9 @@
 
     /// Set of enabled features for the current target, including unstable ones.
     pub unstable_target_features: FxIndexSet<Symbol>,
+
+    /// The version of the rustc process, possibly including a commit hash and description.
+    pub cfg_version: &'static str,
 }
 
 pub struct PerfStats {
@@ -490,20 +493,6 @@
     }
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn span_err_or_warn<S: Into<MultiSpan>>(
-        &self,
-        is_warning: bool,
-        sp: S,
-        msg: impl Into<DiagnosticMessage>,
-    ) {
-        if is_warning {
-            self.span_warn(sp, msg);
-        } else {
-            self.span_err(sp, msg);
-        }
-    }
-    #[rustc_lint_diagnostics]
-    #[track_caller]
     pub fn span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -1380,6 +1369,7 @@
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     target_override: Option<Target>,
+    cfg_version: &'static str,
 ) -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -1388,8 +1378,8 @@
         .lint_opts
         .iter()
         .rfind(|&(key, _)| *key == "warnings")
-        .map_or(false, |&(_, level)| level == lint::Allow);
-    let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
+        .is_some_and(|&(_, level)| level == lint::Allow);
+    let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
     let can_emit_warnings = !(warnings_allow || cap_lints_allow);
 
     let sysroot = match &sopts.maybe_sysroot {
@@ -1400,10 +1390,10 @@
     let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
     let host_triple = TargetTriple::from_triple(config::host_triple());
     let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
-        early_error(sopts.error_format, &format!("Error loading host specification: {e}"))
+        early_error(sopts.error_format, format!("Error loading host specification: {e}"))
     });
     for warning in target_warnings.warning_messages() {
-        early_warn(sopts.error_format, &warning)
+        early_warn(sopts.error_format, warning)
     }
 
     let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
@@ -1445,7 +1435,7 @@
         match profiler {
             Ok(profiler) => Some(Arc::new(profiler)),
             Err(e) => {
-                early_warn(sopts.error_format, &format!("failed to create profiler: {e}"));
+                early_warn(sopts.error_format, format!("failed to create profiler: {e}"));
                 None
             }
         }
@@ -1524,6 +1514,7 @@
         asm_arch,
         target_features: Default::default(),
         unstable_target_features: Default::default(),
+        cfg_version,
     };
 
     validate_commandline_args_with_session_available(&sess);
@@ -1741,18 +1732,22 @@
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
+#[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"]
+pub fn early_error_no_abort(
+    output: config::ErrorOutputType,
+    msg: impl Into<DiagnosticMessage>,
+) -> ErrorGuaranteed {
     early_error_handler(output).struct_err(msg).emit()
 }
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
+pub fn early_error(output: config::ErrorOutputType, msg: impl Into<DiagnosticMessage>) -> ! {
     early_error_handler(output).struct_fatal(msg).emit()
 }
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
+pub fn early_warn(output: config::ErrorOutputType, msg: impl Into<DiagnosticMessage>) {
     early_error_handler(output).struct_warn(msg).emit()
 }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 8c58b52..f65a6aa 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -146,7 +146,12 @@
 impl StableCrateId {
     /// Computes the stable ID for a crate with the given name and
     /// `-Cmetadata` arguments.
-    pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    pub fn new(
+        crate_name: Symbol,
+        is_exe: bool,
+        mut metadata: Vec<String>,
+        cfg_version: &'static str,
+    ) -> StableCrateId {
         let mut hasher = StableHasher::new();
         // We must hash the string text of the crate name, not the id, as the id is not stable
         // across builds.
@@ -180,7 +185,7 @@
         if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
             hasher.write(val.to_string_lossy().into_owned().as_bytes())
         } else {
-            hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes());
+            hasher.write(cfg_version.as_bytes())
         }
 
         StableCrateId(hasher.finish())
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index c669b64..6755657 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -320,7 +320,6 @@
             // Stop going up the backtrace once include! is encountered
             if expn_data.is_root()
                 || expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include)
-                || expn_data.kind == ExpnKind::Inlined
             {
                 break;
             }
@@ -1058,8 +1057,6 @@
     AstPass(AstPass),
     /// Desugaring done by the compiler during HIR lowering.
     Desugaring(DesugaringKind),
-    /// MIR inlining
-    Inlined,
 }
 
 impl ExpnKind {
@@ -1073,7 +1070,6 @@
             },
             ExpnKind::AstPass(kind) => kind.descr().to_string(),
             ExpnKind::Desugaring(kind) => format!("desugaring of {}", kind.descr()),
-            ExpnKind::Inlined => "inlined source".to_string(),
         }
     }
 }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 7bbab34..eae3f0f 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -20,6 +20,7 @@
 #![feature(min_specialization)]
 #![feature(rustc_attrs)]
 #![feature(let_chains)]
+#![feature(round_char_boundary)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
@@ -593,12 +594,6 @@
         matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo
     }
 
-    /// Returns `true` if this span comes from MIR inlining.
-    pub fn is_inlined(self) -> bool {
-        let outer_expn = self.ctxt().outer_expn_data();
-        matches!(outer_expn.kind, ExpnKind::Inlined)
-    }
-
     /// Returns `true` if `span` originates in a derive-macro's expansion.
     pub fn in_derive_expansion(self) -> bool {
         matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
@@ -753,7 +748,7 @@
         self.ctxt()
             .outer_expn_data()
             .allow_internal_unstable
-            .map_or(false, |features| features.iter().any(|&f| f == feature))
+            .is_some_and(|features| features.iter().any(|&f| f == feature))
     }
 
     /// Checks if this span arises from a compiler desugaring of kind `kind`.
@@ -1256,29 +1251,6 @@
     }
 }
 
-#[derive(HashStable_Generic)]
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
-pub enum DebuggerVisualizerType {
-    Natvis,
-    GdbPrettyPrinter,
-}
-
-/// A single debugger visualizer file.
-#[derive(HashStable_Generic)]
-#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
-pub struct DebuggerVisualizerFile {
-    /// The complete debugger visualizer source.
-    pub src: Lrc<[u8]>,
-    /// Indicates which visualizer type this targets.
-    pub visualizer_type: DebuggerVisualizerType,
-}
-
-impl DebuggerVisualizerFile {
-    pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType) -> Self {
-        DebuggerVisualizerFile { src, visualizer_type }
-    }
-}
-
 #[derive(Clone)]
 pub enum SourceFileLines {
     /// The source file lines, in decoded (random-access) form.
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 1294a8b..1824510 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -14,7 +14,9 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
-use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock};
+use rustc_data_structures::sync::{
+    AtomicU32, IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock,
+};
 use std::cmp;
 use std::hash::Hash;
 use std::path::{self, Path, PathBuf};
@@ -176,7 +178,7 @@
     used_address_space: AtomicU32,
 
     files: RwLock<SourceMapFiles>,
-    file_loader: Box<dyn FileLoader + Sync + Send>,
+    file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
     // This is used to apply the file path remapping as specified via
     // `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
     path_mapping: FilePathMapping,
@@ -202,7 +204,7 @@
         SourceMap {
             used_address_space: AtomicU32::new(0),
             files: Default::default(),
-            file_loader,
+            file_loader: IntoDynSyncSend(file_loader),
             path_mapping,
             hash_kind,
         }
@@ -637,7 +639,7 @@
         self.span_to_source(sp, |src, start_index, end_index| {
             Ok(src.get(start_index..end_index).is_some())
         })
-        .map_or(false, |is_accessible| is_accessible)
+        .is_ok_and(|is_accessible| is_accessible)
     }
 
     /// Returns the source snippet as `String` corresponding to the given `Span`.
@@ -833,7 +835,7 @@
             }
             return Ok(true);
         })
-        .map_or(false, |is_accessible| is_accessible)
+        .is_ok_and(|is_accessible| is_accessible)
     }
 
     /// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
@@ -965,7 +967,7 @@
         for _ in 0..limit.unwrap_or(100_usize) {
             sp = self.next_point(sp);
             if let Ok(ref snippet) = self.span_to_snippet(sp) {
-                if expect.map_or(false, |es| snippet == es) {
+                if expect.is_some_and(|es| snippet == es) {
                     break;
                 }
                 if expect.is_none() && snippet.chars().any(|c| !c.is_whitespace()) {
@@ -1017,36 +1019,19 @@
 
         let src = local_begin.sf.external_src.borrow();
 
-        // We need to extend the snippet to the end of the src rather than to end_index so when
-        // searching forwards for boundaries we've got somewhere to search.
-        let snippet = if let Some(ref src) = local_begin.sf.src {
-            &src[start_index..]
+        let snippet = if let Some(src) = &local_begin.sf.src {
+            src
         } else if let Some(src) = src.get_source() {
-            &src[start_index..]
+            src
         } else {
             return 1;
         };
-        debug!("snippet=`{:?}`", snippet);
 
-        let mut target = if forwards { end_index + 1 } else { end_index - 1 };
-        debug!("initial target=`{:?}`", target);
-
-        while !snippet.is_char_boundary(target - start_index) && target < source_len {
-            target = if forwards {
-                target + 1
-            } else {
-                match target.checked_sub(1) {
-                    Some(target) => target,
-                    None => {
-                        break;
-                    }
-                }
-            };
-            debug!("target=`{:?}`", target);
+        if forwards {
+            (snippet.ceil_char_boundary(end_index + 1) - end_index) as u32
+        } else {
+            (end_index - snippet.floor_char_boundary(end_index - 1)) as u32
         }
-        debug!("final target=`{:?}`", target);
-
-        if forwards { (target - end_index) as u32 } else { (end_index - target) as u32 }
     }
 
     pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9951d8f..874d578 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -164,6 +164,7 @@
         Capture,
         Center,
         Clone,
+        ConstParamTy,
         Context,
         Continue,
         Copy,
@@ -1583,6 +1584,7 @@
         unrestricted_attribute_tokens,
         unsafe_block_in_unsafe_fn,
         unsafe_cell,
+        unsafe_cell_from_mut,
         unsafe_no_drop_flag,
         unsafe_pin_internals,
         unsize,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index a3f2629..254ede4 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -220,7 +220,7 @@
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
             ty::FnDef(def_id, substs)
-            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
 
@@ -241,6 +241,8 @@
                 Ok(self)
             }
 
+            ty::Alias(ty::Inherent, _) => panic!("unexpected inherent projection"),
+
             _ => self.pretty_print_type(ty),
         }
     }
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index c974068..692542d 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -107,7 +107,7 @@
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::config::SymbolManglingVersion;
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index c281aa7..9fa4912 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -272,12 +272,11 @@
             s.push('E');
             compress(dict, DictKey::Region(region), &mut s);
         }
-        RegionKind::ReErased => {
+        RegionKind::ReEarlyBound(..) | RegionKind::ReErased => {
             s.push_str("u6region");
             compress(dict, DictKey::Region(region), &mut s);
         }
-        RegionKind::ReEarlyBound(..)
-        | RegionKind::ReFree(..)
+        RegionKind::ReFree(..)
         | RegionKind::ReStatic
         | RegionKind::ReError(_)
         | RegionKind::ReVar(..)
@@ -673,6 +672,14 @@
             typeid.push_str(&s);
         }
 
+        // Type parameters
+        ty::Param(..) => {
+            // u5param as vendor extended type
+            let mut s = String::from("u5param");
+            compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
+            typeid.push_str(&s);
+        }
+
         // Unexpected types
         ty::Bound(..)
         | ty::Error(..)
@@ -680,7 +687,6 @@
         | ty::GeneratorWitnessMIR(..)
         | ty::Infer(..)
         | ty::Alias(..)
-        | ty::Param(..)
         | ty::Placeholder(..) => {
             bug!("encode_ty: unexpected `{:?}`", ty.kind());
         }
@@ -689,6 +695,42 @@
     typeid
 }
 
+/// Transforms predicates for being encoded and used in the substitution dictionary.
+fn transform_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicates: &List<ty::PolyExistentialPredicate<'tcx>>,
+    _options: EncodeTyOptions,
+) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
+    let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates
+        .iter()
+        .filter_map(|predicate| match predicate.skip_binder() {
+            ty::ExistentialPredicate::Trait(trait_ref) => {
+                let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id);
+                Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait(
+                    ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
+                )))
+            }
+            ty::ExistentialPredicate::Projection(..) => None,
+            ty::ExistentialPredicate::AutoTrait(..) => Some(predicate),
+        })
+        .collect();
+    tcx.mk_poly_existential_predicates(&predicates)
+}
+
+/// Transforms substs for being encoded and used in the substitution dictionary.
+fn transform_substs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    substs: SubstsRef<'tcx>,
+    options: TransformTyOptions,
+) -> SubstsRef<'tcx> {
+    let substs = substs.iter().map(|subst| match subst.unpack() {
+        GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
+        GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
+        _ => subst,
+    });
+    tcx.mk_substs_from_iter(substs)
+}
+
 // Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all
 // c_void types into unit types unconditionally, generalizes pointers if
 // TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if
@@ -697,7 +739,7 @@
     let mut ty = ty;
 
     match ty.kind() {
-        ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) | ty::Dynamic(..) => {}
+        ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) => {}
 
         ty::Bool => {
             if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
@@ -776,7 +818,7 @@
                 let field = variant.fields.iter().find(|field| {
                     let ty = tcx.type_of(field.did).subst_identity();
                     let is_zst =
-                        tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.is_zst());
+                        tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.is_zst());
                     !is_zst
                 });
                 if let Some(field) = field {
@@ -870,6 +912,14 @@
             }
         }
 
+        ty::Dynamic(predicates, _region, kind) => {
+            ty = tcx.mk_dynamic(
+                transform_predicates(tcx, predicates, options),
+                tcx.lifetimes.re_erased,
+                *kind,
+            );
+        }
+
         ty::Bound(..)
         | ty::Error(..)
         | ty::GeneratorWitness(..)
@@ -885,20 +935,6 @@
     ty
 }
 
-/// Transforms substs for being encoded and used in the substitution dictionary.
-fn transform_substs<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
-    options: TransformTyOptions,
-) -> SubstsRef<'tcx> {
-    let substs = substs.iter().map(|subst| match subst.unpack() {
-        GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
-        GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
-        _ => subst,
-    });
-    tcx.mk_substs_from_iter(substs)
-}
-
 /// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
 /// extended type qualifiers and types for Rust types that are not used at the FFI boundary.
 #[instrument(level = "trace", skip(tcx))]
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 2235524..4cccc63 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -433,7 +433,7 @@
             // Mangle all nominal types as paths.
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => {
                 self = self.print_def_path(def_id, substs)?;
@@ -482,6 +482,7 @@
                 self = r.print(self)?;
             }
 
+            ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"),
             ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"),
             ty::GeneratorWitnessMIR(..) => bug!("symbol_names: unexpected `GeneratorWitnessMIR`"),
         }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
index b69ade7..9ac7323 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
@@ -4,7 +4,7 @@
 pub fn target() -> Target {
     let arch = Arch::Arm64;
     let mut base = opts("macos", arch);
-    base.cpu = "apple-a14".into();
+    base.cpu = "apple-m1".into();
     base.max_atomic_width = Some(128);
 
     // FIXME: The leak sanitizer currently fails the tests, see #88132.
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index 2b135b6..e2df7e0 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let llvm_target = "arm64-apple-ios-macabi";
+    let llvm_target = "arm64-apple-ios14.0-macabi";
 
     let arch = Arch::Arm64_macabi;
     let mut base = opts("ios", arch);
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
index d0c950c..523eb6b 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
@@ -1,10 +1,15 @@
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.max_atomic_width = Some(128);
     base.supports_xray = true;
     base.features = "+v8a".into();
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::LEAK
+        | SanitizerSet::MEMORY
+        | SanitizerSet::THREAD;
 
     Target {
         llvm_target: "aarch64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
index 5a3e2a7..9f3b0fa 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@
 use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let llvm_target = "x86_64-apple-ios-macabi";
+    let llvm_target = "x86_64-apple-ios14.0-macabi";
 
     let arch = Arch::X86_64_macabi;
     let mut base = opts("ios", arch);
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 8fea3fc..217ba71 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -1,17 +1,13 @@
 trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
 
-trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
-
 trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
     .label = empty on-clause here
 
+trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
+
 trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
     .label = invalid on-clause here
 
-trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
-    .label = expected value here
-    .note = eg `#[rustc_on_unimplemented(message="foo")]`
-
 trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
         [none] {""}
        *[default] {" "}for type `{$self_desc}`
@@ -21,4 +17,8 @@
     .positive_implementation_here = positive implementation here
     .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
 
-trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
+trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
+    .label = expected value here
+    .note = eg `#[rustc_on_unimplemented(message="foo")]`
+
+trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 142c200..312bd38 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -5,7 +5,7 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
-use rustc_middle::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::ty::{GenericArg, ToPredicate};
 use rustc_span::DUMMY_SP;
@@ -82,8 +82,8 @@
     fn enter_canonical_trait_query<K, R>(
         &mut self,
         canonical_key: &Canonical<'tcx, K>,
-        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, R>>
+        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
+    ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
     where
         K: TypeFoldable<TyCtxt<'tcx>>,
         R: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -110,8 +110,8 @@
     fn enter_canonical_trait_query<K, R>(
         &mut self,
         canonical_key: &Canonical<'tcx, K>,
-        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, R>>
+        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
+    ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
     where
         K: TypeFoldable<TyCtxt<'tcx>>,
         R: Debug + TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 25cc82f..f32ff04 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -2,7 +2,6 @@
 
 use super::search_graph::OverflowHandler;
 use super::{EvalCtxt, SolverMode};
-use crate::solve::CanonicalResponseExt;
 use crate::traits::coherence;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def_id::DefId;
@@ -333,8 +332,7 @@
         candidates: &mut Vec<Candidate<'tcx>>,
     ) {
         let tcx = self.tcx();
-        // FIXME: We also have to normalize opaque types, not sure where to best fit that in.
-        let &ty::Alias(ty::Projection, projection_ty) = goal.predicate.self_ty().kind() else {
+        let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else {
             return
         };
 
@@ -356,8 +354,11 @@
                         }),
                     );
                     ecx.add_goal(normalizes_to_goal);
-                    let _ = ecx.try_evaluate_added_goals()?;
+                    let _ = ecx.try_evaluate_added_goals().inspect_err(|_| {
+                        debug!("self type normalization failed");
+                    })?;
                     let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
+                    debug!(?normalized_ty, "self type normalized");
                     // NOTE: Alternatively we could call `evaluate_goal` here and only
                     // have a `Normalized` candidate. This doesn't work as long as we
                     // use `CandidateSource` in winnowing.
@@ -506,10 +507,12 @@
             | ty::Param(_)
             | ty::Placeholder(..)
             | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
+            | ty::Alias(ty::Inherent, _)
             | ty::Error(_) => return,
             ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
             | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
-            ty::Alias(_, alias_ty) => alias_ty,
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
         };
 
         for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
@@ -740,13 +743,18 @@
             SolverMode::Normal => {
                 let param_env_responses = candidates
                     .iter()
-                    .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
+                    .filter(|c| {
+                        matches!(
+                            c.source,
+                            CandidateSource::ParamEnv(_) | CandidateSource::AliasBound
+                        )
+                    })
                     .map(|c| c.result)
                     .collect::<Vec<_>>();
                 if let Some(result) = self.try_merge_responses(&param_env_responses) {
-                    if result.has_only_region_constraints() {
-                        return Ok(result);
-                    }
+                    // We strongly prefer alias and param-env bounds here, even if they affect inference.
+                    // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/11.
+                    return Ok(result);
                 }
             }
         }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 63a73f8..f91c672 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -1,4 +1,4 @@
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -9,7 +9,11 @@
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
+use rustc_middle::traits::solve::{
+    CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
+    PredefinedOpaquesData, QueryResult,
+};
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
     TypeVisitor,
@@ -44,6 +48,9 @@
     infcx: &'a InferCtxt<'tcx>,
 
     pub(super) var_values: CanonicalVarValues<'tcx>,
+
+    predefined_opaques_in_body: PredefinedOpaques<'tcx>,
+
     /// The highest universe index nameable by the caller.
     ///
     /// When we enter a new binder inside of the query we create new universes
@@ -126,6 +133,11 @@
         let mut ecx = EvalCtxt {
             search_graph: &mut search_graph,
             infcx: self,
+            // Only relevant when canonicalizing the response,
+            // which we don't do within this evaluation context.
+            predefined_opaques_in_body: self
+                .tcx
+                .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()),
             // Only relevant when canonicalizing the response.
             max_input_universe: ty::UniverseIndex::ROOT,
             var_values: CanonicalVarValues::dummy(),
@@ -162,29 +174,53 @@
     fn evaluate_canonical_goal(
         tcx: TyCtxt<'tcx>,
         search_graph: &'a mut search_graph::SearchGraph<'tcx>,
-        canonical_goal: CanonicalGoal<'tcx>,
+        canonical_input: CanonicalInput<'tcx>,
     ) -> QueryResult<'tcx> {
         // Deal with overflow, caching, and coinduction.
         //
         // The actual solver logic happens in `ecx.compute_goal`.
-        search_graph.with_new_goal(tcx, canonical_goal, |search_graph| {
+        search_graph.with_new_goal(tcx, canonical_input, |search_graph| {
             let intercrate = match search_graph.solver_mode() {
                 SolverMode::Normal => false,
                 SolverMode::Coherence => true,
             };
-            let (ref infcx, goal, var_values) = tcx
+            let (ref infcx, input, var_values) = tcx
                 .infer_ctxt()
                 .intercrate(intercrate)
-                .build_with_canonical(DUMMY_SP, &canonical_goal);
+                .with_opaque_type_inference(canonical_input.value.anchor)
+                .build_with_canonical(DUMMY_SP, &canonical_input);
+
+            for &(a, b) in &input.predefined_opaques_in_body.opaque_types {
+                let InferOk { value: (), obligations } = infcx
+                    .register_hidden_type_in_new_solver(a, input.goal.param_env, b)
+                    .expect("expected opaque type instantiation to succeed");
+                // We're only registering opaques already defined by the caller,
+                // so we're not responsible for proving that they satisfy their
+                // item bounds, unless we use them in a normalizes-to goal,
+                // which is handled in `EvalCtxt::unify_existing_opaque_tys`.
+                let _ = obligations;
+            }
             let mut ecx = EvalCtxt {
                 infcx,
                 var_values,
-                max_input_universe: canonical_goal.max_universe,
+                predefined_opaques_in_body: input.predefined_opaques_in_body,
+                max_input_universe: canonical_input.max_universe,
                 search_graph,
                 nested_goals: NestedGoals::new(),
                 tainted: Ok(()),
             };
-            ecx.compute_goal(goal)
+
+            let result = ecx.compute_goal(input.goal);
+
+            // When creating a query response we clone the opaque type constraints
+            // instead of taking them. This would cause an ICE here, since we have
+            // assertions against dropping an `InferCtxt` without taking opaques.
+            // FIXME: Once we remove support for the old impl we can remove this.
+            if input.anchor != DefiningAnchor::Error {
+                let _ = infcx.take_opaque_types();
+            }
+
+            result
         })
     }
 
@@ -199,7 +235,8 @@
         let canonical_response =
             EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
 
-        let has_changed = !canonical_response.value.var_values.is_identity();
+        let has_changed = !canonical_response.value.var_values.is_identity()
+            || !canonical_response.value.external_constraints.opaque_types.is_empty();
         let (certainty, nested_goals) = self.instantiate_and_apply_query_response(
             goal.param_env,
             orig_values,
@@ -418,6 +455,7 @@
         let mut ecx = EvalCtxt {
             infcx: self.infcx,
             var_values: self.var_values,
+            predefined_opaques_in_body: self.predefined_opaques_in_body,
             max_input_universe: self.max_input_universe,
             search_graph: self.search_graph,
             nested_goals: self.nested_goals.clone(),
@@ -682,4 +720,56 @@
             | rustc_transmute::Answer::IfAny(_) => Err(NoSolution),
         }
     }
+
+    pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool {
+        self.infcx.opaque_type_origin(def_id).is_some()
+    }
+
+    pub(super) fn register_opaque_ty(
+        &mut self,
+        a: ty::OpaqueTypeKey<'tcx>,
+        b: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Result<(), NoSolution> {
+        let InferOk { value: (), obligations } =
+            self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
+        self.add_goals(obligations.into_iter().map(|obligation| obligation.into()));
+        Ok(())
+    }
+
+    // Do something for each opaque/hidden pair defined with `def_id` in the
+    // current inference context.
+    pub(super) fn unify_existing_opaque_tys(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        key: ty::OpaqueTypeKey<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> Vec<CanonicalResponse<'tcx>> {
+        // FIXME: Super inefficient to be cloning this...
+        let opaques = self.infcx.clone_opaque_types_for_query_response();
+
+        let mut values = vec![];
+        for (candidate_key, candidate_ty) in opaques {
+            if candidate_key.def_id != key.def_id {
+                continue;
+            }
+            values.extend(self.probe(|ecx| {
+                for (a, b) in std::iter::zip(candidate_key.substs, key.substs) {
+                    ecx.eq(param_env, a, b)?;
+                }
+                ecx.eq(param_env, candidate_ty, ty)?;
+                let mut obl = vec![];
+                ecx.infcx.add_item_bounds_for_hidden_type(
+                    candidate_key,
+                    ObligationCause::dummy(),
+                    param_env,
+                    candidate_ty,
+                    &mut obl,
+                );
+                ecx.add_goals(obl.into_iter().map(Into::into));
+                ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }));
+        }
+        values
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 67ad7fb..fdb209f 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -8,16 +8,19 @@
 /// section of the [rustc-dev-guide][c].
 ///
 /// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
-use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
+use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
 use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
 use crate::solve::{CanonicalResponse, QueryResult, Response};
 use rustc_index::IndexVec;
 use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
+use rustc_infer::infer::InferOk;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData, MaybeCause};
-use rustc_middle::ty::{self, BoundVar, GenericArgKind};
+use rustc_middle::traits::solve::{
+    ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
+};
+use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty};
 use rustc_span::DUMMY_SP;
 use std::iter;
 use std::ops::Deref;
@@ -28,13 +31,21 @@
     pub(super) fn canonicalize_goal(
         &self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
-    ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
+    ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalInput<'tcx>) {
         let mut orig_values = Default::default();
         let canonical_goal = Canonicalizer::canonicalize(
             self.infcx,
             CanonicalizeMode::Input,
             &mut orig_values,
-            goal,
+            QueryInput {
+                goal,
+                anchor: self.infcx.defining_use_anchor,
+                predefined_opaques_in_body: self.tcx().mk_predefined_opaques_in_body(
+                    PredefinedOpaquesData {
+                        opaque_types: self.infcx.clone_opaque_types_for_query_response(),
+                    },
+                ),
+            },
         );
         (orig_values, canonical_goal)
     }
@@ -138,7 +149,13 @@
                 region_constraints,
             )
         });
-        let opaque_types = self.infcx.clone_opaque_types_for_query_response();
+
+        let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
+        // Only return opaque type keys for newly-defined opaques
+        opaque_types.retain(|(a, _)| {
+            self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
+        });
+
         Ok(self
             .tcx()
             .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
@@ -164,10 +181,10 @@
 
         let nested_goals = self.unify_query_var_values(param_env, &original_values, var_values)?;
 
-        // FIXME: implement external constraints.
-        let ExternalConstraintsData { region_constraints, opaque_types: _ } =
+        let ExternalConstraintsData { region_constraints, opaque_types } =
             external_constraints.deref();
         self.register_region_constraints(region_constraints);
+        self.register_opaque_types(param_env, opaque_types)?;
 
         Ok((certainty, nested_goals))
     }
@@ -287,4 +304,19 @@
             let _ = member_constraint;
         }
     }
+
+    fn register_opaque_types(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
+    ) -> Result<(), NoSolution> {
+        for &(a, b) in opaque_types {
+            let InferOk { value: (), obligations } =
+                self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
+            // It's sound to drop these obligations, since the normalizes-to goal
+            // is responsible for proving these obligations.
+            let _ = obligations;
+        }
+        Ok(())
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 32bd10f..4a40319 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -133,12 +133,14 @@
                                 | ty::PredicateKind::ObjectSafe(_)
                                 | ty::PredicateKind::ClosureKind(_, _, _)
                                 | ty::PredicateKind::ConstEvaluatable(_)
-                                | ty::PredicateKind::TypeWellFormedFromEnv(_)
                                 | ty::PredicateKind::Ambiguous => {
                                     FulfillmentErrorCode::CodeSelectionError(
                                         SelectionError::Unimplemented,
                                     )
                                 }
+                                ty::PredicateKind::TypeWellFormedFromEnv(_) => {
+                                    bug!("unexpected goal: {goal:?}")
+                                }
                             },
                             root_obligation: obligation,
                         });
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index d94679f..26ace28f 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -24,6 +24,7 @@
 mod canonicalize;
 mod eval_ctxt;
 mod fulfill;
+mod opaques;
 mod project_goals;
 mod search_graph;
 mod trait_goals;
@@ -212,7 +213,7 @@
             );
         }
 
-        match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) {
+        match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
             (None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"),
 
             // RHS is not a projection, only way this is true is if LHS normalizes-to RHS
@@ -238,34 +239,34 @@
                     evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes).ok(),
                 );
                 // Relate via substs
-                candidates.extend(
-                    self.probe(|ecx| {
-                        let span = tracing::span!(
-                            tracing::Level::DEBUG,
-                            "compute_alias_relate_goal(relate_via_substs)",
-                            ?alias_lhs,
-                            ?alias_rhs,
-                            ?direction
-                        );
-                        let _enter = span.enter();
+                let subst_relate_response = self.probe(|ecx| {
+                    let span = tracing::span!(
+                        tracing::Level::DEBUG,
+                        "compute_alias_relate_goal(relate_via_substs)",
+                        ?alias_lhs,
+                        ?alias_rhs,
+                        ?direction
+                    );
+                    let _enter = span.enter();
 
-                        match direction {
-                            ty::AliasRelationDirection::Equate => {
-                                ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
-                            }
-                            ty::AliasRelationDirection::Subtype => {
-                                ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
-                            }
+                    match direction {
+                        ty::AliasRelationDirection::Equate => {
+                            ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
                         }
+                        ty::AliasRelationDirection::Subtype => {
+                            ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
+                        }
+                    }
 
-                        ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                    })
-                    .ok(),
-                );
+                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                });
+                candidates.extend(subst_relate_response);
                 debug!(?candidates);
 
                 if let Some(merged) = self.try_merge_responses(&candidates) {
                     Ok(merged)
+                } else if let Ok(subst_relate_response) = subst_relate_response {
+                    Ok(subst_relate_response)
                 } else {
                     self.flounder(&candidates)
                 }
diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs
new file mode 100644
index 0000000..a5de4dd
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/opaques.rs
@@ -0,0 +1,67 @@
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
+use rustc_middle::traits::Reveal;
+use rustc_middle::ty;
+use rustc_middle::ty::util::NotUniqueParam;
+
+use super::{EvalCtxt, SolverMode};
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+    pub(super) fn normalize_opaque_type(
+        &mut self,
+        goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        let tcx = self.tcx();
+        let opaque_ty = goal.predicate.projection_ty;
+        let expected = goal.predicate.term.ty().expect("no such thing as an opaque const");
+
+        match (goal.param_env.reveal(), self.solver_mode()) {
+            (Reveal::UserFacing, SolverMode::Normal) => {
+                let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else {
+                    return Err(NoSolution);
+                };
+                let opaque_ty =
+                    ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs };
+                // FIXME: at some point we should call queries without defining
+                // new opaque types but having the existing opaque type definitions.
+                // This will require moving this below "Prefer opaques registered already".
+                if !self.can_define_opaque_ty(opaque_ty_def_id) {
+                    return Err(NoSolution);
+                }
+                // FIXME: This may have issues when the substs contain aliases...
+                match self.tcx().uses_unique_placeholders_ignoring_regions(opaque_ty.substs) {
+                    Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
+                        return self.evaluate_added_goals_and_make_canonical_response(
+                            Certainty::AMBIGUOUS,
+                        );
+                    }
+                    Err(_) => {
+                        return Err(NoSolution);
+                    }
+                    Ok(()) => {}
+                }
+                // Prefer opaques registered already.
+                let matches = self.unify_existing_opaque_tys(goal.param_env, opaque_ty, expected);
+                if !matches.is_empty() {
+                    if let Some(response) = self.try_merge_responses(&matches) {
+                        return Ok(response);
+                    } else {
+                        return self.flounder(&matches);
+                    }
+                }
+                // Otherwise, define a new opaque type
+                self.register_opaque_ty(opaque_ty, expected, goal.param_env)?;
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }
+            (Reveal::UserFacing, SolverMode::Coherence) => {
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+            }
+            (Reveal::All, _) => {
+                // FIXME: Add an assertion that opaque type storage is empty.
+                let actual = tcx.type_of(opaque_ty.def_id).subst(tcx, opaque_ty.substs);
+                self.eq(goal.param_env, expected, actual)?;
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 20ce2d9..7d7dfa2 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -22,19 +22,25 @@
         &mut self,
         goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
     ) -> QueryResult<'tcx> {
-        // To only compute normalization once for each projection we only
-        // normalize if the expected term is an unconstrained inference variable.
-        //
-        // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
-        // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
-        // `U` and equate it with `u32`. This means that we don't need a separate
-        // projection cache in the solver.
-        if self.term_is_fully_unconstrained(goal) {
-            let candidates = self.assemble_and_evaluate_candidates(goal);
-            self.merge_candidates(candidates)
-        } else {
-            self.set_normalizes_to_hack_goal(goal);
-            self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+        match goal.predicate.projection_ty.kind(self.tcx()) {
+            ty::AliasKind::Projection => {
+                // To only compute normalization once for each projection we only
+                // normalize if the expected term is an unconstrained inference variable.
+                //
+                // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
+                // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
+                // `U` and equate it with `u32`. This means that we don't need a separate
+                // projection cache in the solver.
+                if self.term_is_fully_unconstrained(goal) {
+                    let candidates = self.assemble_and_evaluate_candidates(goal);
+                    self.merge_candidates(candidates)
+                } else {
+                    self.set_normalizes_to_hack_goal(goal);
+                    self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                }
+            }
+            ty::AliasKind::Opaque => self.normalize_opaque_type(goal),
+            ty::AliasKind::Inherent => bug!("IATs not supported here yet"),
         }
     }
 }
@@ -124,10 +130,24 @@
             };
 
             if !assoc_def.item.defaultness(tcx).has_value() {
-                tcx.sess.delay_span_bug(
+                let guar = tcx.sess.delay_span_bug(
                     tcx.def_span(assoc_def.item.def_id),
                     "missing value for assoc item in impl",
                 );
+                let error_term = match assoc_def.item.kind {
+                    ty::AssocKind::Const => tcx
+                        .const_error(
+                            tcx.type_of(goal.predicate.def_id())
+                                .subst(tcx, goal.predicate.projection_ty.substs),
+                            guar,
+                        )
+                        .into(),
+                    ty::AssocKind::Type => tcx.ty_error(guar).into(),
+                    ty::AssocKind::Fn => unreachable!(),
+                };
+                ecx.eq(goal.param_env, goal.predicate.term, error_term)
+                    .expect("expected goal term to be fully unconstrained");
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
             }
 
             // Getting the right substitutions here is complex, e.g. given:
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
index e6941af..56f126e 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
@@ -11,7 +11,7 @@
 use super::StackDepth;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::IndexVec;
-use rustc_middle::traits::solve::{CanonicalGoal, QueryResult};
+use rustc_middle::traits::solve::{CanonicalInput, QueryResult};
 
 rustc_index::newtype_index! {
     pub struct EntryIndex {}
@@ -34,7 +34,7 @@
 
     // The goal for this entry. Should always be equal to the corresponding goal
     // in the lookup table.
-    pub(super) goal: CanonicalGoal<'tcx>,
+    pub(super) input: CanonicalInput<'tcx>,
 }
 
 pub(super) struct ProvisionalCache<'tcx> {
@@ -42,7 +42,7 @@
     // FIXME: This is only used to quickly check whether a given goal
     // is in the cache. We should experiment with using something like
     // `SsoHashSet` here because in most cases there are only a few entries.
-    pub(super) lookup_table: FxHashMap<CanonicalGoal<'tcx>, EntryIndex>,
+    pub(super) lookup_table: FxHashMap<CanonicalInput<'tcx>, EntryIndex>,
 }
 
 impl<'tcx> ProvisionalCache<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index c190435..19e4b23 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -8,7 +8,7 @@
 use overflow::OverflowData;
 use rustc_index::IndexVec;
 use rustc_middle::dep_graph::DepKind;
-use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
+use rustc_middle::traits::solve::{CanonicalInput, Certainty, MaybeCause, QueryResult};
 use rustc_middle::ty::TyCtxt;
 use std::{collections::hash_map::Entry, mem};
 
@@ -19,7 +19,7 @@
 }
 
 struct StackElem<'tcx> {
-    goal: CanonicalGoal<'tcx>,
+    input: CanonicalInput<'tcx>,
     has_been_used: bool,
 }
 
@@ -77,7 +77,7 @@
             }
 
             // ...or it depends on a goal with a lower depth.
-            let current_goal = self.stack[stack_depth].goal;
+            let current_goal = self.stack[stack_depth].input;
             let entry_index = self.provisional_cache.lookup_table[&current_goal];
             self.provisional_cache.entries[entry_index].depth != stack_depth
         } else {
@@ -92,20 +92,20 @@
     fn try_push_stack(
         &mut self,
         tcx: TyCtxt<'tcx>,
-        goal: CanonicalGoal<'tcx>,
+        input: CanonicalInput<'tcx>,
     ) -> Result<(), QueryResult<'tcx>> {
         // Look at the provisional cache to check for cycles.
         let cache = &mut self.provisional_cache;
-        match cache.lookup_table.entry(goal) {
+        match cache.lookup_table.entry(input) {
             // No entry, simply push this goal on the stack after dealing with overflow.
             Entry::Vacant(v) => {
                 if self.overflow_data.has_overflow(self.stack.len()) {
-                    return Err(self.deal_with_overflow(tcx, goal));
+                    return Err(self.deal_with_overflow(tcx, input));
                 }
 
-                let depth = self.stack.push(StackElem { goal, has_been_used: false });
-                let response = super::response_no_constraints(tcx, goal, Certainty::Yes);
-                let entry_index = cache.entries.push(ProvisionalEntry { response, depth, goal });
+                let depth = self.stack.push(StackElem { input, has_been_used: false });
+                let response = super::response_no_constraints(tcx, input, Certainty::Yes);
+                let entry_index = cache.entries.push(ProvisionalEntry { response, depth, input });
                 v.insert(entry_index);
                 Ok(())
             }
@@ -135,13 +135,13 @@
                 // the stack is enough.
                 if self.stack.raw[stack_depth.index()..]
                     .iter()
-                    .all(|g| g.goal.value.predicate.is_coinductive(tcx))
+                    .all(|g| g.input.value.goal.predicate.is_coinductive(tcx))
                 {
                     Err(cache.provisional_result(entry_index))
                 } else {
                     Err(super::response_no_constraints(
                         tcx,
-                        goal,
+                        input,
                         Certainty::Maybe(MaybeCause::Overflow),
                     ))
                 }
@@ -161,18 +161,18 @@
     /// updated the provisional cache and we have to recompute the current goal.
     ///
     /// FIXME: Refer to the rustc-dev-guide entry once it exists.
-    #[instrument(level = "debug", skip(self, actual_goal), ret)]
+    #[instrument(level = "debug", skip(self, actual_input), ret)]
     fn try_finalize_goal(
         &mut self,
-        actual_goal: CanonicalGoal<'tcx>,
+        actual_input: CanonicalInput<'tcx>,
         response: QueryResult<'tcx>,
     ) -> bool {
         let stack_elem = self.stack.pop().unwrap();
-        let StackElem { goal, has_been_used } = stack_elem;
-        assert_eq!(goal, actual_goal);
+        let StackElem { input, has_been_used } = stack_elem;
+        assert_eq!(input, actual_input);
 
         let cache = &mut self.provisional_cache;
-        let provisional_entry_index = *cache.lookup_table.get(&goal).unwrap();
+        let provisional_entry_index = *cache.lookup_table.get(&input).unwrap();
         let provisional_entry = &mut cache.entries[provisional_entry_index];
         // We eagerly update the response in the cache here. If we have to reevaluate
         // this goal we use the new response when hitting a cycle, and we definitely
@@ -194,7 +194,7 @@
             cache.entries.truncate(provisional_entry_index.index() + 1);
 
             // ...and finally push our goal back on the stack and reevaluate it.
-            self.stack.push(StackElem { goal, has_been_used: false });
+            self.stack.push(StackElem { input, has_been_used: false });
             false
         } else {
             true
@@ -204,17 +204,17 @@
     pub(super) fn with_new_goal(
         &mut self,
         tcx: TyCtxt<'tcx>,
-        canonical_goal: CanonicalGoal<'tcx>,
+        canonical_input: CanonicalInput<'tcx>,
         mut loop_body: impl FnMut(&mut Self) -> QueryResult<'tcx>,
     ) -> QueryResult<'tcx> {
         if self.should_use_global_cache() {
-            if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_goal, tcx) {
-                debug!(?canonical_goal, ?result, "cache hit");
+            if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_input, tcx) {
+                debug!(?canonical_input, ?result, "cache hit");
                 return result;
             }
         }
 
-        match self.try_push_stack(tcx, canonical_goal) {
+        match self.try_push_stack(tcx, canonical_input) {
             Ok(()) => {}
             // Our goal is already on the stack, eager return.
             Err(response) => return response,
@@ -226,19 +226,19 @@
         let (result, dep_node) = tcx.dep_graph.with_anon_task(tcx, DepKind::TraitSelect, || {
             self.repeat_while_none(
                 |this| {
-                    let result = this.deal_with_overflow(tcx, canonical_goal);
+                    let result = this.deal_with_overflow(tcx, canonical_input);
                     let _ = this.stack.pop().unwrap();
                     result
                 },
                 |this| {
                     let result = loop_body(this);
-                    this.try_finalize_goal(canonical_goal, result).then(|| result)
+                    this.try_finalize_goal(canonical_input, result).then(|| result)
                 },
             )
         });
 
         let cache = &mut self.provisional_cache;
-        let provisional_entry_index = *cache.lookup_table.get(&canonical_goal).unwrap();
+        let provisional_entry_index = *cache.lookup_table.get(&canonical_input).unwrap();
         let provisional_entry = &mut cache.entries[provisional_entry_index];
         let depth = provisional_entry.depth;
 
@@ -254,13 +254,13 @@
             // cycle participants without moving them to the global cache.
             let other_cycle_participants = provisional_entry_index.index() + 1;
             for (i, entry) in cache.entries.drain_enumerated(other_cycle_participants..) {
-                let actual_index = cache.lookup_table.remove(&entry.goal);
+                let actual_index = cache.lookup_table.remove(&entry.input);
                 debug_assert_eq!(Some(i), actual_index);
                 debug_assert!(entry.depth == depth);
             }
 
             let current_goal = cache.entries.pop().unwrap();
-            let actual_index = cache.lookup_table.remove(&current_goal.goal);
+            let actual_index = cache.lookup_table.remove(&current_goal.input);
             debug_assert_eq!(Some(provisional_entry_index), actual_index);
             debug_assert!(current_goal.depth == depth);
 
@@ -274,7 +274,7 @@
             let can_cache = !self.overflow_data.did_overflow() || self.stack.is_empty();
             if self.should_use_global_cache() && can_cache {
                 tcx.new_solver_evaluation_cache.insert(
-                    current_goal.goal,
+                    current_goal.input,
                     dep_node,
                     current_goal.response,
                 );
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index dcfa33a..f722f28 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -177,14 +177,18 @@
             return Err(NoSolution);
         }
 
-        if goal.predicate.self_ty().has_non_region_infer() {
+        // The regions of a type don't affect the size of the type
+        let tcx = ecx.tcx();
+        // We should erase regions from both the param-env and type, since both
+        // may have infer regions. Specifically, after canonicalizing and instantiating,
+        // early bound regions turn into region vars in both the new and old solver.
+        let key = tcx.erase_regions(goal.param_env.and(goal.predicate.self_ty()));
+        // But if there are inference variables, we have to wait until it's resolved.
+        if key.has_non_region_infer() {
             return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
         }
 
-        let tcx = ecx.tcx();
-        let self_ty = tcx.erase_regions(goal.predicate.self_ty());
-
-        if let Ok(layout) = tcx.layout_of(goal.param_env.and(self_ty))
+        if let Ok(layout) = tcx.layout_of(key)
             && layout.layout.is_pointer_like(&tcx.data_layout)
         {
             // FIXME: We could make this faster by making a no-constraints response
@@ -354,7 +358,7 @@
                     // Can only unsize to an object-safe type
                     if data
                         .principal_def_id()
-                        .map_or(false, |def_id| !tcx.check_is_object_safe(def_id))
+                        .is_some_and(|def_id| !tcx.check_is_object_safe(def_id))
                     {
                         return Err(NoSolution);
                     }
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 6b080a1..62d2aad 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -801,7 +801,7 @@
                                             span: tcx.def_span(unevaluated.def),
                                             unevaluated: unevaluated,
                                         });
-                                    Err(ErrorHandled::Reported(reported))
+                                    Err(ErrorHandled::Reported(reported.into()))
                                 }
                                 Err(err) => Err(err),
                             }
@@ -834,8 +834,10 @@
                 | ty::PredicateKind::Subtype(..)
                 // FIXME(generic_const_exprs): you can absolutely add this as a where clauses
                 | ty::PredicateKind::ConstEvaluatable(..)
-                | ty::PredicateKind::Coerce(..)
-                | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
+                | ty::PredicateKind::Coerce(..) => {}
+                ty::PredicateKind::TypeWellFormedFromEnv(..) => {
+                    bug!("predicate should only exist in the environment: {bound_predicate:?}")
+                }
                 ty::PredicateKind::Ambiguous => return false,
             };
         }
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 969e5fa..e8c5a8f 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -17,9 +17,10 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_infer::infer::{DefineOpaqueTypes, DefiningAnchor, InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::traits::specialization_graph::OverlapMode;
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitor};
@@ -706,7 +707,7 @@
             }
             ty::Dynamic(tt, ..) => {
                 let principal = tt.principal().map(|p| p.def_id());
-                if principal.map_or(false, |p| self.def_id_is_local(p)) {
+                if principal.is_some_and(|p| self.def_id_is_local(p)) {
                     ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
                 } else {
                     self.found_non_local_ty(ty)
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 9d99d30..bd1ea43 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -79,7 +79,7 @@
                             "Missing value for constant, but no error reported?",
                         )))
                     }
-                    Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+                    Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e.into())),
                     Ok(_) => Ok(()),
                 }
             }
@@ -147,7 +147,7 @@
 
                 Err(err)
             }
-            Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+            Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e.into())),
             Ok(_) => Ok(()),
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 000427b..2c5ffd6 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -14,11 +14,11 @@
 };
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_infer::traits::query::Fallible;
 use rustc_infer::traits::{
     FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
 };
 use rustc_middle::arena::ArenaAllocatable;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::TypeFoldable;
@@ -235,7 +235,7 @@
         &self,
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, T>>
+    ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
         Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index f5f2fe5..a10ecec 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -437,7 +437,7 @@
                     // 1) strictly implied by another error.
                     // 2) implied by an error with a smaller index.
                     for error2 in error_set {
-                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
+                        if error2.index.is_some_and(|index2| is_suppressed[index2]) {
                             // Avoid errors being suppressed by already-suppressed
                             // errors, to prevent all errors from being suppressed
                             // at once.
@@ -885,7 +885,7 @@
                             return;
                         }
 
-                        if self.suggest_impl_trait(&mut err, span, &obligation, trait_predicate) {
+                        if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) {
                             err.emit();
                             return;
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 88525e1..10bd027 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -306,6 +306,14 @@
                     }
                 }
             }
+
+            // `&[{integral}]` - `FromIterator` needs that.
+            if let ty::Ref(_, ref_ty, rustc_ast::Mutability::Not) = self_ty.kind()
+                && let ty::Slice(sty) = ref_ty.kind()
+                && sty.is_integral()
+            {
+                flags.push((sym::_Self, Some("&[{integral}]".to_owned())));
+            }
         });
 
         if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 49b309a..82bad96 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -30,9 +30,9 @@
 use rustc_middle::ty::error::TypeError::{self, Sorts};
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
-    IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
-    TypeSuperFoldable, TypeVisitableExt, TypeckResults,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, InferTy, InternalSubsts, IsSuggestable,
+    ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    TypeVisitableExt, TypeckResults,
 };
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -261,7 +261,6 @@
     fn suggest_impl_trait(
         &self,
         err: &mut Diagnostic,
-        span: Span,
         obligation: &PredicateObligation<'tcx>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool;
@@ -421,7 +420,7 @@
 ) {
     if hir_generics.where_clause_span.from_expansion()
         || hir_generics.where_clause_span.desugaring_kind().is_some()
-        || projection.map_or(false, |projection| tcx.opt_rpitit_info(projection.def_id).is_some())
+        || projection.is_some_and(|projection| tcx.opt_rpitit_info(projection.def_id).is_some())
     {
         return;
     }
@@ -1792,215 +1791,66 @@
     fn suggest_impl_trait(
         &self,
         err: &mut Diagnostic,
-        span: Span,
         obligation: &PredicateObligation<'tcx>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
-        match obligation.cause.code().peel_derives() {
-            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
-            ObligationCauseCode::SizedReturnType => {}
-            _ => return false,
-        }
-
-        let hir = self.tcx.hir();
-        let fn_hir_id = hir.local_def_id_to_hir_id(obligation.cause.body_id);
-        let node = hir.find_by_def_id(obligation.cause.body_id);
-        let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id),
-            ..
-        })) = node
-        else {
+        let ObligationCauseCode::SizedReturnType = obligation.cause.code() else {
             return false;
         };
-        let body = hir.body(*body_id);
-        let trait_pred = self.resolve_vars_if_possible(trait_pred);
-        let ty = trait_pred.skip_binder().self_ty();
-        let is_object_safe = match ty.kind() {
-            ty::Dynamic(predicates, _, ty::Dyn) => {
-                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
-                predicates
-                    .principal_def_id()
-                    .map_or(true, |def_id| self.tcx.check_is_object_safe(def_id))
-            }
-            // We only want to suggest `impl Trait` to `dyn Trait`s.
-            // For example, `fn foo() -> str` needs to be filtered out.
-            _ => return false,
-        };
-
-        let hir::FnRetTy::Return(ret_ty) = sig.decl.output else {
+        let ty::Dynamic(_, _, ty::Dyn) = trait_pred.self_ty().skip_binder().kind() else {
             return false;
         };
 
-        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
-        // cases like `fn foo() -> (dyn Trait, i32) {}`.
-        // Recursively look for `TraitObject` types and if there's only one, use that span to
-        // suggest `impl Trait`.
-
-        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
-        // otherwise suggest using `Box<dyn Trait>` or an enum.
-        let mut visitor = ReturnsVisitor::default();
-        visitor.visit_body(&body);
-
-        let typeck_results = self.typeck_results.as_ref().unwrap();
-        let Some(liberated_sig) = typeck_results.liberated_fn_sigs().get(fn_hir_id).copied() else { return false; };
-
-        let ret_types = visitor
-            .returns
-            .iter()
-            .filter_map(|expr| Some((expr.span, typeck_results.node_type_opt(expr.hir_id)?)))
-            .map(|(expr_span, ty)| (expr_span, self.resolve_vars_if_possible(ty)));
-        let (last_ty, all_returns_have_same_type, only_never_return) = ret_types.clone().fold(
-            (None, true, true),
-            |(last_ty, mut same, only_never_return): (std::option::Option<Ty<'_>>, bool, bool),
-             (_, ty)| {
-                let ty = self.resolve_vars_if_possible(ty);
-                same &=
-                    !matches!(ty.kind(), ty::Error(_))
-                        && last_ty.map_or(true, |last_ty| {
-                            // FIXME: ideally we would use `can_coerce` here instead, but `typeck` comes
-                            // *after* in the dependency graph.
-                            match (ty.kind(), last_ty.kind()) {
-                                (Infer(InferTy::IntVar(_)), Infer(InferTy::IntVar(_)))
-                                | (Infer(InferTy::FloatVar(_)), Infer(InferTy::FloatVar(_)))
-                                | (Infer(InferTy::FreshIntTy(_)), Infer(InferTy::FreshIntTy(_)))
-                                | (
-                                    Infer(InferTy::FreshFloatTy(_)),
-                                    Infer(InferTy::FreshFloatTy(_)),
-                                ) => true,
-                                _ => ty == last_ty,
-                            }
-                        });
-                (Some(ty), same, only_never_return && matches!(ty.kind(), ty::Never))
-            },
-        );
-        let mut spans_and_needs_box = vec![];
-
-        match liberated_sig.output().kind() {
-            ty::Dynamic(predicates, _, ty::Dyn) => {
-                let cause = ObligationCause::misc(ret_ty.span, obligation.cause.body_id);
-                let param_env = ty::ParamEnv::empty();
-
-                if !only_never_return {
-                    for (expr_span, return_ty) in ret_types {
-                        let self_ty_satisfies_dyn_predicates = |self_ty| {
-                            predicates.iter().all(|predicate| {
-                                let pred = predicate.with_self_ty(self.tcx, self_ty);
-                                let obl = Obligation::new(self.tcx, cause.clone(), param_env, pred);
-                                self.predicate_may_hold(&obl)
-                            })
-                        };
-
-                        if let ty::Adt(def, substs) = return_ty.kind()
-                            && def.is_box()
-                            && self_ty_satisfies_dyn_predicates(substs.type_at(0))
-                        {
-                            spans_and_needs_box.push((expr_span, false));
-                        } else if self_ty_satisfies_dyn_predicates(return_ty) {
-                            spans_and_needs_box.push((expr_span, true));
-                        } else {
-                            return false;
-                        }
-                    }
-                }
-            }
-            _ => return false,
-        };
-
-        let sm = self.tcx.sess.source_map();
-        if !ret_ty.span.overlaps(span) {
-            return false;
-        }
-        let snippet = if let hir::TyKind::TraitObject(..) = ret_ty.kind {
-            if let Ok(snippet) = sm.span_to_snippet(ret_ty.span) {
-                snippet
-            } else {
-                return false;
-            }
-        } else {
-            // Substitute the type, so we can print a fixup given `type Alias = dyn Trait`
-            let name = liberated_sig.output().to_string();
-            let name =
-                name.strip_prefix('(').and_then(|name| name.strip_suffix(')')).unwrap_or(&name);
-            if !name.starts_with("dyn ") {
-                return false;
-            }
-            name.to_owned()
-        };
-
         err.code(error_code!(E0746));
         err.set_primary_message("return type cannot have an unboxed trait object");
         err.children.clear();
-        let impl_trait_msg = "for information on `impl Trait`, see \
-            <https://doc.rust-lang.org/book/ch10-02-traits.html\
-            #returning-types-that-implement-traits>";
-        let trait_obj_msg = "for information on trait objects, see \
-            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
-            #using-trait-objects-that-allow-for-values-of-different-types>";
 
-        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
-        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet };
-        if only_never_return {
-            // No return paths, probably using `panic!()` or similar.
-            // Suggest `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
-            suggest_trait_object_return_type_alternatives(
-                err,
-                ret_ty.span,
-                trait_obj,
-                is_object_safe,
-            );
-        } else if let (Some(last_ty), true) = (last_ty, all_returns_have_same_type) {
-            // Suggest `-> impl Trait`.
+        let span = obligation.cause.span;
+        if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span)
+            && snip.starts_with("dyn ")
+        {
             err.span_suggestion(
-                ret_ty.span,
-                format!(
-                    "use `impl {1}` as the return type, as all return paths are of type `{}`, \
-                     which implements `{1}`",
-                    last_ty, trait_obj,
-                ),
-                format!("impl {}", trait_obj),
-                Applicability::MachineApplicable,
+                span.with_hi(span.lo() + BytePos(4)),
+                "return an `impl Trait` instead of a `dyn Trait`, \
+                if all returned values are the same type",
+                "impl ",
+                Applicability::MaybeIncorrect,
             );
-            err.note(impl_trait_msg);
-        } else {
-            if is_object_safe {
-                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
-                err.multipart_suggestion(
-                    "return a boxed trait object instead",
-                    vec![
-                        (ret_ty.span.shrink_to_lo(), "Box<".to_string()),
-                        (span.shrink_to_hi(), ">".to_string()),
-                    ],
-                    Applicability::MaybeIncorrect,
-                );
-                for (span, needs_box) in spans_and_needs_box {
-                    if needs_box {
-                        err.multipart_suggestion(
-                            "... and box this value",
-                            vec![
-                                (span.shrink_to_lo(), "Box::new(".to_string()),
-                                (span.shrink_to_hi(), ")".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-            } else {
-                // This is currently not possible to trigger because E0038 takes precedence, but
-                // leave it in for completeness in case anything changes in an earlier stage.
-                err.note(format!(
-                    "if trait `{}` were object-safe, you could return a trait object",
-                    trait_obj,
-                ));
-            }
-            err.note(trait_obj_msg);
-            err.note(format!(
-                "if all the returned values were of the same type you could use `impl {}` as the \
-                 return type",
-                trait_obj,
-            ));
-            err.note(impl_trait_msg);
-            err.note("you can create a new `enum` with a variant for each returned type");
         }
+
+        let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(obligation.cause.body_id));
+
+        let mut visitor = ReturnsVisitor::default();
+        visitor.visit_body(&body);
+
+        let mut sugg =
+            vec![(span.shrink_to_lo(), "Box<".to_string()), (span.shrink_to_hi(), ">".to_string())];
+        sugg.extend(visitor.returns.into_iter().flat_map(|expr| {
+            let span = expr.span.find_ancestor_in_same_ctxt(obligation.cause.span).unwrap_or(expr.span);
+            if !span.can_be_used_for_suggestions() {
+                vec![]
+            } else if let hir::ExprKind::Call(path, ..) = expr.kind
+                && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, method)) = path.kind
+                && method.ident.name == sym::new
+                && let hir::TyKind::Path(hir::QPath::Resolved(.., box_path)) = ty.kind
+                && box_path.res.opt_def_id().is_some_and(|def_id| Some(def_id) == self.tcx.lang_items().owned_box())
+            {
+                // Don't box `Box::new`
+                vec![]
+            } else {
+                vec![
+                    (span.shrink_to_lo(), "Box::new(".to_string()),
+                    (span.shrink_to_hi(), ")".to_string()),
+                ]
+            }
+        }));
+
+        err.multipart_suggestion(
+            "box the return type, and wrap all of the returned values in `Box::new`",
+            sugg,
+            Applicability::MaybeIncorrect,
+        );
+
         true
     }
 
@@ -2447,10 +2297,9 @@
             && generator_did.is_local()
             // Try to avoid cycles.
             && !generator_within_in_progress_typeck
+            && let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did)
         {
-            let generator_info = &self.tcx.mir_generator_witnesses(generator_did);
             debug!(?generator_info);
-
             'find_source: for (variant, source_info) in
                 generator_info.variant_fields.iter().zip(&generator_info.variant_source_info)
             {
@@ -3087,7 +2936,7 @@
                                     "note_obligation_cause_code: check for async fn"
                                 );
                                 if is_future
-                                    && obligated_types.last().map_or(false, |ty| match ty.kind() {
+                                    && obligated_types.last().is_some_and(|ty| match ty.kind() {
                                         ty::Generator(last_def_id, ..) => {
                                             tcx.generator_is_async(*last_def_id)
                                         }
@@ -4140,37 +3989,6 @@
     }
 }
 
-fn suggest_trait_object_return_type_alternatives(
-    err: &mut Diagnostic,
-    ret_ty: Span,
-    trait_obj: &str,
-    is_object_safe: bool,
-) {
-    err.span_suggestion(
-        ret_ty,
-        format!(
-            "use `impl {}` as the return type if all return paths have the same type but you \
-                want to expose only the trait in the signature",
-            trait_obj,
-        ),
-        format!("impl {}", trait_obj),
-        Applicability::MaybeIncorrect,
-    );
-    if is_object_safe {
-        err.multipart_suggestion(
-            format!(
-                "use a boxed trait object if all return paths implement trait `{}`",
-                trait_obj,
-            ),
-            vec![
-                (ret_ty.shrink_to_lo(), "Box<".to_string()),
-                (ret_ty.shrink_to_hi(), ">".to_string()),
-            ],
-            Applicability::MaybeIncorrect,
-        );
-    }
-}
-
 /// Collect the spans that we see the generic param `param_did`
 struct ReplaceImplTraitVisitor<'a> {
     ty_spans: &'a mut Vec<Span>,
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 43196d1..2f85c32 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -615,7 +615,7 @@
                         (Err(ErrorHandled::Reported(reported)), _)
                         | (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
                             CodeSelectionError(SelectionError::NotConstEvaluatable(
-                                NotConstEvaluatable::Error(reported),
+                                NotConstEvaluatable::Error(reported.into()),
                             )),
                         ),
                         (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 38daca5..f265230 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -17,6 +17,7 @@
 mod select;
 mod specialize;
 mod structural_match;
+mod structural_normalize;
 mod util;
 mod vtable;
 pub mod wf;
@@ -26,6 +27,7 @@
 use crate::traits::error_reporting::TypeErrCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
@@ -61,6 +63,7 @@
 pub use self::structural_match::{
     search_for_adt_const_param_violation, search_for_structural_match_violation,
 };
+pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::elaborate;
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
@@ -142,35 +145,36 @@
 fn pred_known_to_hold_modulo_regions<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
+    pred: impl ToPredicate<'tcx>,
 ) -> bool {
-    let has_non_region_infer = pred.has_non_region_infer();
     let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);
 
     let result = infcx.evaluate_obligation_no_overflow(&obligation);
     debug!(?result);
 
-    if result.must_apply_modulo_regions() && !has_non_region_infer {
+    if result.must_apply_modulo_regions() {
         true
     } else if result.may_apply() {
-        // Because of inference "guessing", selection can sometimes claim
-        // to succeed while the success requires a guess. To ensure
-        // this function's result remains infallible, we must confirm
-        // that guess. While imperfect, I believe this is sound.
+        // Sometimes obligations are ambiguous because the recursive evaluator
+        // is not smart enough, so we fall back to fulfillment when we're not certain
+        // that an obligation holds or not. Even still, we must make sure that
+        // the we do no inference in the process of checking this obligation.
+        let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
+        infcx.probe(|_| {
+            let ocx = ObligationCtxt::new_in_snapshot(infcx);
+            ocx.register_obligation(obligation);
 
-        // The handling of regions in this area of the code is terrible,
-        // see issue #29149. We should be able to improve on this with
-        // NLL.
-        let ocx = ObligationCtxt::new(infcx);
-        ocx.register_obligation(obligation);
-        let errors = ocx.select_all_or_error();
-        match errors.as_slice() {
-            [] => true,
-            errors => {
-                debug!(?errors);
-                false
+            let errors = ocx.select_all_or_error();
+            match errors.as_slice() {
+                // Only known to hold if we did no inference.
+                [] => infcx.shallow_resolve(goal) == goal,
+
+                errors => {
+                    debug!(?errors);
+                    false
+                }
             }
-        }
+        })
     } else {
         false
     }
@@ -498,10 +502,10 @@
     false
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     object_safety::provide(providers);
     vtable::provide(providers);
-    *providers = ty::query::Providers {
+    *providers = Providers {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
         subst_and_check_impossible_predicates,
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 06d9c10..c81bf6e 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -16,6 +16,7 @@
 use rustc_errors::{DelayDm, FatalError, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
 use rustc_middle::ty::{
     self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
@@ -947,7 +948,6 @@
     })
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers =
-        ty::query::Providers { object_safety_violations, check_is_object_safe, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { object_safety_violations, check_is_object_safe, ..*providers };
 }
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 0db8023..0e797a1 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -1,8 +1,8 @@
 use crate::infer::InferCtxt;
 use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
-use crate::traits::query::NoSolution;
 use crate::traits::{ObligationCause, ObligationCtxt};
 use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt};
 use rustc_span::def_id::LocalDefId;
@@ -69,16 +69,12 @@
         }
 
         let span = self.tcx.def_span(body_id);
-        let result = param_env
+        let result: Result<_, ErrorGuaranteed> = param_env
             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
-            .fully_perform(self);
+            .fully_perform(self, span);
         let result = match result {
             Ok(r) => r,
-            Err(NoSolution) => {
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    "implied_outlives_bounds failed to solve all obligations",
-                );
+            Err(_) => {
                 return vec![];
             }
         };
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8e684b7..5106989 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1543,7 +1543,10 @@
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation.predicate.self_ty().kind() {
-        ty::Alias(_, ref data) => tcx.item_bounds(data.def_id).subst(tcx, data.substs),
+        // Excluding IATs here as they don't have meaningful item bounds.
+        ty::Alias(ty::Projection | ty::Opaque, ref data) => {
+            tcx.item_bounds(data.def_id).subst(tcx, data.substs)
+        }
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -2260,7 +2263,7 @@
                 obligation, poly_cache_entry, e,
             );
             debug!("confirm_param_env_candidate: {}", msg);
-            let err = infcx.tcx.ty_error_with_message(obligation.cause.span, &msg);
+            let err = infcx.tcx.ty_error_with_message(obligation.cause.span, msg);
             Progress { term: err.into(), obligations: vec![] }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index e6db96c..c61f545 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -1,5 +1,5 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 
 pub use rustc_middle::traits::query::type_op::AscribeUserType;
@@ -17,7 +17,7 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_ascribe_user_type(canonicalized)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 1f8e756..6d8d210 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -1,32 +1,32 @@
 use crate::infer::canonical::query_response;
-use crate::infer::{InferCtxt, InferOk};
+use crate::infer::InferCtxt;
 use crate::traits::query::type_op::TypeOpOutput;
-use crate::traits::query::Fallible;
 use crate::traits::ObligationCtxt;
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
+use rustc_middle::traits::query::NoSolution;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_span::Span;
 
 use std::fmt;
 
-pub struct CustomTypeOp<F, G> {
+pub struct CustomTypeOp<F> {
     closure: F,
-    description: G,
+    description: &'static str,
 }
 
-impl<F, G> CustomTypeOp<F, G> {
-    pub fn new<'tcx, R>(closure: F, description: G) -> Self
+impl<F> CustomTypeOp<F> {
+    pub fn new<'tcx, R>(closure: F, description: &'static str) -> Self
     where
-        F: FnOnce(&InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
-        G: Fn() -> String,
+        F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
     {
         CustomTypeOp { closure, description }
     }
 }
 
-impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
+impl<'tcx, F, R: fmt::Debug> super::TypeOp<'tcx> for CustomTypeOp<F>
 where
-    F: for<'a, 'cx> FnOnce(&'a InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
-    G: Fn() -> String,
+    F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
 {
     type Output = R;
     /// We can't do any custom error reporting for `CustomTypeOp`, so
@@ -36,21 +36,22 @@
     /// Processes the operation and all resulting obligations,
     /// returning the final result along with any region constraints
     /// (they will be given over to the NLL region solver).
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
         if cfg!(debug_assertions) {
             info!("fully_perform({:?})", self);
         }
 
-        Ok(scrape_region_constraints(infcx, || (self.closure)(infcx))?.0)
+        Ok(scrape_region_constraints(infcx, self.closure, self.description, span)?.0)
     }
 }
 
-impl<F, G> fmt::Debug for CustomTypeOp<F, G>
-where
-    G: Fn() -> String,
-{
+impl<F> fmt::Debug for CustomTypeOp<F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", (self.description)())
+        self.description.fmt(f)
     }
 }
 
@@ -58,8 +59,10 @@
 /// constraints that result, creating query-region-constraints.
 pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     infcx: &InferCtxt<'tcx>,
-    op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
-) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> {
+    op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
+    name: &'static str,
+    span: Span,
+) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed> {
     // During NLL, we expect that nobody will register region
     // obligations **except** as part of a custom type op (and, at the
     // end of each custom type op, we scrape out the region
@@ -72,16 +75,21 @@
         pre_obligations,
     );
 
-    let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
-    let ocx = ObligationCtxt::new(infcx);
-    ocx.register_obligations(obligations);
-    let errors = ocx.select_all_or_error();
-    if !errors.is_empty() {
-        infcx.tcx.sess.diagnostic().delay_span_bug(
-            DUMMY_SP,
-            format!("errors selecting obligation during MIR typeck: {:?}", errors),
-        );
-    }
+    let value = infcx.commit_if_ok(|_| {
+        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let value = op(&ocx).map_err(|_| {
+            infcx.tcx.sess.delay_span_bug(span, format!("error performing operation: {name}"))
+        })?;
+        let errors = ocx.select_all_or_error();
+        if errors.is_empty() {
+            Ok(value)
+        } else {
+            Err(infcx.tcx.sess.delay_span_bug(
+                DUMMY_SP,
+                format!("errors selecting obligation during MIR typeck: {:?}", errors),
+            ))
+        }
+    })?;
 
     let region_obligations = infcx.take_registered_region_obligations();
     let region_constraint_data = infcx.take_and_reset_region_constraints();
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
index 8c9b961..40f8ecf 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
@@ -1,5 +1,5 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 
 pub use rustc_middle::traits::query::type_op::Eq;
@@ -17,7 +17,7 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_eq(canonicalized)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 18d7c9b1..26f0d55 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,6 +1,6 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
 use rustc_infer::traits::query::OutlivesBound;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 
 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
@@ -28,7 +28,7 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
         // FIXME this `unchecked_map` is only necessary because the
         // query is defined as taking a `ParamEnvAnd<Ty>`; it should
         // take an `ImpliedOutlivesBounds` instead
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 9e8bc8b..6423265 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -2,13 +2,14 @@
     Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
 };
 use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
 use crate::traits::ObligationCause;
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::canonical::Certainty;
-use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::PredicateObligations;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
+use rustc_span::Span;
 use std::fmt;
 
 pub mod ascribe_user_type;
@@ -32,7 +33,11 @@
     /// Processes the operation and all resulting obligations,
     /// returning the final result along with any region constraints
     /// (they will be given over to the NLL region solver).
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
 }
 
 /// The output from performing a type op
@@ -74,18 +79,21 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>>;
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution>;
 
     fn fully_perform_into(
         query_key: ParamEnvAnd<'tcx, Self>,
         infcx: &InferCtxt<'tcx>,
         output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
-    ) -> Fallible<(
-        Self::QueryResponse,
-        Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
-        PredicateObligations<'tcx>,
-        Certainty,
-    )> {
+    ) -> Result<
+        (
+            Self::QueryResponse,
+            Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
+            PredicateObligations<'tcx>,
+            Certainty,
+        ),
+        NoSolution,
+    > {
         if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
             return Ok((result, None, vec![], Certainty::Proven));
         }
@@ -120,10 +128,16 @@
     type Output = Q::QueryResponse;
     type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
 
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
         let mut region_constraints = QueryRegionConstraints::default();
         let (output, error_info, mut obligations, _) =
-            Q::fully_perform_into(self, infcx, &mut region_constraints)?;
+            Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
+                infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
+            })?;
 
         // Typically, instantiating NLL query results does not
         // create obligations. However, in some cases there
@@ -151,7 +165,10 @@
                 }
             }
             if !progress {
-                return Err(NoSolution);
+                return Err(infcx.tcx.sess.delay_span_bug(
+                    span,
+                    format!("ambiguity processing {obligations:?} from {self:?}"),
+                ));
             }
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 5b216c0..776c74f 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -1,5 +1,5 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use std::fmt;
@@ -19,7 +19,7 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
         T::type_op_method(tcx, canonicalized)
     }
 }
@@ -28,14 +28,14 @@
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>>;
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution>;
 }
 
 impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_ty(canonicalized)
     }
 }
@@ -44,7 +44,7 @@
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_predicate(canonicalized)
     }
 }
@@ -53,7 +53,7 @@
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_poly_fn_sig(canonicalized)
     }
 }
@@ -62,7 +62,7 @@
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_fn_sig(canonicalized)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 21ef4e2..7ce09bb 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -1,6 +1,6 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
 use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult};
-use crate::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
 
 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
@@ -27,7 +27,7 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
         // Subtle: note that we are not invoking
         // `infcx.at(...).dropck_outlives(...)` here, but rather the
         // underlying `dropck_outlives` query. This same underlying
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index baa2fbb..7c02f36 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -1,5 +1,5 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
 
 pub use rustc_middle::traits::query::type_op::ProvePredicate;
@@ -33,7 +33,7 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_prove_predicate(canonicalized)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
index c51292e..2f2b931 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
@@ -1,5 +1,5 @@
 use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::query::Fallible;
+use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 
 pub use rustc_middle::traits::query::type_op::Subtype;
@@ -14,7 +14,7 @@
     fn perform_query(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
+    ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_subtype(canonicalized)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a8fb55d..8bc82b9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -143,7 +143,8 @@
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
-            ty::Alias(..) => {}
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, _) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(
                     obligation.cause.span,
@@ -966,16 +967,18 @@
     ) {
         // The regions of a type don't affect the size of the type
         let tcx = self.tcx();
-        let self_ty =
-            tcx.erase_regions(tcx.erase_late_bound_regions(obligation.predicate.self_ty()));
-
+        let self_ty = tcx.erase_late_bound_regions(obligation.predicate.self_ty());
+        // We should erase regions from both the param-env and type, since both
+        // may have infer regions. Specifically, after canonicalizing and instantiating,
+        // early bound regions turn into region vars in both the new and old solver.
+        let key = tcx.erase_regions(obligation.param_env.and(self_ty));
         // But if there are inference variables, we have to wait until it's resolved.
-        if self_ty.has_non_region_infer() {
+        if key.has_non_region_infer() {
             candidates.ambiguous = true;
             return;
         }
 
-        if let Ok(layout) = tcx.layout_of(obligation.param_env.and(self_ty))
+        if let Ok(layout) = tcx.layout_of(key)
             && layout.layout.is_pointer_like(&tcx.data_layout)
         {
             candidates.vec.push(BuiltinCandidate { has_nested: false });
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 6a64829..0d9f55d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -132,6 +132,12 @@
             }
         };
 
+        // The obligations returned by confirmation are recursively evaluated
+        // so we need to make sure they have the correct depth.
+        for subobligation in impl_src.borrow_nested_obligations_mut() {
+            subobligation.set_depth_from_parent(obligation.recursion_depth);
+        }
+
         if !obligation.predicate.is_const_if_const() {
             // normalize nested predicates according to parent predicate's constness.
             impl_src = impl_src.map(|mut o| {
@@ -156,7 +162,10 @@
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
         let (def_id, substs) = match *placeholder_self_ty.kind() {
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                (def_id, substs)
+            }
             _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
         };
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b72ff5b..3baf1c9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -537,14 +537,22 @@
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         self.evaluation_probe(|this| {
-            if this.tcx().trait_solver_next() {
-                this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])
+            let goal =
+                this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
+            let mut result = if this.tcx().trait_solver_next() {
+                this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
             } else {
                 this.evaluate_predicate_recursively(
                     TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
                     obligation.clone(),
-                )
+                )?
+            };
+            // If the predicate has done any inference, then downgrade the
+            // result to ambiguous.
+            if this.infcx.shallow_resolve(goal) != goal {
+                result = result.max(EvaluatedToAmbig);
             }
+            Ok(result)
         })
     }
 
@@ -1645,7 +1653,9 @@
 
         let tcx = self.infcx.tcx;
         let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                (def_id, substs)
+            }
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -1783,12 +1793,12 @@
             .infcx
             .at(&obligation.cause, obligation.param_env)
             .sup(DefineOpaqueTypes::No, obligation.predicate, infer_projection)
-            .map_or(false, |InferOk { obligations, value: () }| {
+            .is_ok_and(|InferOk { obligations, value: () }| {
                 self.evaluate_predicates_recursively(
                     TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
                     nested_obligations.into_iter().chain(obligations),
                 )
-                .map_or(false, |res| res.may_apply())
+                .is_ok_and(|res| res.may_apply())
             });
 
         if is_match {
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
new file mode 100644
index 0000000..af8dd0d
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -0,0 +1,55 @@
+use rustc_infer::infer::at::At;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::traits::{FulfillmentError, TraitEngine};
+use rustc_middle::ty::{self, Ty};
+
+use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation};
+
+pub trait StructurallyNormalizeExt<'tcx> {
+    fn structurally_normalize(
+        &self,
+        ty: Ty<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>;
+}
+
+impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
+    fn structurally_normalize(
+        &self,
+        mut ty: Ty<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
+        assert!(!ty.is_ty_var(), "should have resolved vars before calling");
+
+        if self.infcx.tcx.trait_solver_next() {
+            while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
+                let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::NormalizeProjectionType,
+                    span: self.cause.span,
+                });
+                let obligation = Obligation::new(
+                    self.infcx.tcx,
+                    self.cause.clone(),
+                    self.param_env,
+                    ty::Binder::dummy(ty::ProjectionPredicate {
+                        projection_ty,
+                        term: new_infer_ty.into(),
+                    }),
+                );
+                if self.infcx.predicate_may_hold(&obligation) {
+                    fulfill_cx.register_predicate_obligation(self.infcx, obligation);
+                    let errors = fulfill_cx.select_where_possible(self.infcx);
+                    if !errors.is_empty() {
+                        return Err(errors);
+                    }
+                    ty = self.infcx.resolve_vars_if_possible(new_infer_ty);
+                } else {
+                    break;
+                }
+            }
+            Ok(ty)
+        } else {
+            Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
+        }
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index f7a3126..cc674ce 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -4,6 +4,7 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::traits::util::PredicateSet;
 use rustc_infer::traits::ImplSource;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
@@ -379,8 +380,8 @@
     tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
 }
 
-pub(super) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers {
         own_existential_vtable_entries,
         vtable_entries,
         vtable_trait_upcasting_coercion_new_vptr_slot,
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 2f9e480..e447ab9 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -679,7 +679,7 @@
             | ty::PredicateKind::ConstEquate(..)
             | ty::PredicateKind::Ambiguous
             | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
-                bug!("unexpected predicate {}", &self)
+                bug!("unexpected predicate {self}")
             }
         };
         value.map(|value| chalk_ir::Binders::new(binders, value))
diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs
index a5ebc26..8834449 100644
--- a/compiler/rustc_traits/src/chalk/mod.rs
+++ b/compiler/rustc_traits/src/chalk/mod.rs
@@ -7,8 +7,8 @@
 pub(crate) mod lowering;
 
 use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
+use rustc_middle::query::Providers;
 use rustc_middle::traits::ChalkRustInterner;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitable};
 
 use rustc_infer::infer::canonical::{
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 6f81d34..ddba03b 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -3,9 +3,9 @@
 // seems likely that they should eventually be merged into more
 // general routines.
 
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
-use rustc_middle::traits::CodegenObligationError;
+use rustc_middle::traits::{CodegenObligationError, DefiningAnchor};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::{
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index fcdffc7..83f6c7d 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -2,7 +2,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index e94c8ef..f5b2753 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -1,5 +1,6 @@
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_middle::ty::query::Providers;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
@@ -15,6 +16,7 @@
     tcx: TyCtxt<'tcx>,
     canonical_goal: CanonicalPredicateGoal<'tcx>,
 ) -> Result<EvaluationResult, OverflowError> {
+    assert!(!tcx.trait_solver_next());
     debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
     // HACK This bubble is required for this tests to pass:
     // impl-trait/issue99642.rs
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index f5bba14..49cbf9e 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -6,12 +6,12 @@
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::query::OutlivesBound;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
+use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
 use rustc_trait_selection::traits::wf;
 use rustc_trait_selection::traits::ObligationCtxt;
 use smallvec::{smallvec, SmallVec};
@@ -37,7 +37,7 @@
     ocx: &ObligationCtxt<'_, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     ty: Ty<'tcx>,
-) -> Fallible<Vec<OutlivesBound<'tcx>>> {
+) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
     let tcx = ocx.infcx.tcx;
 
     // Sometimes when we ask what it takes for T: WF, we get back that
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 8bea558..b0f9c57 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -23,7 +23,7 @@
 
 pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
 
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 pub fn provide(p: &mut Providers) {
     dropck_outlives::provide(p);
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 5da0f16..94c33ef 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -1,6 +1,6 @@
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::{Normalized, ObligationCause};
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 36d80a0..b552ba4 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -1,6 +1,6 @@
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::{
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 1962211..faf9851 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -1,8 +1,9 @@
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
-use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCauseCode;
-use rustc_middle::ty::query::Providers;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
 use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{ParamEnvAnd, Predicate};
 use rustc_middle::ty::{UserSelfTy, UserSubsts, UserType};
@@ -15,7 +16,6 @@
 use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
 use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
 use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
-use rustc_trait_selection::traits::query::{Fallible, NoSolution};
 use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};
 use std::fmt;
 
@@ -160,7 +160,7 @@
 fn type_op_normalize<'tcx, T>(
     ocx: &ObligationCtxt<'_, 'tcx>,
     key: ParamEnvAnd<'tcx, Normalize<T>>,
-) -> Fallible<T>
+) -> Result<T, NoSolution>
 where
     T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx>,
 {
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index 5bc3e3c..c416aa5 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -1,61 +1,31 @@
-ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
+ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
+
+ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
+
+ty_utils_array_not_supported = array construction is not supported in generic constants
+
+ty_utils_assign_not_supported = assignment is not supported in generic constants
+
+ty_utils_binary_not_supported = unsupported binary operation in generic constants
+
+ty_utils_block_not_supported = blocks are not supported in generic constants
+
+ty_utils_borrow_not_supported = borrowing is not supported in generic constants
+
+ty_utils_box_not_supported = allocations are not allowed in generic constants
+
+ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
+
+ty_utils_const_block_not_supported = const blocks are not supported in generic constants
+
+ty_utils_control_flow_not_supported = control flow is not supported in generic constants
+
+ty_utils_field_not_supported = field access is not supported in generic constants
 
 ty_utils_generic_constant_too_complex = overly complex generic constant
     .help = consider moving this anonymous constant into a `const` function
     .maybe_supported = this operation may be supported in the future
 
-ty_utils_borrow_not_supported = borrowing is not supported in generic constants
-
-ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants
-
-ty_utils_array_not_supported = array construction is not supported in generic constants
-
-ty_utils_block_not_supported = blocks are not supported in generic constants
-
-ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
-
-ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
-
-ty_utils_index_not_supported = indexing is not supported in generic constants
-
-ty_utils_field_not_supported = field access is not supported in generic constants
-
-ty_utils_const_block_not_supported = const blocks are not supported in generic constants
-
-ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants
-
-ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
-
-ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
-
-ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
-
-ty_utils_box_not_supported = allocations are not allowed in generic constants
-
-ty_utils_binary_not_supported = unsupported binary operation in generic constants
-
-ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow
-
-ty_utils_assign_not_supported = assignment is not supported in generic constants
-
-ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
-
-ty_utils_control_flow_not_supported = control flow is not supported in generic constants
-
-ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
-
-ty_utils_operation_not_supported = unsupported operation in generic constants
-
-ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
-
-ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
-
-ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
-
-ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
-
-ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
-
 ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope
     .label = generic argument `{$arg}` used twice
     .note = for this opaque type
@@ -63,3 +33,33 @@
 ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope
     .label = argument `{$arg}` is not a generic parameter
     .note = for this opaque type
+
+ty_utils_index_not_supported = indexing is not supported in generic constants
+
+ty_utils_inline_asm_not_supported = assembly is not supported in generic constants
+
+ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow
+
+ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants
+
+ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field
+
+ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop
+
+ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
+
+ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
+
+ty_utils_operation_not_supported = unsupported operation in generic constants
+
+ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
+
+ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants
+
+ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
+
+ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item
+
+ty_utils_yield_not_supported = generator control flow is not allowed in generic constants
+
+ty_utils_zero_length_simd_type = monomorphising SIMD type `{$ty}` of zero length
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 271284b..15c1910 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -1,5 +1,6 @@
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
     fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
 };
@@ -14,8 +15,8 @@
 
 use std::iter;
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
 }
 
 // NOTE(eddyb) this is private to avoid using it from outside of
@@ -237,6 +238,7 @@
     layout: TyAndLayout<'tcx>,
     offset: Size,
     is_return: bool,
+    drop_target_pointee: Option<Ty<'tcx>>,
 ) {
     // Booleans are always a noundef i1 that needs to be zero-extended.
     if scalar.is_bool() {
@@ -250,14 +252,24 @@
     }
 
     // Only pointer types handled below.
-    let Scalar::Initialized { value: Pointer(_), valid_range} = scalar else { return };
+    let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return };
 
-    if !valid_range.contains(0) {
+    // Set `nonnull` if the validity range excludes zero, or for the argument to `drop_in_place`,
+    // which must be nonnull per its documented safety requirements.
+    if !valid_range.contains(0) || drop_target_pointee.is_some() {
         attrs.set(ArgAttribute::NonNull);
     }
 
     if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
-        if let Some(kind) = pointee.safe {
+        let kind = if let Some(kind) = pointee.safe {
+            Some(kind)
+        } else if let Some(pointee) = drop_target_pointee {
+            // The argument to `drop_in_place` is semantically equivalent to a mutable reference.
+            Some(PointerKind::MutableRef { unpin: pointee.is_unpin(cx.tcx, cx.param_env()) })
+        } else {
+            None
+        };
+        if let Some(kind) = kind {
             attrs.pointee_align = Some(pointee.align);
 
             // `Box` are not necessarily dereferenceable for the entire duration of the function as
@@ -361,10 +373,18 @@
     use SpecAbi::*;
     let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
 
+    let is_drop_in_place =
+        fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn();
+
     let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
         let span = tracing::debug_span!("arg_of");
         let _entered = span.enter();
         let is_return = arg_idx.is_none();
+        let is_drop_target = is_drop_in_place && arg_idx == Some(0);
+        let drop_target_pointee = is_drop_target.then(|| match ty.kind() {
+            ty::RawPtr(ty::TypeAndMut { ty, .. }) => *ty,
+            _ => bug!("argument to drop_in_place is not a raw ptr: {:?}", ty),
+        });
 
         let layout = cx.layout_of(ty)?;
         let layout = if force_thin_self_ptr && arg_idx == Some(0) {
@@ -378,7 +398,15 @@
 
         let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
             let mut attrs = ArgAttributes::new();
-            adjust_for_rust_scalar(*cx, &mut attrs, scalar, *layout, offset, is_return);
+            adjust_for_rust_scalar(
+                *cx,
+                &mut attrs,
+                scalar,
+                *layout,
+                offset,
+                is_return,
+                drop_target_pointee,
+            );
             attrs
         });
 
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 9029ba2..ed574f2 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -4,11 +4,12 @@
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt};
 use rustc_span::symbol::kw;
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
         associated_item,
         associated_item_def_ids,
         associated_items,
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
index 3b1abdc..51b9088 100644
--- a/compiler/rustc_ty_utils/src/common_traits.rs
+++ b/compiler/rustc_ty_utils/src/common_traits.rs
@@ -2,6 +2,7 @@
 
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_trait_selection::traits;
 
@@ -32,12 +33,6 @@
     traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
 }
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
-        is_copy_raw,
-        is_sized_raw,
-        is_freeze_raw,
-        is_unpin_raw,
-        ..*providers
-    };
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers { is_copy_raw, is_sized_raw, is_freeze_raw, is_unpin_raw, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 3dd1d05..1219bb4 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -2,6 +2,7 @@
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
+use rustc_middle::query::Providers;
 use rustc_middle::thir::visit;
 use rustc_middle::thir::visit::Visitor;
 use rustc_middle::ty::abstract_const::CastKind;
@@ -115,9 +116,7 @@
             let sp = node.span;
             match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
                 Ok(c) => c,
-                Err(LitToConstError::Reported(guar)) => {
-                    tcx.const_error_with_guaranteed(node.ty, guar)
-                }
+                Err(LitToConstError::Reported(guar)) => tcx.const_error(node.ty, guar),
                 Err(LitToConstError::TypeError) => {
                     bug!("encountered type error in lit_to_const")
                 }
@@ -423,6 +422,6 @@
     Ok(Some(ty::EarlyBinder(recurse_build(tcx, body, body_id, root_span)?)))
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { destructure_const, thir_abstract_const, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { destructure_const, thir_abstract_const, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 5ca5d14..081be06 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -1,8 +1,9 @@
 use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { assumed_wf_types, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { assumed_wf_types, ..*providers };
 }
 
 fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index eb3c21163..36a20c7 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,6 +1,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
@@ -319,6 +320,6 @@
     })
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { resolve_instance, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { resolve_instance, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index f7c7558..16cd8bc 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -3,6 +3,7 @@
 use rustc_index::bit_set::BitSet;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
@@ -22,8 +23,8 @@
 };
 use crate::layout_sanity_check::sanity_check_layout;
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { layout_of, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { layout_of, ..*providers };
 }
 
 #[instrument(skip(tcx, query), level = "debug")]
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 8306c5a..55b8857 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -21,7 +21,7 @@
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 mod abi;
 mod assoc;
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index a04f85a..1f9701b 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -2,6 +2,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
@@ -323,8 +324,8 @@
     .map(|components| tcx.mk_type_list(&components))
 }
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
         needs_drop_raw,
         has_significant_drop_raw,
         adt_drop_tys,
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 25ebb33..4e91dd3 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::{def::DefKind, def_id::LocalDefId};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -192,6 +193,6 @@
     }
 }
 
-pub(super) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { opaque_types_defined_by, ..*providers };
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers { opaque_types_defined_by, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 26d6dea..0b5e27c 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -2,7 +2,7 @@
 
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
 
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
index 9cb0fc1..215acbe 100644
--- a/compiler/rustc_ty_utils/src/structural_match.rs
+++ b/compiler/rustc_ty_utils/src/structural_match.rs
@@ -1,5 +1,5 @@
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use rustc_infer::infer::TyCtxtInferExt;
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 78efcce..65dc3c3 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -2,6 +2,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty,
     TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
@@ -566,8 +567,8 @@
     unsizing_params
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
         asyncness,
         adt_sized_constraint,
         param_env,
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index c9675f9..45a2e90 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -21,6 +21,7 @@
     (),
     bool,
     usize,
+    u8,
     u16,
     u32,
     u64,
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 6f2ba95..01d1fdc 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -37,6 +37,9 @@
     #[rustc_allocator_zeroed]
     #[rustc_nounwind]
     fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
+
+    #[cfg(not(bootstrap))]
+    static __rust_no_alloc_shim_is_unstable: u8;
 }
 
 /// The global memory allocator.
@@ -90,7 +93,14 @@
 #[must_use = "losing the pointer will leak memory"]
 #[inline]
 pub unsafe fn alloc(layout: Layout) -> *mut u8 {
-    unsafe { __rust_alloc(layout.size(), layout.align()) }
+    unsafe {
+        // Make sure we don't accidentally allow omitting the allocator shim in
+        // stable code until it is actually stabilized.
+        #[cfg(not(bootstrap))]
+        core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable);
+
+        __rust_alloc(layout.size(), layout.align())
+    }
 }
 
 /// Deallocate memory with the global allocator.
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 2daef82..1f8a1ec 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -3021,7 +3021,7 @@
         })
     }
 
-    /// Returns a mutable reference to the of the element that the cursor is
+    /// Returns a mutable reference to the key of the element that the cursor is
     /// currently pointing to.
     ///
     /// This returns `None` if the cursor is currently pointing to the
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 088139a..498fbd9 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2623,6 +2623,15 @@
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "fmt_arguments_to_string_specialization", since = "CURRENT_RUSTC_VERSION")]
+impl ToString for fmt::Arguments<'_> {
+    #[inline]
+    fn to_string(&self) -> String {
+        crate::fmt::format(*self)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<str> for String {
     #[inline]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 7347980..bfdb7a9 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -502,6 +502,7 @@
     /// assert_eq!(*five, 5)
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
@@ -535,6 +536,7 @@
     ///
     /// [zeroed]: mem::MaybeUninit::zeroed
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
@@ -844,6 +846,7 @@
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
@@ -871,6 +874,7 @@
     ///
     /// [zeroed]: mem::MaybeUninit::zeroed
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
@@ -1300,10 +1304,10 @@
         mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
     ) -> *mut ArcInner<T> {
         let layout = arcinner_layout_for_value_layout(value_layout);
-        unsafe {
-            Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner)
-                .unwrap_or_else(|_| handle_alloc_error(layout))
-        }
+
+        let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+
+        unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) }
     }
 
     /// Allocates an `ArcInner<T>` with sufficient space for
@@ -1321,7 +1325,16 @@
 
         let ptr = allocate(layout)?;
 
-        // Initialize the ArcInner
+        let inner = unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) };
+
+        Ok(inner)
+    }
+
+    unsafe fn initialize_arcinner(
+        ptr: NonNull<[u8]>,
+        layout: Layout,
+        mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
+    ) -> *mut ArcInner<T> {
         let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr());
         debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout);
 
@@ -1330,7 +1343,7 @@
             ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
         }
 
-        Ok(inner)
+        inner
     }
 
     /// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index 2f1ee8b..5ecd047 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -178,7 +178,8 @@
             )
         };
 
-        let len = SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end);
+        // SAFETY: `dst_buf` and `dst_end` are the start and end of the buffer.
+        let len = unsafe { SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end) };
 
         let src = unsafe { iterator.as_inner().as_into_iter() };
         // check if SourceIter contract was upheld
@@ -239,7 +240,7 @@
     /// `Iterator::__iterator_get_unchecked` calls with a `TrustedRandomAccessNoCoerce` bound
     /// on `I` which means the caller of this method must take the safety conditions
     /// of that trait into consideration.
-    fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize;
+    unsafe fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize;
 }
 
 impl<T, I> SpecInPlaceCollect<T, I> for I
@@ -247,7 +248,7 @@
     I: Iterator<Item = T>,
 {
     #[inline]
-    default fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
+    default unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
         // use try-fold since
         // - it vectorizes better for some iterator adapters
         // - unlike most internal iteration methods, it only takes a &mut self
@@ -265,7 +266,7 @@
     I: Iterator<Item = T> + TrustedRandomAccessNoCoerce,
 {
     #[inline]
-    fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
+    unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
         let len = self.size();
         let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf };
         for i in 0..len {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 97da6f0..82f30a2 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -646,14 +646,14 @@
     ///
     /// // The vector contains no items, even though it has capacity for more
     /// assert_eq!(vec.len(), 0);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     ///
     /// // These are all done without reallocating...
     /// for i in 0..10 {
     ///     vec.push(i);
     /// }
     /// assert_eq!(vec.len(), 10);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     ///
     /// // ...but this may make the vector reallocate
     /// vec.push(11);
@@ -877,7 +877,7 @@
     /// ```
     /// let mut vec: Vec<i32> = Vec::with_capacity(10);
     /// vec.push(42);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1028,7 +1028,7 @@
     /// ```
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
     /// ```
@@ -1055,7 +1055,7 @@
     /// ```
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// vec.shrink_to(4);
     /// assert!(vec.capacity() >= 4);
     /// vec.shrink_to(0);
@@ -1090,7 +1090,7 @@
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
     ///
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// let slice = vec.into_boxed_slice();
     /// assert_eq!(slice.into_vec().capacity(), 3);
     /// ```
diff --git a/library/core/benches/fmt.rs b/library/core/benches/fmt.rs
index ff726ff..d1cdb12 100644
--- a/library/core/benches/fmt.rs
+++ b/library/core/benches/fmt.rs
@@ -1,13 +1,13 @@
 use std::fmt::{self, Write as FmtWrite};
 use std::io::{self, Write as IoWrite};
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn write_vec_value(bh: &mut Bencher) {
     bh.iter(|| {
         let mut mem = Vec::new();
         for _ in 0..1000 {
-            mem.write_all("abc".as_bytes()).unwrap();
+            mem.write_all(black_box("abc").as_bytes()).unwrap();
         }
     });
 }
@@ -18,7 +18,7 @@
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            wr.write_all("abc".as_bytes()).unwrap();
+            wr.write_all(black_box("abc").as_bytes()).unwrap();
         }
     });
 }
@@ -29,7 +29,7 @@
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            write!(wr, "abc").unwrap();
+            write!(wr, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -40,7 +40,7 @@
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            write!(wr, "{}", "abc").unwrap();
+            write!(wr, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -51,7 +51,7 @@
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            write!(wr, "{:?}", "☃").unwrap();
+            write!(wr, "{:?}", black_box("☃")).unwrap();
         }
     });
 }
@@ -61,7 +61,7 @@
     bh.iter(|| {
         let mut mem = String::new();
         for _ in 0..1000 {
-            mem.write_str("abc").unwrap();
+            mem.write_str(black_box("abc")).unwrap();
         }
     });
 }
@@ -72,7 +72,7 @@
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            wr.write_str("abc").unwrap();
+            wr.write_str(black_box("abc")).unwrap();
         }
     });
 }
@@ -82,7 +82,7 @@
     bh.iter(|| {
         let mut mem = String::new();
         for _ in 0..1000 {
-            write!(mem, "abc").unwrap();
+            write!(mem, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -93,7 +93,7 @@
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            write!(wr, "{}", "abc").unwrap();
+            write!(wr, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -104,7 +104,7 @@
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            write!(wr, "{:?}", "☃").unwrap();
+            write!(wr, "{:?}", black_box("☃")).unwrap();
         }
     });
 }
@@ -115,7 +115,7 @@
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            write!(wr, "{:?}", "Hello, World!").unwrap();
+            write!(wr, "{:?}", black_box("Hello, World!")).unwrap();
         }
     });
 }
diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs
index 9193c79..60ef832 100644
--- a/library/core/benches/iter.rs
+++ b/library/core/benches/iter.rs
@@ -404,7 +404,7 @@
 
 /// Exercises the iter::Copied specialization for slice::Iter
 #[bench]
-fn bench_copied_chunks(b: &mut Bencher) {
+fn bench_next_chunk_copied(b: &mut Bencher) {
     let v = vec![1u8; 1024];
 
     b.iter(|| {
@@ -421,7 +421,7 @@
 
 /// Exercises the TrustedRandomAccess specialization in ArrayChunks
 #[bench]
-fn bench_trusted_random_access_chunks(b: &mut Bencher) {
+fn bench_next_chunk_trusted_random_access(b: &mut Bencher) {
     let v = vec![1u8; 1024];
 
     b.iter(|| {
@@ -437,3 +437,45 @@
             .sum::<Wrapping<u64>>()
     })
 }
+
+#[bench]
+fn bench_next_chunk_filter_even(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i % 2 == 0).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_predictably_true(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i < 100).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_mostly_false(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i > 900).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_even(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i % 2 == 0).then(|| i)).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_predictably_true(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i < 100).then(|| i)).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_mostly_false(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i > 900).then(|| i)).next_chunk::<32>())
+}
diff --git a/library/core/benches/num/dec2flt/mod.rs b/library/core/benches/num/dec2flt/mod.rs
index 305baa6..fb4a786 100644
--- a/library/core/benches/num/dec2flt/mod.rs
+++ b/library/core/benches/num/dec2flt/mod.rs
@@ -1,57 +1,57 @@
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_0(b: &mut Bencher) {
-    b.iter(|| "0.0".parse::<f64>());
+    b.iter(|| black_box("0.0").parse::<f64>());
 }
 
 #[bench]
 fn bench_42(b: &mut Bencher) {
-    b.iter(|| "42".parse::<f64>());
+    b.iter(|| black_box("42").parse::<f64>());
 }
 
 #[bench]
 fn bench_huge_int(b: &mut Bencher) {
     // 2^128 - 1
-    b.iter(|| "170141183460469231731687303715884105727".parse::<f64>());
+    b.iter(|| black_box("170141183460469231731687303715884105727").parse::<f64>());
 }
 
 #[bench]
 fn bench_short_decimal(b: &mut Bencher) {
-    b.iter(|| "1234.5678".parse::<f64>());
+    b.iter(|| black_box("1234.5678").parse::<f64>());
 }
 
 #[bench]
 fn bench_pi_long(b: &mut Bencher) {
-    b.iter(|| "3.14159265358979323846264338327950288".parse::<f64>());
+    b.iter(|| black_box("3.14159265358979323846264338327950288").parse::<f64>());
 }
 
 #[bench]
 fn bench_pi_short(b: &mut Bencher) {
-    b.iter(|| "3.141592653589793".parse::<f64>())
+    b.iter(|| black_box("3.141592653589793").parse::<f64>())
 }
 
 #[bench]
 fn bench_1e150(b: &mut Bencher) {
-    b.iter(|| "1e150".parse::<f64>());
+    b.iter(|| black_box("1e150").parse::<f64>());
 }
 
 #[bench]
 fn bench_long_decimal_and_exp(b: &mut Bencher) {
-    b.iter(|| "727501488517303786137132964064381141071e-123".parse::<f64>());
+    b.iter(|| black_box("727501488517303786137132964064381141071e-123").parse::<f64>());
 }
 
 #[bench]
 fn bench_min_subnormal(b: &mut Bencher) {
-    b.iter(|| "5e-324".parse::<f64>());
+    b.iter(|| black_box("5e-324").parse::<f64>());
 }
 
 #[bench]
 fn bench_min_normal(b: &mut Bencher) {
-    b.iter(|| "2.2250738585072014e-308".parse::<f64>());
+    b.iter(|| black_box("2.2250738585072014e-308").parse::<f64>());
 }
 
 #[bench]
 fn bench_max(b: &mut Bencher) {
-    b.iter(|| "1.7976931348623157e308".parse::<f64>());
+    b.iter(|| black_box("1.7976931348623157e308").parse::<f64>());
 }
diff --git a/library/core/benches/num/flt2dec/mod.rs b/library/core/benches/num/flt2dec/mod.rs
index 32fd5e6..1a330ef5 100644
--- a/library/core/benches/num/flt2dec/mod.rs
+++ b/library/core/benches/num/flt2dec/mod.rs
@@ -7,7 +7,7 @@
 use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
 use std::io::Write;
 use std::vec::Vec;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
@@ -22,7 +22,7 @@
 
     b.iter(|| {
         buf.clear();
-        write!(&mut buf, "{}", 3.1415926f64).unwrap()
+        write!(black_box(&mut buf), "{}", black_box(3.1415926f64)).unwrap()
     });
 }
 
@@ -32,6 +32,6 @@
 
     b.iter(|| {
         buf.clear();
-        write!(&mut buf, "{}", f64::MAX).unwrap()
+        write!(black_box(&mut buf), "{}", black_box(f64::MAX)).unwrap()
     });
 }
diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs
index 2f9cad2..b97014d 100644
--- a/library/core/benches/num/mod.rs
+++ b/library/core/benches/num/mod.rs
@@ -3,7 +3,7 @@
 mod int_log;
 
 use std::str::FromStr;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 const ASCII_NUMBERS: [&str; 19] = [
     "0",
@@ -36,7 +36,7 @@
                     .iter()
                     .cycle()
                     .take(5_000)
-                    .filter_map(|s| <$t>::from_str(s).ok())
+                    .filter_map(|s| <$t>::from_str(black_box(s)).ok())
                     .max()
             })
         }
@@ -52,7 +52,7 @@
                     .iter()
                     .cycle()
                     .take(5_000)
-                    .filter_map(|s| <$t>::from_str_radix(s, $radix).ok())
+                    .filter_map(|s| <$t>::from_str_radix(black_box(s), $radix).ok())
                     .max()
             })
         }
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index bb93ea5..d1c1ae6 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -866,7 +866,7 @@
 ///
 /// A data provider provides values by calling this type's provide methods.
 #[unstable(feature = "provide_any", issue = "96024")]
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 pub struct Demand<'a>(dyn Erased<'a> + 'a);
 
 impl<'a> Demand<'a> {
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index 7fd14a7..ef8e4d0 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -91,7 +91,7 @@
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn escape_default(c: u8) -> EscapeDefault {
-    let mut data = [0; 4];
+    let mut data = [Char::Null; 4];
     let range = escape::escape_ascii_into(&mut data, c);
     EscapeDefault(escape::EscapeIterInner::new(data, range))
 }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index a96dfaf..744767a 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2030,6 +2030,27 @@
 }
 
 impl<T: ?Sized> UnsafeCell<T> {
+    /// Converts from `&mut T` to `&mut UnsafeCell<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(unsafe_cell_from_mut)]
+    /// use std::cell::UnsafeCell;
+    ///
+    /// let mut val = 42;
+    /// let uc = UnsafeCell::from_mut(&mut val);
+    ///
+    /// *uc.get_mut() -= 1;
+    /// assert_eq!(*uc.get_mut(), 41);
+    /// ```
+    #[inline(always)]
+    #[unstable(feature = "unsafe_cell_from_mut", issue = "111645")]
+    pub const fn from_mut(value: &mut T) -> &mut UnsafeCell<T> {
+        // SAFETY: `UnsafeCell<T>` has the same memory layout as `T` due to #[repr(transparent)].
+        unsafe { &mut *(value as *mut T as *mut UnsafeCell<T>) }
+    }
+
     /// Gets a mutable pointer to the wrapped value.
     ///
     /// This can be cast to a pointer of any kind.
@@ -2100,6 +2121,8 @@
     ///
     /// let m = MaybeUninit::<UnsafeCell<i32>>::uninit();
     /// unsafe { UnsafeCell::raw_get(m.as_ptr()).write(5); }
+    /// // avoid below which references to uninitialized data
+    /// // unsafe { UnsafeCell::get(&*m.as_ptr()).write(5); }
     /// let uc = unsafe { m.assume_init() };
     ///
     /// assert_eq!(uc.into_inner(), 5);
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 1dfa9c3..515b8d2 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -392,13 +392,13 @@
     #[inline]
     pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
         match self {
-            '\0' => EscapeDebug::backslash(b'0'),
-            '\t' => EscapeDebug::backslash(b't'),
-            '\r' => EscapeDebug::backslash(b'r'),
-            '\n' => EscapeDebug::backslash(b'n'),
-            '\\' => EscapeDebug::backslash(b'\\'),
-            '"' if args.escape_double_quote => EscapeDebug::backslash(b'"'),
-            '\'' if args.escape_single_quote => EscapeDebug::backslash(b'\''),
+            '\0' => EscapeDebug::backslash(ascii::Char::Digit0),
+            '\t' => EscapeDebug::backslash(ascii::Char::SmallT),
+            '\r' => EscapeDebug::backslash(ascii::Char::SmallR),
+            '\n' => EscapeDebug::backslash(ascii::Char::SmallN),
+            '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus),
+            '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark),
+            '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe),
             _ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
                 EscapeDebug::from_unicode(self.escape_unicode())
             }
@@ -503,11 +503,11 @@
     #[inline]
     pub fn escape_default(self) -> EscapeDefault {
         match self {
-            '\t' => EscapeDefault::backslash(b't'),
-            '\r' => EscapeDefault::backslash(b'r'),
-            '\n' => EscapeDefault::backslash(b'n'),
-            '\\' | '\'' | '"' => EscapeDefault::backslash(self as u8),
-            '\x20'..='\x7e' => EscapeDefault::printable(self as u8),
+            '\t' => EscapeDefault::backslash(ascii::Char::SmallT),
+            '\r' => EscapeDefault::backslash(ascii::Char::SmallR),
+            '\n' => EscapeDefault::backslash(ascii::Char::SmallN),
+            '\\' | '\'' | '"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
+            '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()),
             _ => EscapeDefault::from_unicode(self.escape_unicode()),
         }
     }
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index e186db7..5c42912 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -38,6 +38,7 @@
 #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
 pub use self::methods::encode_utf8_raw;
 
+use crate::ascii;
 use crate::error::Error;
 use crate::escape;
 use crate::fmt::{self, Write};
@@ -152,7 +153,7 @@
 
 impl EscapeUnicode {
     fn new(chr: char) -> Self {
-        let mut data = [0; 10];
+        let mut data = [ascii::Char::Null; 10];
         let range = escape::escape_unicode_into(&mut data, chr);
         Self(escape::EscapeIterInner::new(data, range))
     }
@@ -218,14 +219,14 @@
 pub struct EscapeDefault(escape::EscapeIterInner<10>);
 
 impl EscapeDefault {
-    fn printable(chr: u8) -> Self {
-        let data = [chr, 0, 0, 0, 0, 0, 0, 0, 0, 0];
-        Self(escape::EscapeIterInner::new(data, 0..1))
+    fn printable(chr: ascii::Char) -> Self {
+        let data = [chr];
+        Self(escape::EscapeIterInner::from_array(data))
     }
 
-    fn backslash(chr: u8) -> Self {
-        let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
-        Self(escape::EscapeIterInner::new(data, 0..2))
+    fn backslash(chr: ascii::Char) -> Self {
+        let data = [ascii::Char::ReverseSolidus, chr];
+        Self(escape::EscapeIterInner::from_array(data))
     }
 
     fn from_unicode(esc: EscapeUnicode) -> Self {
@@ -307,9 +308,9 @@
         Self(EscapeDebugInner::Char(chr))
     }
 
-    fn backslash(chr: u8) -> Self {
-        let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
-        let iter = escape::EscapeIterInner::new(data, 0..2);
+    fn backslash(chr: ascii::Char) -> Self {
+        let data = [ascii::Char::ReverseSolidus, chr];
+        let iter = escape::EscapeIterInner::from_array(data);
         Self(EscapeDebugInner::Bytes(iter))
     }
 
@@ -318,7 +319,7 @@
     }
 
     fn clear(&mut self) {
-        let bytes = escape::EscapeIterInner::new([0; 10], 0..0);
+        let bytes = escape::EscapeIterInner::from_array([]);
         self.0 = EscapeDebugInner::Bytes(bytes);
     }
 }
diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs
index 20ac3cf..3d47141 100644
--- a/library/core/src/escape.rs
+++ b/library/core/src/escape.rs
@@ -1,34 +1,41 @@
 //! Helper code for character escaping.
 
+use crate::ascii;
 use crate::num::NonZeroUsize;
 use crate::ops::Range;
 
-const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
+const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap();
 
 /// Escapes a byte into provided buffer; returns length of escaped
 /// representation.
-pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range<u8> {
+pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range<u8> {
+    #[inline]
+    fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) {
+        ([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2)
+    }
+
     let (data, len) = match byte {
-        b'\t' => ([b'\\', b't', 0, 0], 2),
-        b'\r' => ([b'\\', b'r', 0, 0], 2),
-        b'\n' => ([b'\\', b'n', 0, 0], 2),
-        b'\\' => ([b'\\', b'\\', 0, 0], 2),
-        b'\'' => ([b'\\', b'\'', 0, 0], 2),
-        b'"' => ([b'\\', b'"', 0, 0], 2),
-        b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1),
-        _ => {
+        b'\t' => backslash(ascii::Char::SmallT),
+        b'\r' => backslash(ascii::Char::SmallR),
+        b'\n' => backslash(ascii::Char::SmallN),
+        b'\\' => backslash(ascii::Char::ReverseSolidus),
+        b'\'' => backslash(ascii::Char::Apostrophe),
+        b'\"' => backslash(ascii::Char::QuotationMark),
+        _ => if let Some(a) = byte.as_ascii() && !byte.is_ascii_control() {
+            ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1)
+        } else {
             let hi = HEX_DIGITS[usize::from(byte >> 4)];
             let lo = HEX_DIGITS[usize::from(byte & 0xf)];
-            ([b'\\', b'x', hi, lo], 4)
+            ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4)
         }
     };
     *output = data;
-    0..(len as u8)
+    0..len
 }
 
 /// Escapes a character into provided buffer using `\u{NNNN}` representation.
-pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> {
-    output[9] = b'}';
+pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range<u8> {
+    output[9] = ascii::Char::RightCurlyBracket;
 
     let ch = ch as u32;
     output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize];
@@ -41,7 +48,8 @@
     // or-ing 1 ensures that for ch==0 the code computes that one digit should
     // be printed.
     let start = (ch | 1).leading_zeros() as usize / 4 - 2;
-    output[start..start + 3].copy_from_slice(b"\\u{");
+    const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\\u{".as_ascii().unwrap();
+    output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX);
 
     (start as u8)..10
 }
@@ -52,29 +60,34 @@
 /// limited to u8 to reduce size of the structure.
 #[derive(Clone, Debug)]
 pub(crate) struct EscapeIterInner<const N: usize> {
-    // Invariant: data[alive] is all ASCII.
-    pub(crate) data: [u8; N],
+    // The element type ensures this is always ASCII, and thus also valid UTF-8.
+    pub(crate) data: [ascii::Char; N],
 
     // Invariant: alive.start <= alive.end <= N.
     pub(crate) alive: Range<u8>,
 }
 
 impl<const N: usize> EscapeIterInner<N> {
-    pub fn new(data: [u8; N], alive: Range<u8>) -> Self {
+    pub fn new(data: [ascii::Char; N], alive: Range<u8>) -> Self {
         const { assert!(N < 256) };
         debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}");
-        let this = Self { data, alive };
-        debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes());
-        this
+        Self { data, alive }
     }
 
-    fn as_bytes(&self) -> &[u8] {
+    pub fn from_array<const M: usize>(array: [ascii::Char; M]) -> Self {
+        const { assert!(M <= N) };
+
+        let mut data = [ascii::Char::Null; N];
+        data[..M].copy_from_slice(&array);
+        Self::new(data, 0..M as u8)
+    }
+
+    pub fn as_ascii(&self) -> &[ascii::Char] {
         &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]
     }
 
     pub fn as_str(&self) -> &str {
-        // SAFETY: self.data[self.alive] is all ASCII characters.
-        unsafe { crate::str::from_utf8_unchecked(self.as_bytes()) }
+        self.as_ascii().as_str()
     }
 
     pub fn len(&self) -> usize {
@@ -82,11 +95,11 @@
     }
 
     pub fn next(&mut self) -> Option<u8> {
-        self.alive.next().map(|i| self.data[usize::from(i)])
+        self.alive.next().map(|i| self.data[usize::from(i)].as_u8())
     }
 
     pub fn next_back(&mut self) -> Option<u8> {
-        self.alive.next_back().map(|i| self.data[usize::from(i)])
+        self.alive.next_back().map(|i| self.data[usize::from(i)].as_u8())
     }
 
     pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 07b1181..201bacb 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -517,8 +517,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(cstr_is_empty)]
-    ///
     /// use std::ffi::CStr;
     /// # use std::ffi::FromBytesWithNulError;
     ///
@@ -533,7 +531,8 @@
     /// # }
     /// ```
     #[inline]
-    #[unstable(feature = "cstr_is_empty", issue = "102444")]
+    #[stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
     pub const fn is_empty(&self) -> bool {
         // SAFETY: We know there is at least one byte; for empty strings it
         // is the NUL terminator.
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index b858942..b73abbb 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -203,7 +203,7 @@
 //     be UB.
 #[doc = include_str!("c_void.md")]
 #[cfg_attr(not(bootstrap), lang = "c_void")]
-#[repr(u8)]
+#[cfg_attr(not(doc), repr(u8))] // work around https://github.com/rust-lang/rust/issues/90435
 #[stable(feature = "core_c_void", since = "1.30.0")]
 pub enum c_void {
     #[unstable(
@@ -244,7 +244,7 @@
     target_os = "uefi",
     windows,
 ))]
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 #[unstable(
     feature = "c_variadic",
     reason = "the `c_variadic` feature has not been properly tested on \
@@ -296,7 +296,7 @@
     not(target_os = "uefi"),
     not(windows),
 ))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -316,7 +316,7 @@
 
 /// PowerPC ABI implementation of a `va_list`.
 #[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -336,7 +336,7 @@
 
 /// s390x ABI implementation of a `va_list`.
 #[cfg(target_arch = "s390x")]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -355,7 +355,7 @@
 
 /// x86_64 ABI implementation of a `va_list`.
 #[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -373,7 +373,7 @@
 }
 
 /// A wrapper for a `va_list`
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 89d5fac..3bbf5d8 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -45,7 +45,8 @@
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_exact_fixed_str` and `format_exact` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Don't inline this so callers that call both this and the above won't wind
@@ -71,7 +72,8 @@
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_shortest_str` and `format_shortest` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 fn float_to_decimal_display<T>(fmt: &mut Formatter<'_>, num: &T) -> Result
@@ -116,7 +118,8 @@
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_exact_exp_str` and `format_exact` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Don't inline this so callers that call both this and the above won't wind
@@ -143,7 +146,8 @@
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_shortest_exp_str` and `format_shortest` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Common code of floating point LowerExp and UpperExp.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index bac2f31..1786b30 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -1415,7 +1415,11 @@
     /// Takes the formatted parts and applies the padding.
     /// Assumes that the caller already has rendered the parts with required precision,
     /// so that `self.precision` can be ignored.
-    fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
+    ///
+    /// # Safety
+    ///
+    /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
+    unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
         if let Some(mut width) = self.width {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
@@ -1438,10 +1442,14 @@
             let len = formatted.len();
             let ret = if width <= len {
                 // no padding
-                self.write_formatted_parts(&formatted)
+                // SAFETY: Per the precondition.
+                unsafe { self.write_formatted_parts(&formatted) }
             } else {
                 let post_padding = self.padding(width - len, Alignment::Right)?;
-                self.write_formatted_parts(&formatted)?;
+                // SAFETY: Per the precondition.
+                unsafe {
+                    self.write_formatted_parts(&formatted)?;
+                }
                 post_padding.write(self)
             };
             self.fill = old_fill;
@@ -1449,20 +1457,20 @@
             ret
         } else {
             // this is the common case and we take a shortcut
-            self.write_formatted_parts(formatted)
+            // SAFETY: Per the precondition.
+            unsafe { self.write_formatted_parts(formatted) }
         }
     }
 
-    fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
-        fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
+    /// # Safety
+    ///
+    /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
+    unsafe fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
+        unsafe fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
             // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`.
             // It's safe to use for `numfmt::Part::Num` since every char `c` is between
-            // `b'0'` and `b'9'`, which means `s` is valid UTF-8.
-            // It's also probably safe in practice to use for `numfmt::Part::Copy(buf)`
-            // since `buf` should be plain ASCII, but it's possible for someone to pass
-            // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a
-            // public function.
-            // FIXME: Determine whether this could result in UB.
+            // `b'0'` and `b'9'`, which means `s` is valid UTF-8. It's safe to use for
+            // `numfmt::Part::Copy` due to this function's precondition.
             buf.write_str(unsafe { str::from_utf8_unchecked(s) })
         }
 
@@ -1489,11 +1497,15 @@
                         *c = b'0' + (v % 10) as u8;
                         v /= 10;
                     }
-                    write_bytes(self.buf, &s[..len])?;
+                    // SAFETY: Per the precondition.
+                    unsafe {
+                        write_bytes(self.buf, &s[..len])?;
+                    }
                 }
-                numfmt::Part::Copy(buf) => {
+                // SAFETY: Per the precondition.
+                numfmt::Part::Copy(buf) => unsafe {
                     write_bytes(self.buf, buf)?;
-                }
+                },
             }
         }
         Ok(())
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index d8365ae..4f42f73 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -52,8 +52,12 @@
 impl_uint! { u8 u16 u32 u64 u128 usize }
 
 /// A type that represents a specific radix
+///
+/// # Safety
+///
+/// `digit` must return an ASCII character.
 #[doc(hidden)]
-trait GenericRadix: Sized {
+unsafe trait GenericRadix: Sized {
     /// The number of digits.
     const BASE: u8;
 
@@ -129,7 +133,7 @@
 
 macro_rules! radix {
     ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
-        impl GenericRadix for $T {
+        unsafe impl GenericRadix for $T {
             const BASE: u8 = $base;
             const PREFIX: &'static str = $prefix;
             fn digit(x: u8) -> u8 {
@@ -407,7 +411,7 @@
             let parts = &[
                 numfmt::Part::Copy(buf_slice),
                 numfmt::Part::Zero(added_precision),
-                numfmt::Part::Copy(exp_slice)
+                numfmt::Part::Copy(exp_slice),
             ];
             let sign = if !is_nonnegative {
                 "-"
@@ -416,8 +420,9 @@
             } else {
                 ""
             };
-            let formatted = numfmt::Formatted{sign, parts};
-            f.pad_formatted_parts(&formatted)
+            let formatted = numfmt::Formatted { sign, parts };
+            // SAFETY: `buf_slice` and `exp_slice` contain only ASCII characters.
+            unsafe { f.pad_formatted_parts(&formatted) }
         }
 
         $(
diff --git a/library/core/src/future/join.rs b/library/core/src/future/join.rs
index 35f0dea..3f35179 100644
--- a/library/core/src/future/join.rs
+++ b/library/core/src/future/join.rs
@@ -4,7 +4,7 @@
 use crate::future::{poll_fn, Future};
 use crate::mem;
 use crate::pin::Pin;
-use crate::task::{Context, Poll};
+use crate::task::{ready, Context, Poll};
 
 /// Polls multiple futures simultaneously, returning a tuple
 /// of all results once complete.
@@ -118,7 +118,7 @@
                             fut
                         })
                     };
-                    // Despite how tempting it may be to `let () = fut.poll(cx).ready()?;`
+                    // Despite how tempting it may be to `let () = ready!(fut.poll(cx));`
                     // doing so would defeat the point of `join!`: to start polling eagerly all
                     // of the futures, to allow parallelizing the waits.
                     done &= fut.poll(cx).is_ready();
@@ -180,7 +180,7 @@
             // Do not mix match ergonomics with unsafe.
             match *self.as_mut().get_unchecked_mut() {
                 MaybeDone::Future(ref mut f) => {
-                    let val = Pin::new_unchecked(f).poll(cx).ready()?;
+                    let val = ready!(Pin::new_unchecked(f).poll(cx));
                     self.set(Self::Done(val));
                 }
                 MaybeDone::Done(_) => {}
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 19f8b94..5944a0d 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -228,7 +228,7 @@
 //!
 //!  - Operands implicitly convert to `Use` rvalues.
 //!  - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
-//!  - [`Discriminant`] and [`Len`] have associated functions.
+//!  - [`Discriminant`], [`Len`], and [`CopyForDeref`] have associated functions.
 //!  - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
 //!  - The binary operation `Offset` can be created via [`Offset`].
 //!  - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
@@ -279,6 +279,7 @@
 define!("mir_deinit", fn Deinit<T>(place: T));
 define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
 define!("mir_len", fn Len<T>(place: T) -> usize);
+define!("mir_copy_for_deref", fn CopyForDeref<T>(place: T) -> T);
 define!("mir_retag", fn Retag<T>(place: T));
 define!("mir_move", fn Move<T>(place: T) -> T);
 define!("mir_static", fn Static<T>(s: T) -> &'static T);
diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs
index a0afaa3..723657b 100644
--- a/library/core/src/iter/adapters/filter.rs
+++ b/library/core/src/iter/adapters/filter.rs
@@ -1,6 +1,9 @@
 use crate::fmt;
 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
 use crate::ops::Try;
+use core::array;
+use core::mem::{ManuallyDrop, MaybeUninit};
+use core::ops::ControlFlow;
 
 /// An iterator that filters the elements of `iter` with `predicate`.
 ///
@@ -57,6 +60,58 @@
     }
 
     #[inline]
+    fn next_chunk<const N: usize>(
+        &mut self,
+    ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+        let mut array: [MaybeUninit<Self::Item>; N] = MaybeUninit::uninit_array();
+
+        struct Guard<'a, T> {
+            array: &'a mut [MaybeUninit<T>],
+            initialized: usize,
+        }
+
+        impl<T> Drop for Guard<'_, T> {
+            #[inline]
+            fn drop(&mut self) {
+                if const { crate::mem::needs_drop::<T>() } {
+                    // SAFETY: self.initialized is always <= N, which also is the length of the array.
+                    unsafe {
+                        core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
+                            self.array.get_unchecked_mut(..self.initialized),
+                        ));
+                    }
+                }
+            }
+        }
+
+        let mut guard = Guard { array: &mut array, initialized: 0 };
+
+        let result = self.iter.try_for_each(|element| {
+            let idx = guard.initialized;
+            guard.initialized = idx + (self.predicate)(&element) as usize;
+
+            // SAFETY: Loop conditions ensure the index is in bounds.
+            unsafe { guard.array.get_unchecked_mut(idx) }.write(element);
+
+            if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
+        });
+
+        let guard = ManuallyDrop::new(guard);
+
+        match result {
+            ControlFlow::Break(()) => {
+                // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
+                Ok(unsafe { MaybeUninit::array_assume_init(array) })
+            }
+            ControlFlow::Continue(()) => {
+                let initialized = guard.initialized;
+                // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
+                Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
+            }
+        }
+    }
+
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index 6bdf53f..6934799 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -1,6 +1,7 @@
-use crate::fmt;
 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::mem::{ManuallyDrop, MaybeUninit};
 use crate::ops::{ControlFlow, Try};
+use crate::{array, fmt};
 
 /// An iterator that uses `f` to both filter and map elements from `iter`.
 ///
@@ -62,6 +63,65 @@
     }
 
     #[inline]
+    fn next_chunk<const N: usize>(
+        &mut self,
+    ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+        let mut array: [MaybeUninit<Self::Item>; N] = MaybeUninit::uninit_array();
+
+        struct Guard<'a, T> {
+            array: &'a mut [MaybeUninit<T>],
+            initialized: usize,
+        }
+
+        impl<T> Drop for Guard<'_, T> {
+            #[inline]
+            fn drop(&mut self) {
+                if const { crate::mem::needs_drop::<T>() } {
+                    // SAFETY: self.initialized is always <= N, which also is the length of the array.
+                    unsafe {
+                        core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
+                            self.array.get_unchecked_mut(..self.initialized),
+                        ));
+                    }
+                }
+            }
+        }
+
+        let mut guard = Guard { array: &mut array, initialized: 0 };
+
+        let result = self.iter.try_for_each(|element| {
+            let idx = guard.initialized;
+            let val = (self.f)(element);
+            guard.initialized = idx + val.is_some() as usize;
+
+            // SAFETY: Loop conditions ensure the index is in bounds.
+
+            unsafe {
+                let opt_payload_at = core::intrinsics::option_payload_ptr(&val);
+                let dst = guard.array.as_mut_ptr().add(idx);
+                crate::ptr::copy_nonoverlapping(opt_payload_at.cast(), dst, 1);
+                crate::mem::forget(val);
+            };
+
+            if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
+        });
+
+        let guard = ManuallyDrop::new(guard);
+
+        match result {
+            ControlFlow::Break(()) => {
+                // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
+                Ok(unsafe { MaybeUninit::array_assume_init(array) })
+            }
+            ControlFlow::Continue(()) => {
+                let initialized = guard.initialized;
+                // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
+                Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
+            }
+        }
+    }
+
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 520ec9a..2568aaf 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -310,6 +310,7 @@
 /// Real logic of both `Flatten` and `FlatMap` which simply delegate to
 /// this type.
 #[derive(Clone, Debug)]
+#[unstable(feature = "trusted_len", issue = "37572")]
 struct FlattenCompat<I, U> {
     iter: Fuse<I>,
     frontiter: Option<U>,
@@ -463,6 +464,7 @@
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 impl<I, U> Iterator for FlattenCompat<I, U>
 where
     I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -577,6 +579,7 @@
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
 where
     I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -646,6 +649,7 @@
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <[T; N] as IntoIterator>::IntoIter>
 where
@@ -653,6 +657,7 @@
 {
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <&'a [T; N] as IntoIterator>::IntoIter>
 where
@@ -660,6 +665,7 @@
 {
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <&'a mut [T; N] as IntoIterator>::IntoIter>
 where
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 76b3a32..0675e56 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -95,6 +95,16 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
+        _Self = "&[{A}]",
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
+        all(A = "{integer}", any(_Self = "&[{integral}]",)),
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
         _Self = "[{A}]",
         message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size",
         label = "try explicitly collecting into a `Vec<{A}>`",
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 26c51e8..6c419eb 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -133,6 +133,7 @@
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_maybe_uninit_uninit_array)]
 #![feature(const_nonnull_new)]
+#![feature(const_num_midpoint)]
 #![feature(const_option)]
 #![feature(const_option_ext)]
 #![feature(const_pin)]
@@ -215,6 +216,7 @@
 #![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
+#![feature(let_chains)]
 #![feature(link_llvm_intrinsics)]
 #![feature(macro_metavar_expr)]
 #![feature(min_specialization)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 0160608..8dab8d1 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -43,27 +43,17 @@
 /// ```
 #[unstable(feature = "internal_impls_macro", issue = "none")]
 macro marker_impls {
-    ( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
-        // This inner macro is needed because... idk macros are weird.
-        // It allows repeating `meta` on all impls.
-        #[unstable(feature = "internal_impls_macro", issue = "none")]
-        macro _impl {
-            ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
-                $(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
-            }
-        }
-        $( _impl! { $({$($bounds)*})? $T } )+
+    ( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
+        $(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {}
+        marker_impls! { $(#[$($meta)*])* $Trait for $($($rest)*)? }
     },
-    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
-        #[unstable(feature = "internal_impls_macro", issue = "none")]
-        macro _impl {
-            ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
-                $(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
-            }
-        }
+    ( $(#[$($meta:tt)*])* $Trait:ident for ) => {},
 
-        $( _impl! { $({$($bounds)*})? $T } )+
+    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
+        $(#[$($meta)*])* unsafe impl< $($($bounds)*)? > $Trait for $T {}
+        marker_impls! { $(#[$($meta)*])* unsafe $Trait for $($($rest)*)? }
     },
+    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for ) => {},
 }
 
 /// Types that can be transferred across thread boundaries.
@@ -695,7 +685,7 @@
 /// }
 /// ```
 ///
-/// This also in turn requires the annotation `T: 'a`, indicating
+/// This also in turn infers the lifetime bound `T: 'a`, indicating
 /// that any references in `T` are valid over the lifetime `'a`.
 ///
 /// When initializing a `Slice` you simply provide the value
@@ -986,6 +976,14 @@
 #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 pub trait ConstParamTy: StructuralEq {}
 
+/// Derive macro generating an impl of the trait `ConstParamTy`.
+#[rustc_builtin_macro]
+#[unstable(feature = "adt_const_params", issue = "95174")]
+#[cfg(not(bootstrap))]
+pub macro ConstParamTy($item:item) {
+    /* compiler built-in */
+}
+
 // FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure`
 // FIXME(generic_const_parameter_types): handle `ty::Tuple`
 marker_impls! {
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 2893052..afbfd6d 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -968,7 +968,7 @@
 /// Integers and other types implementing [`Copy`] are unaffected by `drop`.
 ///
 /// ```
-/// # #![cfg_attr(not(bootstrap), allow(drop_copy))]
+/// # #![cfg_attr(not(bootstrap), allow(dropping_copy_types))]
 /// #[derive(Copy, Clone)]
 /// struct Foo(u8);
 ///
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 1c6819b..4a035ad 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -940,6 +940,42 @@
         }
     }
 
+    /// Calculates the middle point of `self` and `rhs`.
+    ///
+    /// This returns NaN when *either* argument is NaN or if a combination of
+    /// +inf and -inf is provided as arguments.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(num_midpoint)]
+    /// assert_eq!(1f32.midpoint(4.0), 2.5);
+    /// assert_eq!((-5.5f32).midpoint(8.0), 1.25);
+    /// ```
+    #[unstable(feature = "num_midpoint", issue = "110840")]
+    pub fn midpoint(self, other: f32) -> f32 {
+        const LO: f32 = f32::MIN_POSITIVE * 2.;
+        const HI: f32 = f32::MAX / 2.;
+
+        let (a, b) = (self, other);
+        let abs_a = a.abs_private();
+        let abs_b = b.abs_private();
+
+        if abs_a <= HI && abs_b <= HI {
+            // Overflow is impossible
+            (a + b) / 2.
+        } else if abs_a < LO {
+            // Not safe to halve a
+            a + (b / 2.)
+        } else if abs_b < LO {
+            // Not safe to halve b
+            (a / 2.) + b
+        } else {
+            // Not safe to halve a and b
+            (a / 2.) + (b / 2.)
+        }
+    }
+
     /// Rounds toward zero and converts to any primitive integer type,
     /// assuming that the value is finite and fits in that type.
     ///
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 1e73872..3aafc43 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -951,6 +951,42 @@
         }
     }
 
+    /// Calculates the middle point of `self` and `rhs`.
+    ///
+    /// This returns NaN when *either* argument is NaN or if a combination of
+    /// +inf and -inf is provided as arguments.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(num_midpoint)]
+    /// assert_eq!(1f64.midpoint(4.0), 2.5);
+    /// assert_eq!((-5.5f64).midpoint(8.0), 1.25);
+    /// ```
+    #[unstable(feature = "num_midpoint", issue = "110840")]
+    pub fn midpoint(self, other: f64) -> f64 {
+        const LO: f64 = f64::MIN_POSITIVE * 2.;
+        const HI: f64 = f64::MAX / 2.;
+
+        let (a, b) = (self, other);
+        let abs_a = a.abs_private();
+        let abs_b = b.abs_private();
+
+        if abs_a <= HI && abs_b <= HI {
+            // Overflow is impossible
+            (a + b) / 2.
+        } else if abs_a < LO {
+            // Not safe to halve a
+            a + (b / 2.)
+        } else if abs_b < LO {
+            // Not safe to halve b
+            (a / 2.) + b
+        } else {
+            // Not safe to halve a and b
+            (a / 2.) + (b / 2.)
+        }
+    }
+
     /// Rounds toward zero and converts to any primitive integer type,
     /// assuming that the value is finite and fits in that type.
     ///
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 17715c9..1199d09 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2332,6 +2332,44 @@
             }
         }
 
+        /// Calculates the middle point of `self` and `rhs`.
+        ///
+        /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+        /// sufficiently-large signed integral type. This implies that the result is
+        /// always rounded towards negative infinity and that no overflow will ever occur.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_midpoint)]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-1), -1);")]
+        #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(0), -1);")]
+        /// ```
+        #[unstable(feature = "num_midpoint", issue = "110840")]
+        #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+        #[rustc_allow_const_fn_unstable(const_num_midpoint)]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn midpoint(self, rhs: Self) -> Self {
+            const U: $UnsignedT = <$SelfT>::MIN.unsigned_abs();
+
+            // Map an $SelfT to an $UnsignedT
+            // ex: i8 [-128; 127] to [0; 255]
+            const fn map(a: $SelfT) -> $UnsignedT {
+                (a as $UnsignedT) ^ U
+            }
+
+            // Map an $UnsignedT to an $SelfT
+            // ex: u8 [0; 255] to [-128; 127]
+            const fn demap(a: $UnsignedT) -> $SelfT {
+                (a ^ U) as $SelfT
+            }
+
+            demap(<$UnsignedT>::midpoint(map(self), map(rhs)))
+        }
+
         /// Returns the logarithm of the number with respect to an arbitrary base,
         /// rounded down.
         ///
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 0844442..c9baa09 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -95,6 +95,57 @@
     };
 }
 
+macro_rules! midpoint_impl {
+    ($SelfT:ty, unsigned) => {
+        /// Calculates the middle point of `self` and `rhs`.
+        ///
+        /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+        /// sufficiently-large signed integral type. This implies that the result is
+        /// always rounded towards negative infinity and that no overflow will ever occur.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_midpoint)]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
+        /// ```
+        #[unstable(feature = "num_midpoint", issue = "110840")]
+        #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
+            // Use the well known branchless algorthim from Hacker's Delight to compute
+            // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`.
+            ((self ^ rhs) >> 1) + (self & rhs)
+        }
+    };
+    ($SelfT:ty, $WideT:ty, unsigned) => {
+        /// Calculates the middle point of `self` and `rhs`.
+        ///
+        /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+        /// sufficiently-large signed integral type. This implies that the result is
+        /// always rounded towards negative infinity and that no overflow will ever occur.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_midpoint)]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
+        /// ```
+        #[unstable(feature = "num_midpoint", issue = "110840")]
+        #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
+            ((self as $WideT + rhs as $WideT) / 2) as $SelfT
+        }
+    };
+}
+
 macro_rules! widening_impl {
     ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => {
         /// Calculates the complete product `self * rhs` without the possibility to overflow.
@@ -455,6 +506,7 @@
         bound_condition = "",
     }
     widening_impl! { u8, u16, 8, unsigned }
+    midpoint_impl! { u8, u16, unsigned }
 
     /// Checks if the value is within the ASCII range.
     ///
@@ -1066,6 +1118,7 @@
         bound_condition = "",
     }
     widening_impl! { u16, u32, 16, unsigned }
+    midpoint_impl! { u16, u32, unsigned }
 
     /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
     ///
@@ -1114,6 +1167,7 @@
         bound_condition = "",
     }
     widening_impl! { u32, u64, 32, unsigned }
+    midpoint_impl! { u32, u64, unsigned }
 }
 
 impl u64 {
@@ -1137,6 +1191,7 @@
         bound_condition = "",
     }
     widening_impl! { u64, u128, 64, unsigned }
+    midpoint_impl! { u64, u128, unsigned }
 }
 
 impl u128 {
@@ -1161,6 +1216,7 @@
         from_xe_bytes_doc = "",
         bound_condition = "",
     }
+    midpoint_impl! { u128, unsigned }
 }
 
 #[cfg(target_pointer_width = "16")]
@@ -1185,6 +1241,7 @@
         bound_condition = " on 16-bit targets",
     }
     widening_impl! { usize, u32, 16, unsigned }
+    midpoint_impl! { usize, u32, unsigned }
 }
 
 #[cfg(target_pointer_width = "32")]
@@ -1209,6 +1266,7 @@
         bound_condition = " on 32-bit targets",
     }
     widening_impl! { usize, u64, 32, unsigned }
+    midpoint_impl! { usize, u64, unsigned }
 }
 
 #[cfg(target_pointer_width = "64")]
@@ -1233,6 +1291,7 @@
         bound_condition = " on 64-bit targets",
     }
     widening_impl! { usize, u128, 64, unsigned }
+    midpoint_impl! { usize, u128, unsigned }
 }
 
 impl usize {
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 74a325b..38a1c42 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -493,6 +493,43 @@
                 pub const fn ilog10(self) -> u32 {
                     super::int_log10::$Int(self.0)
                 }
+
+                /// Calculates the middle point of `self` and `rhs`.
+                ///
+                /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+                /// sufficiently-large signed integral type. This implies that the result is
+                /// always rounded towards negative infinity and that no overflow will ever occur.
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(num_midpoint)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+                ///
+                /// assert_eq!(one.midpoint(four), two);
+                /// assert_eq!(four.midpoint(one), two);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "num_midpoint", issue = "110840")]
+                #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+                #[rustc_allow_const_fn_unstable(const_num_midpoint)]
+                #[must_use = "this returns the result of the operation, \
+                              without modifying the original"]
+                #[inline]
+                pub const fn midpoint(self, rhs: Self) -> Self {
+                    // SAFETY: The only way to get `0` with midpoint is to have two opposite or
+                    // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because
+                    // of the unsignedness of this number and also because $Ty is guaranteed to
+                    // never being 0.
+                    unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) }
+                }
             }
         )+
     }
@@ -719,8 +756,6 @@
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -734,7 +769,8 @@
                 /// ```
                 #[must_use]
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn is_positive(self) -> bool {
                     self.get().is_positive()
                 }
@@ -745,8 +781,6 @@
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -760,7 +794,8 @@
                 /// ```
                 #[must_use]
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn is_negative(self) -> bool {
                     self.get().is_negative()
                 }
@@ -770,8 +805,6 @@
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -786,7 +819,8 @@
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn checked_neg(self) -> Option<$Ty> {
                     if let Some(result) = self.get().checked_neg() {
                         // SAFETY: negation of nonzero cannot yield zero values.
@@ -803,8 +837,6 @@
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -819,7 +851,8 @@
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn overflowing_neg(self) -> ($Ty, bool) {
                     let (result, overflow) = self.get().overflowing_neg();
                     // SAFETY: negation of nonzero cannot yield zero values.
@@ -832,8 +865,6 @@
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -853,7 +884,8 @@
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn saturating_neg(self) -> $Ty {
                     if let Some(result) = self.checked_neg() {
                         return result;
@@ -870,8 +902,6 @@
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -886,7 +916,8 @@
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn wrapping_neg(self) -> $Ty {
                     let result = self.get().wrapping_neg();
                     // SAFETY: negation of nonzero cannot yield zero values.
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 8338a5d..20be60d 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -28,16 +28,18 @@
         $crate::panicking::panic($msg)
     ),
     // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
-    ($msg:expr $(,)?) => (
-        $crate::panicking::panic_str($msg)
-    ),
+    ($msg:expr $(,)?) => ({
+        $crate::panicking::panic_str($msg);
+    }),
     // Special-case the single-argument case for const_panic.
-    ("{}", $arg:expr $(,)?) => (
-        $crate::panicking::panic_display(&$arg)
-    ),
-    ($fmt:expr, $($arg:tt)+) => (
-        $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
-    ),
+    ("{}", $arg:expr $(,)?) => ({
+        $crate::panicking::panic_display(&$arg);
+    }),
+    ($fmt:expr, $($arg:tt)+) => ({
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+));
+    }),
 }
 
 #[doc(hidden)]
@@ -50,12 +52,14 @@
         $crate::panicking::panic("explicit panic")
     ),
     // Special-case the single-argument case for const_panic.
-    ("{}", $arg:expr $(,)?) => (
-        $crate::panicking::panic_display(&$arg)
-    ),
-    ($($t:tt)+) => (
-        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
-    ),
+    ("{}", $arg:expr $(,)?) => ({
+        $crate::panicking::panic_display(&$arg);
+    }),
+    ($($t:tt)+) => ({
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
+    }),
 }
 
 #[doc(hidden)]
@@ -69,9 +73,9 @@
     ),
     // Use of `unreachable_display` for non_fmt_panic lint.
     // NOTE: the message ("internal error ...") is embedded directly in unreachable_display
-    ($msg:expr $(,)?) => (
-        $crate::panicking::unreachable_display(&$msg)
-    ),
+    ($msg:expr $(,)?) => ({
+        $crate::panicking::unreachable_display(&$msg);
+    }),
     ($fmt:expr, $($arg:tt)*) => (
         $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
     ),
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index 06fbe08..5576add 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -134,7 +134,7 @@
     /// whose ABI does not support unwinding.
     ///
     /// It is safe for a panic handler to unwind even when this function returns
-    /// true, however this will simply cause the panic handler to be called
+    /// false, however this will simply cause the panic handler to be called
     /// again.
     #[must_use]
     #[unstable(feature = "panic_can_unwind", issue = "92988")]
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index c4b89a6..6b319b4 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -393,6 +393,8 @@
 /// value in place, preventing the value referenced by that pointer from being moved
 /// unless it implements [`Unpin`].
 ///
+/// `Pin<P>` is guaranteed to have the same memory layout and ABI as `P`.
+///
 /// *See the [`pin` module] documentation for an explanation of pinning.*
 ///
 /// [`pin` module]: self
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index ecbf4e6..ff9fa48 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -441,10 +441,18 @@
 ///
 /// * `to_drop` must be [valid] for both reads and writes.
 ///
-/// * `to_drop` must be properly aligned.
+/// * `to_drop` must be properly aligned, even if `T` has size 0.
 ///
-/// * The value `to_drop` points to must be valid for dropping, which may mean it must uphold
-///   additional invariants - this is type-dependent.
+/// * `to_drop` must be nonnull, even if `T` has size 0.
+///
+/// * The value `to_drop` points to must be valid for dropping, which may mean
+///   it must uphold additional invariants. These invariants depend on the type
+///   of the value being dropped. For instance, when dropping a Box, the box's
+///   pointer to the heap must be valid.
+///
+/// * While `drop_in_place` is executing, the only way to access parts of
+///   `to_drop` is through the `&mut self` references supplied to the
+///   `Drop::drop` methods that `drop_in_place` invokes.
 ///
 /// Additionally, if `T` is not [`Copy`], using the pointed-to value after
 /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
@@ -452,8 +460,6 @@
 /// again. [`write()`] can be used to overwrite data without causing it to be
 /// dropped.
 ///
-/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
-///
 /// [valid]: self#safety
 ///
 /// # Examples
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c2e9ba2..bd1b16e 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -42,6 +42,7 @@
 mod iter;
 mod raw;
 mod rotate;
+mod select;
 mod specialize;
 
 #[unstable(feature = "str_internals", issue = "none")]
@@ -319,6 +320,264 @@
         if let [.., last] = self { Some(last) } else { None }
     }
 
+    /// Returns the first `N` elements of the slice, or `None` if it has fewer than `N` elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let u = [10, 40, 30];
+    /// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
+    ///
+    /// let v: &[i32] = &[10];
+    /// assert_eq!(None, v.first_chunk::<2>());
+    ///
+    /// let w: &[i32] = &[];
+    /// assert_eq!(Some(&[]), w.first_chunk::<0>());
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   and do not let the reference outlive the slice.
+            Some(unsafe { &*(self.as_ptr() as *const [T; N]) })
+        }
+    }
+
+    /// Returns a mutable reference to the first `N` elements of the slice,
+    /// or `None` if it has fewer than `N` elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(first) = x.first_chunk_mut::<2>() {
+    ///     first[0] = 5;
+    ///     first[1] = 4;
+    /// }
+    /// assert_eq!(x, &[5, 4, 2]);
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   do not let the reference outlive the slice,
+            //   and require exclusive access to the entire slice to mutate the chunk.
+            Some(unsafe { &mut *(self.as_mut_ptr() as *mut [T; N]) })
+        }
+    }
+
+    /// Returns the first `N` elements of the slice and the remainder,
+    /// or `None` if it has fewer than `N` elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first_chunk::<2>() {
+    ///     assert_eq!(first, &[0, 1]);
+    ///     assert_eq!(elements, &[2]);
+    /// }
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We manually verified the bounds of the split.
+            let (first, tail) = unsafe { self.split_at_unchecked(N) };
+
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   and do not let the references outlive the slice.
+            Some((unsafe { &*(first.as_ptr() as *const [T; N]) }, tail))
+        }
+    }
+
+    /// Returns a mutable reference to the first `N` elements of the slice and the remainder,
+    /// or `None` if it has fewer than `N` elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
+    ///     first[0] = 3;
+    ///     first[1] = 4;
+    ///     elements[0] = 5;
+    /// }
+    /// assert_eq!(x, &[3, 4, 5]);
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn split_first_chunk_mut<const N: usize>(
+        &mut self,
+    ) -> Option<(&mut [T; N], &mut [T])> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We manually verified the bounds of the split.
+            let (first, tail) = unsafe { self.split_at_mut_unchecked(N) };
+
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   do not let the reference outlive the slice,
+            //   and enforce exclusive mutability of the chunk by the split.
+            Some((unsafe { &mut *(first.as_mut_ptr() as *mut [T; N]) }, tail))
+        }
+    }
+
+    /// Returns the last `N` elements of the slice and the remainder,
+    /// or `None` if it has fewer than `N` elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last_chunk::<2>() {
+    ///     assert_eq!(last, &[1, 2]);
+    ///     assert_eq!(elements, &[0]);
+    /// }
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We manually verified the bounds of the split.
+            let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) };
+
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   and do not let the references outlive the slice.
+            Some((unsafe { &*(last.as_ptr() as *const [T; N]) }, init))
+        }
+    }
+
+    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last_chunk_mut::<2>() {
+    ///     last[0] = 3;
+    ///     last[1] = 4;
+    ///     elements[0] = 5;
+    /// }
+    /// assert_eq!(x, &[5, 3, 4]);
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn split_last_chunk_mut<const N: usize>(
+        &mut self,
+    ) -> Option<(&mut [T; N], &mut [T])> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We manually verified the bounds of the split.
+            let (init, last) = unsafe { self.split_at_mut_unchecked(self.len() - N) };
+
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   do not let the reference outlive the slice,
+            //   and enforce exclusive mutability of the chunk by the split.
+            Some((unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }, init))
+        }
+    }
+
+    /// Returns the last element of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let u = [10, 40, 30];
+    /// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
+    ///
+    /// let v: &[i32] = &[10];
+    /// assert_eq!(None, v.last_chunk::<2>());
+    ///
+    /// let w: &[i32] = &[];
+    /// assert_eq!(Some(&[]), w.last_chunk::<0>());
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We manually verified the bounds of the slice.
+            // FIXME: Without const traits, we need this instead of `get_unchecked`.
+            let last = unsafe { self.split_at_unchecked(self.len() - N).1 };
+
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   and do not let the references outlive the slice.
+            Some(unsafe { &*(last.as_ptr() as *const [T; N]) })
+        }
+    }
+
+    /// Returns a mutable pointer to the last item in the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_first_last_chunk)]
+    ///
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(last) = x.last_chunk_mut::<2>() {
+    ///     last[0] = 10;
+    ///     last[1] = 20;
+    /// }
+    /// assert_eq!(x, &[0, 10, 20]);
+    /// ```
+    #[unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
+    #[inline]
+    pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
+        if self.len() < N {
+            None
+        } else {
+            // SAFETY: We manually verified the bounds of the slice.
+            // FIXME: Without const traits, we need this instead of `get_unchecked`.
+            let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 };
+
+            // SAFETY: We explicitly check for the correct number of elements,
+            //   do not let the reference outlive the slice,
+            //   and require exclusive access to the entire slice to mutate the chunk.
+            Some(unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) })
+        }
+    }
+
     /// Returns a reference to an element or subslice depending on the type of
     /// index.
     ///
@@ -995,7 +1254,7 @@
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     #[must_use]
-    pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
+    pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
         let this = self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
@@ -1043,7 +1302,7 @@
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
+    pub const fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at(len * N);
@@ -1075,7 +1334,7 @@
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
+    pub const fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
@@ -1152,7 +1411,7 @@
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     #[must_use]
-    pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
+    pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
         let this = &*self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
@@ -1195,7 +1454,7 @@
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
+    pub const fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at_mut(len * N);
@@ -1233,7 +1492,7 @@
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
+    pub const fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
@@ -1595,7 +1854,8 @@
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_slice_split_at_not_mut", issue = "101158")]
+    #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_allow_const_fn_unstable(slice_split_at_unchecked)]
     #[inline]
     #[track_caller]
     #[must_use]
@@ -2775,7 +3035,7 @@
     where
         T: Ord,
     {
-        sort::partition_at_index(self, index, T::lt)
+        select::partition_at_index(self, index, T::lt)
     }
 
     /// Reorder the slice with a comparator function such that the element at `index` is at its
@@ -2830,7 +3090,7 @@
     where
         F: FnMut(&T, &T) -> Ordering,
     {
-        sort::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
+        select::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
     }
 
     /// Reorder the slice with a key extraction function such that the element at `index` is at its
@@ -2886,7 +3146,7 @@
         F: FnMut(&T) -> K,
         K: Ord,
     {
-        sort::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b)))
+        select::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b)))
     }
 
     /// Moves all consecutive repeated elements to the end of the slice according to the
diff --git a/library/core/src/slice/select.rs b/library/core/src/slice/select.rs
new file mode 100644
index 0000000..ffc1935
--- /dev/null
+++ b/library/core/src/slice/select.rs
@@ -0,0 +1,302 @@
+//! Slice selection
+//!
+//! This module contains the implementation for `slice::select_nth_unstable`.
+//! It uses an introselect algorithm based on Orson Peters' pattern-defeating quicksort,
+//! published at: <https://github.com/orlp/pdqsort>
+//!
+//! The fallback algorithm used for introselect is Median of Medians using Tukey's Ninther
+//! for pivot selection. Using this as a fallback ensures O(n) worst case running time with
+//! better performance than one would get using heapsort as fallback.
+
+use crate::cmp;
+use crate::mem::{self, SizedTypeProperties};
+use crate::slice::sort::{
+    break_patterns, choose_pivot, insertion_sort_shift_left, partition, partition_equal,
+};
+
+// For slices of up to this length it's probably faster to simply sort them.
+// Defined at the module scope because it's used in multiple functions.
+const MAX_INSERTION: usize = 10;
+
+fn partition_at_index_loop<'a, T, F>(
+    mut v: &'a mut [T],
+    mut index: usize,
+    is_less: &mut F,
+    mut pred: Option<&'a T>,
+) where
+    F: FnMut(&T, &T) -> bool,
+{
+    // Limit the amount of iterations and fall back to fast deterministic selection
+    // to ensure O(n) worst case running time. This limit needs to be constant, because
+    // using `ilog2(len)` like in `sort` would result in O(n log n) time complexity.
+    // The exact value of the limit is chosen somewhat arbitrarily, but for most inputs bad pivot
+    // selections should be relatively rare, so the limit usually shouldn't be reached
+    // anyways.
+    let mut limit = 16;
+
+    // True if the last partitioning was reasonably balanced.
+    let mut was_balanced = true;
+
+    loop {
+        if v.len() <= MAX_INSERTION {
+            if v.len() > 1 {
+                insertion_sort_shift_left(v, 1, is_less);
+            }
+            return;
+        }
+
+        if limit == 0 {
+            median_of_medians(v, is_less, index);
+            return;
+        }
+
+        // If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
+        // some elements around. Hopefully we'll choose a better pivot this time.
+        if !was_balanced {
+            break_patterns(v);
+            limit -= 1;
+        }
+
+        // Choose a pivot
+        let (pivot, _) = choose_pivot(v, is_less);
+
+        // If the chosen pivot is equal to the predecessor, then it's the smallest element in the
+        // slice. Partition the slice into elements equal to and elements greater than the pivot.
+        // This case is usually hit when the slice contains many duplicate elements.
+        if let Some(p) = pred {
+            if !is_less(p, &v[pivot]) {
+                let mid = partition_equal(v, pivot, is_less);
+
+                // If we've passed our index, then we're good.
+                if mid > index {
+                    return;
+                }
+
+                // Otherwise, continue sorting elements greater than the pivot.
+                v = &mut v[mid..];
+                index = index - mid;
+                pred = None;
+                continue;
+            }
+        }
+
+        let (mid, _) = partition(v, pivot, is_less);
+        was_balanced = cmp::min(mid, v.len() - mid) >= v.len() / 8;
+
+        // Split the slice into `left`, `pivot`, and `right`.
+        let (left, right) = v.split_at_mut(mid);
+        let (pivot, right) = right.split_at_mut(1);
+        let pivot = &pivot[0];
+
+        if mid < index {
+            v = right;
+            index = index - mid - 1;
+            pred = Some(pivot);
+        } else if mid > index {
+            v = left;
+        } else {
+            // If mid == index, then we're done, since partition() guaranteed that all elements
+            // after mid are greater than or equal to mid.
+            return;
+        }
+    }
+}
+
+/// Helper function that returns the index of the minimum element in the slice using the given
+/// comparator function
+fn min_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
+    slice
+        .iter()
+        .enumerate()
+        .reduce(|acc, t| if is_less(t.1, acc.1) { t } else { acc })
+        .map(|(i, _)| i)
+}
+
+/// Helper function that returns the index of the maximum element in the slice using the given
+/// comparator function
+fn max_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
+    slice
+        .iter()
+        .enumerate()
+        .reduce(|acc, t| if is_less(acc.1, t.1) { t } else { acc })
+        .map(|(i, _)| i)
+}
+
+/// Reorder the slice such that the element at `index` is at its final sorted position.
+pub fn partition_at_index<T, F>(
+    v: &mut [T],
+    index: usize,
+    mut is_less: F,
+) -> (&mut [T], &mut T, &mut [T])
+where
+    F: FnMut(&T, &T) -> bool,
+{
+    if index >= v.len() {
+        panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
+    }
+
+    if T::IS_ZST {
+        // Sorting has no meaningful behavior on zero-sized types. Do nothing.
+    } else if index == v.len() - 1 {
+        // Find max element and place it in the last position of the array. We're free to use
+        // `unwrap()` here because we know v must not be empty.
+        let max_idx = max_index(v, &mut is_less).unwrap();
+        v.swap(max_idx, index);
+    } else if index == 0 {
+        // Find min element and place it in the first position of the array. We're free to use
+        // `unwrap()` here because we know v must not be empty.
+        let min_idx = min_index(v, &mut is_less).unwrap();
+        v.swap(min_idx, index);
+    } else {
+        partition_at_index_loop(v, index, &mut is_less, None);
+    }
+
+    let (left, right) = v.split_at_mut(index);
+    let (pivot, right) = right.split_at_mut(1);
+    let pivot = &mut pivot[0];
+    (left, pivot, right)
+}
+
+/// Selection algorithm to select the k-th element from the slice in guaranteed O(n) time.
+/// This is essentially a quickselect that uses Tukey's Ninther for pivot selection
+fn median_of_medians<T, F: FnMut(&T, &T) -> bool>(mut v: &mut [T], is_less: &mut F, mut k: usize) {
+    // Since this function isn't public, it should never be called with an out-of-bounds index.
+    debug_assert!(k < v.len());
+
+    // If T is as ZST, `partition_at_index` will already return early.
+    debug_assert!(!T::IS_ZST);
+
+    // We now know that `k < v.len() <= isize::MAX`
+    loop {
+        if v.len() <= MAX_INSERTION {
+            if v.len() > 1 {
+                insertion_sort_shift_left(v, 1, is_less);
+            }
+            return;
+        }
+
+        // `median_of_{minima,maxima}` can't handle the extreme cases of the first/last element,
+        // so we catch them here and just do a linear search.
+        if k == v.len() - 1 {
+            // Find max element and place it in the last position of the array. We're free to use
+            // `unwrap()` here because we know v must not be empty.
+            let max_idx = max_index(v, is_less).unwrap();
+            v.swap(max_idx, k);
+            return;
+        } else if k == 0 {
+            // Find min element and place it in the first position of the array. We're free to use
+            // `unwrap()` here because we know v must not be empty.
+            let min_idx = min_index(v, is_less).unwrap();
+            v.swap(min_idx, k);
+            return;
+        }
+
+        let p = median_of_ninthers(v, is_less);
+
+        if p == k {
+            return;
+        } else if p > k {
+            v = &mut v[..p];
+        } else {
+            // Since `p < k < v.len()`, `p + 1` doesn't overflow and is
+            // a valid index into the slice.
+            v = &mut v[p + 1..];
+            k -= p + 1;
+        }
+    }
+}
+
+// Optimized for when `k` lies somewhere in the middle of the slice. Selects a pivot
+// as close as possible to the median of the slice. For more details on how the algorithm
+// operates, refer to the paper <https://drops.dagstuhl.de/opus/volltexte/2017/7612/pdf/LIPIcs-SEA-2017-24.pdf>.
+fn median_of_ninthers<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) -> usize {
+    // use `saturating_mul` so the multiplication doesn't overflow on 16-bit platforms.
+    let frac = if v.len() <= 1024 {
+        v.len() / 12
+    } else if v.len() <= 128_usize.saturating_mul(1024) {
+        v.len() / 64
+    } else {
+        v.len() / 1024
+    };
+
+    let pivot = frac / 2;
+    let lo = v.len() / 2 - pivot;
+    let hi = frac + lo;
+    let gap = (v.len() - 9 * frac) / 4;
+    let mut a = lo - 4 * frac - gap;
+    let mut b = hi + gap;
+    for i in lo..hi {
+        ninther(v, is_less, a, i - frac, b, a + 1, i, b + 1, a + 2, i + frac, b + 2);
+        a += 3;
+        b += 3;
+    }
+
+    median_of_medians(&mut v[lo..lo + frac], is_less, pivot);
+    partition(v, lo + pivot, is_less).0
+}
+
+/// Moves around the 9 elements at the indices a..i, such that
+/// `v[d]` contains the median of the 9 elements and the other
+/// elements are partitioned around it.
+fn ninther<T, F: FnMut(&T, &T) -> bool>(
+    v: &mut [T],
+    is_less: &mut F,
+    a: usize,
+    mut b: usize,
+    c: usize,
+    mut d: usize,
+    e: usize,
+    mut f: usize,
+    g: usize,
+    mut h: usize,
+    i: usize,
+) {
+    b = median_idx(v, is_less, a, b, c);
+    h = median_idx(v, is_less, g, h, i);
+    if is_less(&v[h], &v[b]) {
+        mem::swap(&mut b, &mut h);
+    }
+    if is_less(&v[f], &v[d]) {
+        mem::swap(&mut d, &mut f);
+    }
+    if is_less(&v[e], &v[d]) {
+        // do nothing
+    } else if is_less(&v[f], &v[e]) {
+        d = f;
+    } else {
+        if is_less(&v[e], &v[b]) {
+            v.swap(e, b);
+        } else if is_less(&v[h], &v[e]) {
+            v.swap(e, h);
+        }
+        return;
+    }
+    if is_less(&v[d], &v[b]) {
+        d = b;
+    } else if is_less(&v[h], &v[d]) {
+        d = h;
+    }
+
+    v.swap(d, e);
+}
+
+/// returns the index pointing to the median of the 3
+/// elements `v[a]`, `v[b]` and `v[c]`
+fn median_idx<T, F: FnMut(&T, &T) -> bool>(
+    v: &[T],
+    is_less: &mut F,
+    mut a: usize,
+    b: usize,
+    mut c: usize,
+) -> usize {
+    if is_less(&v[c], &v[a]) {
+        mem::swap(&mut a, &mut c);
+    }
+    if is_less(&v[c], &v[b]) {
+        return c;
+    }
+    if is_less(&v[b], &v[a]) {
+        return a;
+    }
+    b
+}
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index e6e3b55..db76d26 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -145,7 +145,7 @@
 /// Never inline this function to avoid code bloat. It still optimizes nicely and has practically no
 /// performance impact. Even improving performance in some cases.
 #[inline(never)]
-fn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
+pub(super) fn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
 where
     F: FnMut(&T, &T) -> bool,
 {
@@ -557,7 +557,7 @@
 ///
 /// 1. Number of elements smaller than `v[pivot]`.
 /// 2. True if `v` was already partitioned.
-fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
+pub(super) fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
 where
     F: FnMut(&T, &T) -> bool,
 {
@@ -612,7 +612,7 @@
 ///
 /// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain
 /// elements smaller than the pivot.
-fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
+pub(super) fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
 where
     F: FnMut(&T, &T) -> bool,
 {
@@ -670,7 +670,7 @@
 /// Scatters some elements around in an attempt to break patterns that might cause imbalanced
 /// partitions in quicksort.
 #[cold]
-fn break_patterns<T>(v: &mut [T]) {
+pub(super) fn break_patterns<T>(v: &mut [T]) {
     let len = v.len();
     if len >= 8 {
         let mut seed = len;
@@ -719,7 +719,7 @@
 /// Chooses a pivot in `v` and returns the index and `true` if the slice is likely already sorted.
 ///
 /// Elements in `v` might be reordered in the process.
-fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
+pub(super) fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
 where
     F: FnMut(&T, &T) -> bool,
 {
@@ -897,138 +897,6 @@
     recurse(v, &mut is_less, None, limit);
 }
 
-fn partition_at_index_loop<'a, T, F>(
-    mut v: &'a mut [T],
-    mut index: usize,
-    is_less: &mut F,
-    mut pred: Option<&'a T>,
-) where
-    F: FnMut(&T, &T) -> bool,
-{
-    // Limit the amount of iterations and fall back to heapsort, similarly to `slice::sort_unstable`.
-    // This lowers the worst case running time from O(n^2) to O(n log n).
-    // FIXME: Investigate whether it would be better to use something like Median of Medians
-    // or Fast Deterministic Selection to guarantee O(n) worst case.
-    let mut limit = usize::BITS - v.len().leading_zeros();
-
-    // True if the last partitioning was reasonably balanced.
-    let mut was_balanced = true;
-
-    loop {
-        let len = v.len();
-
-        // For slices of up to this length it's probably faster to simply sort them.
-        const MAX_INSERTION: usize = 10;
-        if len <= MAX_INSERTION {
-            if len >= 2 {
-                insertion_sort_shift_left(v, 1, is_less);
-            }
-            return;
-        }
-
-        if limit == 0 {
-            heapsort(v, is_less);
-            return;
-        }
-
-        // If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
-        // some elements around. Hopefully we'll choose a better pivot this time.
-        if !was_balanced {
-            break_patterns(v);
-            limit -= 1;
-        }
-
-        // Choose a pivot
-        let (pivot, _) = choose_pivot(v, is_less);
-
-        // If the chosen pivot is equal to the predecessor, then it's the smallest element in the
-        // slice. Partition the slice into elements equal to and elements greater than the pivot.
-        // This case is usually hit when the slice contains many duplicate elements.
-        if let Some(p) = pred {
-            if !is_less(p, &v[pivot]) {
-                let mid = partition_equal(v, pivot, is_less);
-
-                // If we've passed our index, then we're good.
-                if mid > index {
-                    return;
-                }
-
-                // Otherwise, continue sorting elements greater than the pivot.
-                v = &mut v[mid..];
-                index = index - mid;
-                pred = None;
-                continue;
-            }
-        }
-
-        let (mid, _) = partition(v, pivot, is_less);
-        was_balanced = cmp::min(mid, len - mid) >= len / 8;
-
-        // Split the slice into `left`, `pivot`, and `right`.
-        let (left, right) = v.split_at_mut(mid);
-        let (pivot, right) = right.split_at_mut(1);
-        let pivot = &pivot[0];
-
-        if mid < index {
-            v = right;
-            index = index - mid - 1;
-            pred = Some(pivot);
-        } else if mid > index {
-            v = left;
-        } else {
-            // If mid == index, then we're done, since partition() guaranteed that all elements
-            // after mid are greater than or equal to mid.
-            return;
-        }
-    }
-}
-
-/// Reorder the slice such that the element at `index` is at its final sorted position.
-pub fn partition_at_index<T, F>(
-    v: &mut [T],
-    index: usize,
-    mut is_less: F,
-) -> (&mut [T], &mut T, &mut [T])
-where
-    F: FnMut(&T, &T) -> bool,
-{
-    use cmp::Ordering::Greater;
-    use cmp::Ordering::Less;
-
-    if index >= v.len() {
-        panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
-    }
-
-    if T::IS_ZST {
-        // Sorting has no meaningful behavior on zero-sized types. Do nothing.
-    } else if index == v.len() - 1 {
-        // Find max element and place it in the last position of the array. We're free to use
-        // `unwrap()` here because we know v must not be empty.
-        let (max_index, _) = v
-            .iter()
-            .enumerate()
-            .max_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
-            .unwrap();
-        v.swap(max_index, index);
-    } else if index == 0 {
-        // Find min element and place it in the first position of the array. We're free to use
-        // `unwrap()` here because we know v must not be empty.
-        let (min_index, _) = v
-            .iter()
-            .enumerate()
-            .min_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
-            .unwrap();
-        v.swap(min_index, index);
-    } else {
-        partition_at_index_loop(v, index, &mut is_less, None);
-    }
-
-    let (left, right) = v.split_at_mut(index);
-    let (pivot, right) = right.split_at_mut(1);
-    let pivot = &mut pivot[0];
-    (left, pivot, right)
-}
-
 /// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `buf` as temporary storage, and
 /// stores the result into `v[..]`.
 ///
@@ -1085,12 +953,12 @@
 
             // SAFETY: left and right must be valid and part of v same for out.
             unsafe {
-                let to_copy = if is_less(&*right, &**left) {
-                    get_and_increment(&mut right)
-                } else {
-                    get_and_increment(left)
-                };
-                ptr::copy_nonoverlapping(to_copy, get_and_increment(out), 1);
+                let is_l = is_less(&*right, &**left);
+                let to_copy = if is_l { right } else { *left };
+                ptr::copy_nonoverlapping(to_copy, *out, 1);
+                *out = out.add(1);
+                right = right.add(is_l as usize);
+                *left = left.add(!is_l as usize);
             }
         }
     } else {
@@ -1113,32 +981,18 @@
 
             // SAFETY: left and right must be valid and part of v same for out.
             unsafe {
-                let to_copy = if is_less(&*right.sub(1), &*left.sub(1)) {
-                    decrement_and_get(left)
-                } else {
-                    decrement_and_get(right)
-                };
-                ptr::copy_nonoverlapping(to_copy, decrement_and_get(&mut out), 1);
+                let is_l = is_less(&*right.sub(1), &*left.sub(1));
+                *left = left.sub(is_l as usize);
+                *right = right.sub(!is_l as usize);
+                let to_copy = if is_l { *left } else { *right };
+                out = out.sub(1);
+                ptr::copy_nonoverlapping(to_copy, out, 1);
             }
         }
     }
     // Finally, `hole` gets dropped. If the shorter run was not fully consumed, whatever remains of
     // it will now be copied into the hole in `v`.
 
-    unsafe fn get_and_increment<T>(ptr: &mut *mut T) -> *mut T {
-        let old = *ptr;
-
-        // SAFETY: ptr.add(1) must still be a valid pointer and part of `v`.
-        *ptr = unsafe { ptr.add(1) };
-        old
-    }
-
-    unsafe fn decrement_and_get<T>(ptr: &mut *mut T) -> *mut T {
-        // SAFETY: ptr.sub(1) must still be a valid pointer and part of `v`.
-        *ptr = unsafe { ptr.sub(1) };
-        *ptr
-    }
-
     // When dropped, copies the range `start..end` into `dest..`.
     struct MergeHole<T> {
         start: *mut T,
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index e3a464a..91ee290 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -791,8 +791,8 @@
 /// # Examples
 ///
 /// ```
-/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
-/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['o', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['h', 'w']), Some(6));
 /// ```
 impl<'a, const N: usize> Pattern<'a> for [char; N] {
     pattern_methods!(CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher);
@@ -811,8 +811,8 @@
 /// # Examples
 ///
 /// ```
-/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
-/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['o', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['h', 'w']), Some(6));
 /// ```
 impl<'a, 'b, const N: usize> Pattern<'a> for &'b [char; N] {
     pattern_methods!(CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher);
diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs
index c5f89b9..3f0080e 100644
--- a/library/core/src/task/mod.rs
+++ b/library/core/src/task/mod.rs
@@ -13,5 +13,3 @@
 mod ready;
 #[stable(feature = "ready_macro", since = "1.64.0")]
 pub use ready::ready;
-#[unstable(feature = "poll_ready", issue = "89780")]
-pub use ready::Ready;
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 5283a57..0a0f702 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -3,7 +3,6 @@
 use crate::convert;
 use crate::ops::{self, ControlFlow};
 use crate::result::Result;
-use crate::task::Ready;
 
 /// Indicates whether a value is available or if the current task has been
 /// scheduled to receive a wakeup instead.
@@ -95,38 +94,6 @@
     pub const fn is_pending(&self) -> bool {
         !self.is_ready()
     }
-
-    /// Extracts the successful type of a [`Poll<T>`].
-    ///
-    /// When combined with the `?` operator, this function will
-    /// propagate any [`Poll::Pending`] values to the caller, and
-    /// extract the `T` from [`Poll::Ready`].
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// #![feature(poll_ready)]
-    ///
-    /// use std::task::{Context, Poll};
-    /// use std::future::{self, Future};
-    /// use std::pin::Pin;
-    ///
-    /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
-    ///     let mut fut = future::ready(42);
-    ///     let fut = Pin::new(&mut fut);
-    ///
-    ///     let num = fut.poll(cx).ready()?;
-    ///     # let _ = num; // to silence unused warning
-    ///     // ... use num
-    ///
-    ///     Poll::Ready(())
-    /// }
-    /// ```
-    #[inline]
-    #[unstable(feature = "poll_ready", issue = "89780")]
-    pub fn ready(self) -> Ready<T> {
-        Ready(self)
-    }
 }
 
 impl<T, E> Poll<Result<T, E>> {
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
index 8d12625..495d72f 100644
--- a/library/core/src/task/ready.rs
+++ b/library/core/src/task/ready.rs
@@ -1,8 +1,3 @@
-use core::convert;
-use core::fmt;
-use core::ops::{ControlFlow, FromResidual, Try};
-use core::task::Poll;
-
 /// Extracts the successful type of a [`Poll<T>`].
 ///
 /// This macro bakes in propagation of [`Pending`] signals by returning early.
@@ -60,55 +55,3 @@
         }
     }
 }
-
-/// Extracts the successful type of a [`Poll<T>`].
-///
-/// See [`Poll::ready`] for details.
-#[unstable(feature = "poll_ready", issue = "89780")]
-pub struct Ready<T>(pub(crate) Poll<T>);
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> Try for Ready<T> {
-    type Output = T;
-    type Residual = Ready<convert::Infallible>;
-
-    #[inline]
-    fn from_output(output: Self::Output) -> Self {
-        Ready(Poll::Ready(output))
-    }
-
-    #[inline]
-    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
-        match self.0 {
-            Poll::Ready(v) => ControlFlow::Continue(v),
-            Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> FromResidual for Ready<T> {
-    #[inline]
-    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
-        match residual.0 {
-            Poll::Pending => Ready(Poll::Pending),
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
-    #[inline]
-    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
-        match residual.0 {
-            Poll::Pending => Poll::Pending,
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> fmt::Debug for Ready<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("Ready").finish()
-    }
-}
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 8088253..7043ab5 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -232,7 +232,7 @@
 ///
 /// [`Future::poll()`]: core::future::Future::poll
 /// [`Poll::Pending`]: core::task::Poll::Pending
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub struct Waker {
     waker: RawWaker,
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 3c49d17..3933e32 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -53,6 +53,7 @@
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(min_specialization)]
 #![feature(numfmt)]
+#![feature(num_midpoint)]
 #![feature(step_trait)]
 #![feature(str_internals)]
 #![feature(std_internals)]
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 7f03381..aee9c89 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -386,6 +386,26 @@
     // Layout of tuples is unstable
     assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
     assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
+
+    #[repr(C)]
+    struct Generic<T> {
+        x: u8,
+        y: u32,
+        z: T
+    }
+
+    trait Trait {}
+
+    // Ensure that this type of generics works
+    fn offs_of_z<T>() -> usize {
+        offset_of!(Generic<T>, z)
+    }
+
+    assert_eq!(offset_of!(Generic<u8>, z), 8);
+    assert_eq!(offs_of_z::<u8>(), 8);
+
+    // Ensure that it works with the implicit lifetime in `Box<dyn Trait + '_>`.
+    assert_eq!(offset_of!(Generic<Box<dyn Trait>>, z), 8);
 }
 
 #[test]
diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs
index 18c55e4..439bbe6 100644
--- a/library/core/tests/num/int_macros.rs
+++ b/library/core/tests/num/int_macros.rs
@@ -364,6 +364,32 @@
                 assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true));
                 assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false));
             }
+
+            #[test]
+            fn test_midpoint() {
+                assert_eq!(<$T>::midpoint(1, 3), 2);
+                assert_eq!(<$T>::midpoint(3, 1), 2);
+
+                assert_eq!(<$T>::midpoint(0, 0), 0);
+                assert_eq!(<$T>::midpoint(0, 2), 1);
+                assert_eq!(<$T>::midpoint(2, 0), 1);
+                assert_eq!(<$T>::midpoint(2, 2), 2);
+
+                assert_eq!(<$T>::midpoint(1, 4), 2);
+                assert_eq!(<$T>::midpoint(4, 1), 2);
+                assert_eq!(<$T>::midpoint(3, 4), 3);
+                assert_eq!(<$T>::midpoint(4, 3), 3);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), -1);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), -1);
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3);
+            }
         }
     };
 }
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 3e1f848..3f3659b 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -724,7 +724,7 @@
 }
 
 macro_rules! test_float {
-    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => {
+    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => {
         mod $modname {
             #[test]
             fn min() {
@@ -845,6 +845,38 @@
                 assert!(($nan as $fty).maximum($nan).is_nan());
             }
             #[test]
+            fn midpoint() {
+                assert_eq!((0.5 as $fty).midpoint(0.5), 0.5);
+                assert_eq!((0.5 as $fty).midpoint(2.5), 1.5);
+                assert_eq!((3.0 as $fty).midpoint(4.0), 3.5);
+                assert_eq!((-3.0 as $fty).midpoint(4.0), 0.5);
+                assert_eq!((3.0 as $fty).midpoint(-4.0), -0.5);
+                assert_eq!((-3.0 as $fty).midpoint(-4.0), -3.5);
+                assert_eq!((0.0 as $fty).midpoint(0.0), 0.0);
+                assert_eq!((-0.0 as $fty).midpoint(-0.0), -0.0);
+                assert_eq!((-5.0 as $fty).midpoint(5.0), 0.0);
+                assert_eq!(($max as $fty).midpoint($min), 0.0);
+                assert_eq!(($min as $fty).midpoint($max), -0.0);
+                assert_eq!(($max as $fty).midpoint($min_pos), $max / 2.);
+                assert_eq!((-$max as $fty).midpoint($min_pos), -$max / 2.);
+                assert_eq!(($max as $fty).midpoint(-$min_pos), $max / 2.);
+                assert_eq!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
+                assert_eq!(($min_pos as $fty).midpoint($max), $max / 2.);
+                assert_eq!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
+                assert_eq!((-$min_pos as $fty).midpoint($max), $max / 2.);
+                assert_eq!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
+                assert_eq!(($max as $fty).midpoint($max), $max);
+                assert_eq!(($min_pos as $fty).midpoint($min_pos), $min_pos);
+                assert_eq!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
+                assert_eq!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
+                assert_eq!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
+                assert_eq!(($inf as $fty).midpoint($inf), $inf);
+                assert_eq!(($neginf as $fty).midpoint($neginf), $neginf);
+                assert!(($nan as $fty).midpoint(1.0).is_nan());
+                assert!((1.0 as $fty).midpoint($nan).is_nan());
+                assert!(($nan as $fty).midpoint($nan).is_nan());
+            }
+            #[test]
             fn rem_euclid() {
                 let a: $fty = 42.0;
                 assert!($inf.rem_euclid(a).is_nan());
@@ -867,5 +899,23 @@
     };
 }
 
-test_float!(f32, f32, f32::INFINITY, f32::NEG_INFINITY, f32::NAN);
-test_float!(f64, f64, f64::INFINITY, f64::NEG_INFINITY, f64::NAN);
+test_float!(
+    f32,
+    f32,
+    f32::INFINITY,
+    f32::NEG_INFINITY,
+    f32::NAN,
+    f32::MIN,
+    f32::MAX,
+    f32::MIN_POSITIVE
+);
+test_float!(
+    f64,
+    f64,
+    f64::INFINITY,
+    f64::NEG_INFINITY,
+    f64::NAN,
+    f64::MIN,
+    f64::MAX,
+    f64::MIN_POSITIVE
+);
diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs
index 15ae9f2..7d6203d 100644
--- a/library/core/tests/num/uint_macros.rs
+++ b/library/core/tests/num/uint_macros.rs
@@ -252,6 +252,32 @@
                 assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false));
                 assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
             }
+
+            #[test]
+            fn test_midpoint() {
+                assert_eq!(<$T>::midpoint(1, 3), 2);
+                assert_eq!(<$T>::midpoint(3, 1), 2);
+
+                assert_eq!(<$T>::midpoint(0, 0), 0);
+                assert_eq!(<$T>::midpoint(0, 2), 1);
+                assert_eq!(<$T>::midpoint(2, 0), 1);
+                assert_eq!(<$T>::midpoint(2, 2), 2);
+
+                assert_eq!(<$T>::midpoint(1, 4), 2);
+                assert_eq!(<$T>::midpoint(4, 1), 2);
+                assert_eq!(<$T>::midpoint(3, 4), 3);
+                assert_eq!(<$T>::midpoint(4, 3), 3);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2);
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+            }
         }
     };
 }
diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs
index e58df80..e0f3c7b 100644
--- a/library/portable-simd/crates/core_simd/src/masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks.rs
@@ -88,7 +88,7 @@
 /// The layout of this type is unspecified, and may change between platforms
 /// and/or Rust versions, and code should not assume that it is equivalent to
 /// `[T; LANES]`.
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 pub struct Mask<T, const LANES: usize>(mask_impl::Mask<T, LANES>)
 where
     T: MaskElement,
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 1454b00..824abc7 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -16,7 +16,7 @@
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.91" }
+compiler_builtins = { version = "0.1.92" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.13", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 6640c7f..89dfdfa 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -15,6 +15,7 @@
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
 use crate::path::{Path, PathBuf};
+use crate::sealed::Sealed;
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 use crate::time::SystemTime;
@@ -1391,6 +1392,16 @@
     }
 }
 
+impl AsInnerMut<fs_imp::FileTimes> for FileTimes {
+    fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes {
+        &mut self.0
+    }
+}
+
+// For implementing OS extension traits in `std::os`
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl Sealed for FileTimes {}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
@@ -1946,7 +1957,7 @@
 /// On success, the total number of bytes copied is returned and it is equal to
 /// the length of the `to` file as reported by `metadata`.
 ///
-/// If you’re wanting to copy the contents of one file to another and you’re
+/// If you want to copy the contents of one file to another and you’re
 /// working with [`File`]s, see the [`io::copy()`] function.
 ///
 /// # Platform-specific behavior
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index a8a0b9f..e2480bc 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,7 +1,7 @@
 use crate::io::prelude::*;
 
 use crate::env;
-use crate::fs::{self, File, OpenOptions};
+use crate::fs::{self, File, FileTimes, OpenOptions};
 use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
 use crate::mem::MaybeUninit;
 use crate::path::Path;
@@ -9,7 +9,7 @@
 use crate::sync::Arc;
 use crate::sys_common::io::test::{tmpdir, TempDir};
 use crate::thread;
-use crate::time::{Duration, Instant};
+use crate::time::{Duration, Instant, SystemTime};
 
 use rand::RngCore;
 
@@ -1633,3 +1633,53 @@
     assert!(new_path.join("newdir").is_dir());
     assert!(new_path.join("newdir/temp.txt").exists());
 }
+
+#[test]
+fn test_file_times() {
+    #[cfg(target_os = "ios")]
+    use crate::os::ios::fs::FileTimesExt;
+    #[cfg(target_os = "macos")]
+    use crate::os::macos::fs::FileTimesExt;
+    #[cfg(target_os = "watchos")]
+    use crate::os::watchos::fs::FileTimesExt;
+    #[cfg(windows)]
+    use crate::os::windows::fs::FileTimesExt;
+
+    let tmp = tmpdir();
+    let file = File::create(tmp.join("foo")).unwrap();
+    let mut times = FileTimes::new();
+    let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
+    let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
+    times = times.set_accessed(accessed).set_modified(modified);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    {
+        times = times.set_created(created);
+    }
+    match file.set_times(times) {
+        // Allow unsupported errors on platforms which don't support setting times.
+        #[cfg(not(any(
+            windows,
+            all(
+                unix,
+                not(any(
+                    target_os = "android",
+                    target_os = "redox",
+                    target_os = "espidf",
+                    target_os = "horizon"
+                ))
+            )
+        )))]
+        Err(e) if e.kind() == ErrorKind::Unsupported => return,
+        Err(e) => panic!("error setting file times: {e:?}"),
+        Ok(_) => {}
+    }
+    let metadata = file.metadata().unwrap();
+    assert_eq!(metadata.accessed().unwrap(), accessed);
+    assert_eq!(metadata.modified().unwrap(), modified);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    {
+        assert_eq!(metadata.created().unwrap(), created);
+    }
+}
diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs
index 38b98aff..1d9d93f 100644
--- a/library/std/src/io/copy.rs
+++ b/library/std/src/io/copy.rs
@@ -10,7 +10,7 @@
 /// On success, the total number of bytes that were copied from
 /// `reader` to `writer` is returned.
 ///
-/// If you’re wanting to copy the contents of one file to another and you’re
+/// If you want to copy the contents of one file to another and you’re
 /// working with filesystem paths, see the [`fs::copy`] function.
 ///
 /// [`fs::copy`]: crate::fs::copy
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 9e09ce3..8a007d0 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -593,7 +593,8 @@
     /// This may happen for example because fewer bytes are actually available right now
     /// (e. g. being close to end-of-file) or because read() was interrupted by a signal.
     ///
-    /// As this trait is safe to implement, callers cannot rely on `n <= buf.len()` for safety.
+    /// As this trait is safe to implement, callers in unsafe code cannot rely on
+    /// `n <= buf.len()` for safety.
     /// Extra care needs to be taken when `unsafe` functions are used to access the read bytes.
     /// Callers have to ensure that no unchecked out-of-bounds accesses are possible even if
     /// `n > buf.len()`.
@@ -603,8 +604,8 @@
     /// contents of `buf` being true. It is recommended that *implementations*
     /// only write data to `buf` instead of reading its contents.
     ///
-    /// Correspondingly, however, *callers* of this method must not assume any guarantees
-    /// about how the implementation uses `buf`. The trait is safe to implement,
+    /// Correspondingly, however, *callers* of this method in unsafe code must not assume
+    /// any guarantees about how the implementation uses `buf`. The trait is safe to implement,
     /// so it is possible that the code that's supposed to write to the buffer might also read
     /// from it. It is your responsibility to make sure that `buf` is initialized
     /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 541e95d..141a18a 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -756,6 +756,15 @@
     /// ];
     /// let listener = TcpListener::bind(&addrs[..]).unwrap();
     /// ```
+    ///
+    /// Creates a TCP listener bound to a port assigned by the operating system
+    /// at `127.0.0.1`.
+    ///
+    /// ```no_run
+    /// use std::net::TcpListener;
+    ///
+    /// let socket = TcpListener::bind("127.0.0.1:0").unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
         super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener)
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 9628bcc..5ca4ed8 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -90,6 +90,15 @@
     /// ];
     /// let socket = UdpSocket::bind(&addrs[..]).expect("couldn't bind to address");
     /// ```
+    ///
+    /// Creates a UDP socket bound to a port assigned by the operating system
+    /// at `127.0.0.1`.
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
         super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs
index 4a4637c..6d4d54b 100644
--- a/library/std/src/os/ios/fs.rs
+++ b/library/std/src/os/ios/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::ios::raw;
@@ -140,3 +142,19 @@
         self.as_inner().as_inner().st_lspare as u32
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs
index 91915da..fe82d03 100644
--- a/library/std/src/os/macos/fs.rs
+++ b/library/std/src/os/macos/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::macos::raw;
@@ -146,3 +148,19 @@
         [qspare[0] as u64, qspare[1] as u64]
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs
index a14fe35..2ecc4c6 100644
--- a/library/std/src/os/watchos/fs.rs
+++ b/library/std/src/os/watchos/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::watchos::raw;
@@ -140,3 +142,19 @@
         self.as_inner().as_inner().st_lspare as u32
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs
index a091f06..94509e5 100644
--- a/library/std/src/os/windows/fs.rs
+++ b/library/std/src/os/windows/fs.rs
@@ -9,7 +9,8 @@
 use crate::path::Path;
 use crate::sealed::Sealed;
 use crate::sys;
-use crate::sys_common::{AsInner, AsInnerMut};
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 /// Windows-specific extensions to [`fs::File`].
 #[stable(feature = "file_offset", since = "1.15.0")]
@@ -526,6 +527,22 @@
     }
 }
 
+/// Windows-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
+
 /// Creates a new symlink to a non-directory file on the filesystem.
 ///
 /// The `link` path will be a file symbolic link pointing to the `original`
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 280757a..cbf8209 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -437,6 +437,42 @@
     }
 }
 
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+/// This impl allows implementing traits that require `AsHandle` on Arc.
+/// ```
+/// # #[cfg(windows)] mod group_cfg {
+/// # use std::os::windows::io::AsHandle;
+/// use std::fs::File;
+/// use std::sync::Arc;
+///
+/// trait MyTrait: AsHandle {}
+/// impl MyTrait for Arc<File> {}
+/// impl MyTrait for Box<File> {}
+/// # }
+/// ```
+impl<T: AsHandle> AsHandle for crate::sync::Arc<T> {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        (**self).as_handle()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsHandle> AsHandle for crate::rc::Rc<T> {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        (**self).as_handle()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsHandle> AsHandle for Box<T> {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        (**self).as_handle()
+    }
+}
+
 #[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for BorrowedHandle<'_> {
     #[inline]
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index eb6097a..0c90d55 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -254,6 +254,42 @@
     }
 }
 
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+/// This impl allows implementing traits that require `AsSocket` on Arc.
+/// ```
+/// # #[cfg(windows)] mod group_cfg {
+/// # use std::os::windows::io::AsSocket;
+/// use std::net::UdpSocket;
+/// use std::sync::Arc;
+///
+/// trait MyTrait: AsSocket {}
+/// impl MyTrait for Arc<UdpSocket> {}
+/// impl MyTrait for Box<UdpSocket> {}
+/// # }
+/// ```
+impl<T: AsSocket> AsSocket for crate::sync::Arc<T> {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        (**self).as_socket()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsSocket> AsSocket for crate::rc::Rc<T> {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        (**self).as_socket()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsSocket> AsSocket for Box<T> {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        (**self).as_socket()
+    }
+}
+
 #[stable(feature = "io_safety", since = "1.63.0")]
 impl AsSocket for BorrowedSocket<'_> {
     #[inline]
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 345d72e..69a6f3e 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -19,14 +19,16 @@
         $crate::rt::begin_panic("explicit panic")
     }),
     ($msg:expr $(,)?) => ({
-        $crate::rt::begin_panic($msg)
+        $crate::rt::begin_panic($msg);
     }),
     // Special-case the single-argument case for const_panic.
     ("{}", $arg:expr $(,)?) => ({
-        $crate::rt::panic_display(&$arg)
+        $crate::rt::panic_display(&$arg);
     }),
     ($fmt:expr, $($arg:tt)+) => ({
-        $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+));
     }),
 }
 
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 43203c5..febdeb5 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -733,8 +733,9 @@
         }
     }
 
-    // parse a given byte sequence into the corresponding path component
-    fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
+    // parse a given byte sequence following the OsStr encoding into the
+    // corresponding path component
+    unsafe fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
         match comp {
             b"." if self.prefix_verbatim() => Some(Component::CurDir),
             b"." => None, // . components are normalized away, except at
@@ -754,7 +755,8 @@
             None => (0, self.path),
             Some(i) => (1, &self.path[..i]),
         };
-        (comp.len() + extra, self.parse_single_component(comp))
+        // SAFETY: `comp` is a valid substring, since it is split on a separator.
+        (comp.len() + extra, unsafe { self.parse_single_component(comp) })
     }
 
     // parse a component from the right, saying how many bytes to consume to
@@ -766,7 +768,8 @@
             None => (0, &self.path[start..]),
             Some(i) => (1, &self.path[start + i + 1..]),
         };
-        (comp.len() + extra, self.parse_single_component(comp))
+        // SAFETY: `comp` is a valid substring, since it is split on a separator.
+        (comp.len() + extra, unsafe { self.parse_single_component(comp) })
     }
 
     // trim away repeated separators (i.e., empty components) on the left
diff --git a/library/std/src/sync/mpmc/error.rs b/library/std/src/sync/mpmc/error.rs
index 1b8a1f3..33b2bff 100644
--- a/library/std/src/sync/mpmc/error.rs
+++ b/library/std/src/sync/mpmc/error.rs
@@ -35,7 +35,7 @@
     }
 }
 
-impl<T: Send> error::Error for SendTimeoutError<T> {}
+impl<T> error::Error for SendTimeoutError<T> {}
 
 impl<T> From<SendError<T>> for SendTimeoutError<T> {
     fn from(err: SendError<T>) -> SendTimeoutError<T> {
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index 6e3c28f..0e0c87d 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -1124,7 +1124,7 @@
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> error::Error for SendError<T> {
+impl<T> error::Error for SendError<T> {
     #[allow(deprecated)]
     fn description(&self) -> &str {
         "sending on a closed channel"
@@ -1152,7 +1152,7 @@
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> error::Error for TrySendError<T> {
+impl<T> error::Error for TrySendError<T> {
     #[allow(deprecated)]
     fn description(&self) -> &str {
         match *self {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 09db5b1..09e9ae2 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -349,6 +349,8 @@
 pub struct FileTimes {
     accessed: Option<SystemTime>,
     modified: Option<SystemTime>,
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    created: Option<SystemTime>,
 }
 
 #[derive(Copy, Clone, Eq, Debug)]
@@ -591,6 +593,11 @@
     pub fn set_modified(&mut self, t: SystemTime) {
         self.modified = Some(t);
     }
+
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    pub fn set_created(&mut self, t: SystemTime) {
+        self.created = Some(t);
+    }
 }
 
 impl FileType {
@@ -1215,26 +1222,41 @@
                     io::ErrorKind::Unsupported,
                     "setting file times not supported",
                 ))
-            } else if #[cfg(any(target_os = "android", target_os = "macos"))] {
+            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
+                let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
+                let mut num_times = 0;
+                let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
+                attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT;
+                if times.created.is_some() {
+                    buf[num_times].write(to_timespec(times.created)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_CRTIME;
+                }
+                if times.modified.is_some() {
+                    buf[num_times].write(to_timespec(times.modified)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_MODTIME;
+                }
+                if times.accessed.is_some() {
+                    buf[num_times].write(to_timespec(times.accessed)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_ACCTIME;
+                }
+                cvt(unsafe { libc::fsetattrlist(
+                    self.as_raw_fd(),
+                    (&attrlist as *const libc::attrlist).cast::<libc::c_void>().cast_mut(),
+                    buf.as_ptr().cast::<libc::c_void>().cast_mut(),
+                    num_times * mem::size_of::<libc::timespec>(),
+                    0
+                ) })?;
+                Ok(())
+            } else if #[cfg(target_os = "android")] {
                 let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
-                // futimens requires macOS 10.13, and Android API level 19
+                // futimens requires Android API level 19
                 cvt(unsafe {
                     weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
                     match futimens.get() {
                         Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
-                        #[cfg(target_os = "macos")]
-                        None => {
-                            fn ts_to_tv(ts: &libc::timespec) -> libc::timeval {
-                                libc::timeval {
-                                    tv_sec: ts.tv_sec,
-                                    tv_usec: (ts.tv_nsec / 1000) as _
-                                }
-                            }
-                            let timevals = [ts_to_tv(&times[0]), ts_to_tv(&times[1])];
-                            libc::futimes(self.as_raw_fd(), timevals.as_ptr())
-                        }
-                        // futimes requires even newer Android.
-                        #[cfg(target_os = "android")]
                         None => return Err(io::const_io_error!(
                             io::ErrorKind::Unsupported,
                             "setting file times requires Android API level >= 19",
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index ce42776..21a65bc 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -88,8 +88,10 @@
 pub struct FileTimes {
     accessed: Option<c::FILETIME>,
     modified: Option<c::FILETIME>,
+    created: Option<c::FILETIME>,
 }
-impl core::fmt::Debug for c::FILETIME {
+
+impl fmt::Debug for c::FILETIME {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let time = ((self.dwHighDateTime as u64) << 32) | self.dwLowDateTime as u64;
         f.debug_tuple("FILETIME").field(&time).finish()
@@ -582,7 +584,10 @@
 
     pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
         let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0;
-        if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) {
+        if times.accessed.map_or(false, is_zero)
+            || times.modified.map_or(false, is_zero)
+            || times.created.map_or(false, is_zero)
+        {
             return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
                 "Cannot set file timestamp to 0",
@@ -590,18 +595,23 @@
         }
         let is_max =
             |t: c::FILETIME| t.dwLowDateTime == c::DWORD::MAX && t.dwHighDateTime == c::DWORD::MAX;
-        if times.accessed.map_or(false, is_max) || times.modified.map_or(false, is_max) {
+        if times.accessed.map_or(false, is_max)
+            || times.modified.map_or(false, is_max)
+            || times.created.map_or(false, is_max)
+        {
             return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
                 "Cannot set file timestamp to 0xFFFF_FFFF_FFFF_FFFF",
             ));
         }
         cvt(unsafe {
+            let created =
+                times.created.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
             let accessed =
                 times.accessed.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
             let modified =
                 times.modified.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
-            c::SetFileTime(self.as_raw_handle(), ptr::null_mut(), accessed, modified)
+            c::SetFileTime(self.as_raw_handle(), created, accessed, modified)
         })?;
         Ok(())
     }
@@ -1005,6 +1015,10 @@
     pub fn set_modified(&mut self, t: SystemTime) {
         self.modified = Some(t.into_inner());
     }
+
+    pub fn set_created(&mut self, t: SystemTime) {
+        self.created = Some(t.into_inner());
+    }
 }
 
 impl FileType {
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index 8752f46..6f02094 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -68,13 +68,17 @@
         }
 
         let mut hit = false;
-        let mut stop = false;
         backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
             hit = true;
+
+            // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
+            // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
+            // called before the panic hook, so we won't ignore any frames if there is no
+            // invoke of `__rust_begin_short_backtrace`.
             if print_fmt == PrintFmt::Short {
                 if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
                     if start && sym.contains("__rust_begin_short_backtrace") {
-                        stop = true;
+                        start = false;
                         return;
                     }
                     if sym.contains("__rust_end_short_backtrace") {
@@ -88,9 +92,6 @@
                 res = bt_fmt.frame().symbol(frame, symbol);
             }
         });
-        if stop {
-            return false;
-        }
         #[cfg(target_os = "nto")]
         if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
             if !hit && start {
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 3b7c318..1b86d89 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -18,8 +18,8 @@
 /// target platform. It is instantiated with the [`thread_local!`] macro and the
 /// primary method is the [`with`] method.
 ///
-/// The [`with`] method yields a reference to the contained value which cannot be
-/// sent across threads or escape the given closure.
+/// The [`with`] method yields a reference to the contained value which cannot
+/// outlive the current thread or escape the given closure.
 ///
 /// [`thread_local!`]: crate::thread_local
 ///
diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs
index 9d22ebb..6ac3b3e 100644
--- a/library/test/src/cli.rs
+++ b/library/test/src/cli.rs
@@ -404,13 +404,13 @@
         Some("terse") => OutputFormat::Terse,
         Some("json") => {
             if !allow_unstable {
-                return Err("The \"json\" format is only accepted on the nightly compiler".into());
+                return Err("The \"json\" format is only accepted on the nightly compiler with -Z unstable-options".into());
             }
             OutputFormat::Json
         }
         Some("junit") => {
             if !allow_unstable {
-                return Err("The \"junit\" format is only accepted on the nightly compiler".into());
+                return Err("The \"junit\" format is only accepted on the nightly compiler with -Z unstable-options".into());
             }
             OutputFormat::Junit
         }
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index dfe6bb7..8f8778e 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -45,6 +45,7 @@
  "build_helper",
  "cc",
  "clap",
+ "clap_complete",
  "cmake",
  "fd-lock",
  "filetime",
@@ -57,6 +58,7 @@
  "once_cell",
  "opener",
  "pretty_assertions",
+ "semver",
  "serde",
  "serde_derive",
  "serde_json",
@@ -120,6 +122,15 @@
 ]
 
 [[package]]
+name = "clap_complete"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36774babb166352bb4f7b9cb16f781ffa3439d2a8f12cd31bea85a38c888fea3"
+dependencies = [
+ "clap",
+]
+
+[[package]]
 name = "clap_derive"
 version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -128,7 +139,7 @@
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -477,9 +488,9 @@
 
 [[package]]
 name = "object"
-version = "0.29.0"
+version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
 dependencies = [
  "memchr",
 ]
@@ -636,20 +647,26 @@
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
-name = "serde"
-version = "1.0.137"
+name = "semver"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+
+[[package]]
+name = "serde"
+version = "1.0.160"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.137"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -687,9 +704,9 @@
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index fd5eb74..367c619 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -37,7 +37,7 @@
 cc = "1.0.69"
 libc = "0.2"
 hex = "0.4"
-object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
+object = { version = "0.31.1", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
 serde = "1.0.137"
 # Directly use serde_derive rather than through the derive feature of serde to allow building both
 # in parallel and to allow serde_json and toml to start building as soon as serde has been built.
@@ -56,6 +56,8 @@
 # Dependencies needed by the build-metrics feature
 sysinfo = { version = "0.26.0", optional = true }
 clap = { version = "4.2.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
+clap_complete = "4.2.2"
+semver = "1.0.17"
 
 # Solaris doesn't support flock() and thus fd-lock is not option now
 [target.'cfg(not(target_os = "solaris"))'.dependencies]
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 0575609..58d1926 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -109,7 +109,7 @@
                 "-L", # Follow redirect.
                 "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
                 "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
-                "--retry", "3", "-Sf", url],
+                "--retry", "3", "-SRf", url],
                 stdout=outfile,    #Implements cli redirect operator '>'
                 verbose=verbose,
                 exception=True, # Will raise RuntimeError on failure
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 237f65b..cf7c659 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -839,6 +839,7 @@
                 run::CollectLicenseMetadata,
                 run::GenerateCopyright,
                 run::GenerateWindowsSys,
+                run::GenerateCompletions,
             ),
             Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
             Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
@@ -941,7 +942,6 @@
         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
     }
 
-    /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
     pub fn doc_rust_lang_org_channel(&self) -> String {
         let channel = match &*self.config.channel {
             "stable" => &self.version,
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index c32fe59..edca8fe 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -146,6 +146,22 @@
     );
 }
 
+#[test]
+fn test_beta_rev_parsing() {
+    use crate::extract_beta_rev;
+
+    // single digit revision
+    assert_eq!(extract_beta_rev("1.99.9-beta.7 (xxxxxx)"), Some("7".to_string()));
+    // multiple digits
+    assert_eq!(extract_beta_rev("1.99.9-beta.777 (xxxxxx)"), Some("777".to_string()));
+    // nightly channel (no beta revision)
+    assert_eq!(extract_beta_rev("1.99.9-nightly (xxxxxx)"), None);
+    // stable channel (no beta revision)
+    assert_eq!(extract_beta_rev("1.99.9 (xxxxxxx)"), None);
+    // invalid string
+    assert_eq!(extract_beta_rev("invalid"), None);
+}
+
 mod defaults {
     use super::{configure, first, run_build};
     use crate::builder::*;
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index bf3bc32..e192cda 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -24,6 +24,7 @@
 use crate::flags::{Color, Flags, Warnings};
 use crate::util::{exe, output, t};
 use once_cell::sync::OnceCell;
+use semver::Version;
 use serde::{Deserialize, Deserializer};
 use serde_derive::Deserialize;
 
@@ -349,7 +350,7 @@
 }
 
 /// LTO mode used for compiling rustc itself.
-#[derive(Default, Clone, PartialEq)]
+#[derive(Default, Clone, PartialEq, Debug)]
 pub enum RustcLto {
     Off,
     #[default]
@@ -507,29 +508,42 @@
     profile: Option<String>,
 }
 
+/// Describes how to handle conflicts in merging two [`TomlConfig`]
+#[derive(Copy, Clone, Debug)]
+enum ReplaceOpt {
+    /// Silently ignore a duplicated value
+    IgnoreDuplicate,
+    /// Override the current value, even if it's `Some`
+    Override,
+    /// Exit with an error on duplicate values
+    ErrorOnDuplicate,
+}
+
 trait Merge {
-    fn merge(&mut self, other: Self);
+    fn merge(&mut self, other: Self, replace: ReplaceOpt);
 }
 
 impl Merge for TomlConfig {
     fn merge(
         &mut self,
-        TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen: _ }: Self,
+        TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen }: Self,
+        replace: ReplaceOpt,
     ) {
-        fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>) {
+        fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
             if let Some(new) = y {
                 if let Some(original) = x {
-                    original.merge(new);
+                    original.merge(new, replace);
                 } else {
                     *x = Some(new);
                 }
             }
         }
-        do_merge(&mut self.build, build);
-        do_merge(&mut self.install, install);
-        do_merge(&mut self.llvm, llvm);
-        do_merge(&mut self.rust, rust);
-        do_merge(&mut self.dist, dist);
+        self.changelog_seen.merge(changelog_seen, replace);
+        do_merge(&mut self.build, build, replace);
+        do_merge(&mut self.install, install, replace);
+        do_merge(&mut self.llvm, llvm, replace);
+        do_merge(&mut self.rust, rust, replace);
+        do_merge(&mut self.dist, dist, replace);
         assert!(target.is_none(), "merging target-specific config is not currently supported");
     }
 }
@@ -546,10 +560,33 @@
         }
 
         impl Merge for $name {
-            fn merge(&mut self, other: Self) {
+            fn merge(&mut self, other: Self, replace: ReplaceOpt) {
                 $(
-                    if !self.$field.is_some() {
-                        self.$field = other.$field;
+                    match replace {
+                        ReplaceOpt::IgnoreDuplicate => {
+                            if self.$field.is_none() {
+                                self.$field = other.$field;
+                            }
+                        },
+                        ReplaceOpt::Override => {
+                            if other.$field.is_some() {
+                                self.$field = other.$field;
+                            }
+                        }
+                        ReplaceOpt::ErrorOnDuplicate => {
+                            if other.$field.is_some() {
+                                if self.$field.is_some() {
+                                    if cfg!(test) {
+                                        panic!("overriding existing option")
+                                    } else {
+                                        eprintln!("overriding existing option: `{}`", stringify!($field));
+                                        crate::detail_exit(2);
+                                    }
+                                } else {
+                                    self.$field = other.$field;
+                                }
+                            }
+                        }
                     }
                 )*
             }
@@ -622,6 +659,37 @@
     }
 }
 
+impl<T> Merge for Option<T> {
+    fn merge(&mut self, other: Self, replace: ReplaceOpt) {
+        match replace {
+            ReplaceOpt::IgnoreDuplicate => {
+                if self.is_none() {
+                    *self = other;
+                }
+            }
+            ReplaceOpt::Override => {
+                if other.is_some() {
+                    *self = other;
+                }
+            }
+            ReplaceOpt::ErrorOnDuplicate => {
+                if other.is_some() {
+                    if self.is_some() {
+                        if cfg!(test) {
+                            panic!("overriding existing option")
+                        } else {
+                            eprintln!("overriding existing option");
+                            crate::detail_exit(2);
+                        }
+                    } else {
+                        *self = other;
+                    }
+                }
+            }
+        }
+    }
+}
+
 define_config! {
     /// TOML representation of various global build decisions.
     #[derive(Default)]
@@ -863,28 +931,27 @@
 
     pub fn parse(args: &[String]) -> Config {
         #[cfg(test)]
-        let get_toml = |_: &_| TomlConfig::default();
+        fn get_toml(_: &Path) -> TomlConfig {
+            TomlConfig::default()
+        }
+
         #[cfg(not(test))]
-        let get_toml = |file: &Path| {
+        fn get_toml(file: &Path) -> TomlConfig {
             let contents =
                 t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
             // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
             // TomlConfig and sub types to be monomorphized 5x by toml.
-            match toml::from_str(&contents)
+            toml::from_str(&contents)
                 .and_then(|table: toml::Value| TomlConfig::deserialize(table))
-            {
-                Ok(table) => table,
-                Err(err) => {
-                    eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
+                .unwrap_or_else(|err| {
+                    eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
                     crate::detail_exit(2);
-                }
-            }
-        };
-
+                })
+        }
         Self::parse_inner(args, get_toml)
     }
 
-    fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig) -> Config {
+    fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
         let mut flags = Flags::parse(&args);
         let mut config = Config::default_opts();
 
@@ -997,9 +1064,41 @@
             include_path.push("defaults");
             include_path.push(format!("config.{}.toml", include));
             let included_toml = get_toml(&include_path);
-            toml.merge(included_toml);
+            toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
         }
 
+        let mut override_toml = TomlConfig::default();
+        for option in flags.set.iter() {
+            fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
+                toml::from_str(&option)
+                    .and_then(|table: toml::Value| TomlConfig::deserialize(table))
+            }
+
+            let mut err = match get_table(option) {
+                Ok(v) => {
+                    override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+                    continue;
+                }
+                Err(e) => e,
+            };
+            // We want to be able to set string values without quotes,
+            // like in `configure.py`. Try adding quotes around the right hand side
+            if let Some((key, value)) = option.split_once("=") {
+                if !value.contains('"') {
+                    match get_table(&format!(r#"{key}="{value}""#)) {
+                        Ok(v) => {
+                            override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+                            continue;
+                        }
+                        Err(e) => err = e,
+                    }
+                }
+            }
+            eprintln!("failed to parse override `{option}`: `{err}");
+            crate::detail_exit(2)
+        }
+        toml.merge(override_toml, ReplaceOpt::Override);
+
         config.changelog_seen = toml.changelog_seen;
 
         let build = toml.build.unwrap_or_default();
@@ -1019,6 +1118,7 @@
             config.download_beta_toolchain();
             config.out.join(config.build.triple).join("stage0/bin/rustc")
         });
+
         config.initial_cargo = build
             .cargo
             .map(|cargo| {
@@ -1680,6 +1780,42 @@
         self.rust_codegen_backends.get(0).cloned()
     }
 
+    pub fn check_build_rustc_version(&self) {
+        if self.dry_run() {
+            return;
+        }
+
+        // check rustc version is same or lower with 1 apart from the building one
+        let mut cmd = Command::new(&self.initial_rustc);
+        cmd.arg("--version");
+        let rustc_output = output(&mut cmd)
+            .lines()
+            .next()
+            .unwrap()
+            .split(' ')
+            .nth(1)
+            .unwrap()
+            .split('-')
+            .next()
+            .unwrap()
+            .to_owned();
+        let rustc_version = Version::parse(&rustc_output.trim()).unwrap();
+        let source_version =
+            Version::parse(&fs::read_to_string(self.src.join("src/version")).unwrap().trim())
+                .unwrap();
+        if !(source_version == rustc_version
+            || (source_version.major == rustc_version.major
+                && source_version.minor == rustc_version.minor + 1))
+        {
+            let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
+            eprintln!(
+                "Unexpected rustc version: {}, we should use {}/{} to build source with {}",
+                rustc_version, prev_version, source_version, source_version
+            );
+            crate::detail_exit(1);
+        }
+    }
+
     /// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
     fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> {
         // If `download-rustc` is not set, default to rebuilding.
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index d913ca2..4de84b5 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -1,13 +1,11 @@
-use super::{Config, Flags, TomlConfig};
+use super::{Config, Flags};
 use clap::CommandFactory;
 use std::{env, path::Path};
 
-fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
-    |&_| toml::from_str(config).unwrap()
-}
-
 fn parse(config: &str) -> Config {
-    Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], toml(config))
+    Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| {
+        toml::from_str(config).unwrap()
+    })
 }
 
 #[test]
@@ -94,3 +92,70 @@
 fn clap_verify() {
     Flags::command().debug_assert();
 }
+
+#[test]
+fn override_toml() {
+    let config = Config::parse_inner(
+        &[
+            "check".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--set=changelog-seen=1".to_owned(),
+            "--set=rust.lto=fat".to_owned(),
+            "--set=rust.deny-warnings=false".to_owned(),
+            "--set=build.gdb=\"bar\"".to_owned(),
+            "--set=build.tools=[\"cargo\"]".to_owned(),
+            "--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(),
+        ],
+        |&_| {
+            toml::from_str(
+                r#"
+changelog-seen = 0
+[rust]
+lto = "off"
+deny-warnings = true
+
+[build]
+gdb = "foo"
+tools = []
+
+[llvm]
+download-ci-llvm = false
+build-config = {}
+                "#,
+            )
+            .unwrap()
+        },
+    );
+    assert_eq!(config.changelog_seen, Some(1), "setting top-level value");
+    assert_eq!(
+        config.rust_lto,
+        crate::config::RustcLto::Fat,
+        "setting string value without quotes"
+    );
+    assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
+    assert_eq!(config.deny_warnings, false, "setting boolean value");
+    assert_eq!(
+        config.tools,
+        Some(["cargo".to_string()].into_iter().collect()),
+        "setting list value"
+    );
+    assert_eq!(
+        config.llvm_build_config,
+        [("foo".to_string(), "bar".to_string())].into_iter().collect(),
+        "setting dictionary value"
+    );
+}
+
+#[test]
+#[should_panic]
+fn override_toml_duplicate() {
+    Config::parse_inner(
+        &[
+            "check".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--set=changelog-seen=1".to_owned(),
+            "--set=changelog-seen=2".to_owned(),
+        ],
+        |&_| toml::from_str("changelog-seen = 0").unwrap(),
+    );
+}
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 9cead7a..b498453 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1071,7 +1071,11 @@
 
         tarball.add_file(&cargo, "bin", 0o755);
         tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
-        tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
+        tarball.add_renamed_file(
+            etc.join("cargo.bashcomp.sh"),
+            "src/etc/bash_completion.d",
+            "cargo",
+        );
         tarball.add_dir(etc.join("man"), "share/man/man1");
         tarball.add_legal_and_readme_to("share/doc/cargo");
 
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 3e82a38..25df5b2 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -219,7 +219,7 @@
             "30", // timeout if cannot connect within 30 seconds
             "--retry",
             "3",
-            "-Sf",
+            "-SRf",
         ]);
         curl.arg(url);
         let f = File::create(tempfile).unwrap();
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index c79a1bf..80e7157 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -3,9 +3,9 @@
 //! This module implements the command-line parsing of the build system which
 //! has various flags to configure how it's run.
 
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
-use clap::{Parser, ValueEnum};
+use clap::{CommandFactory, Parser, ValueEnum};
 
 use crate::builder::{Builder, Kind};
 use crate::config::{target_selection_list, Config, TargetSelectionList};
@@ -54,15 +54,15 @@
     /// Build directory, overrides `build.build-dir` in `config.toml`
     pub build_dir: Option<PathBuf>,
 
-    #[arg(global(true), long, value_name = "BUILD")]
+    #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "BUILD")]
     /// build target of the stage0 compiler
     pub build: Option<String>,
 
-    #[arg(global(true), long, value_name = "HOST", value_parser = target_selection_list)]
+    #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "HOST", value_parser = target_selection_list)]
     /// host targets to build
     pub host: Option<TargetSelectionList>,
 
-    #[arg(global(true), long, value_name = "TARGET", value_parser = target_selection_list)]
+    #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "TARGET", value_parser = target_selection_list)]
     /// target targets to build
     pub target: Option<TargetSelectionList>,
 
@@ -73,7 +73,7 @@
     /// include default paths in addition to the provided ones
     pub include_default_paths: bool,
 
-    #[arg(global(true), long)]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long)]
     pub rustc_error_format: Option<String>,
 
     #[arg(global(true), long, value_hint = clap::ValueHint::CommandString, value_name = "CMD")]
@@ -82,16 +82,16 @@
     #[arg(global(true), long)]
     /// dry run; don't build anything
     pub dry_run: bool,
-    #[arg(global(true), long, value_name = "N")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
     /// stage to build (indicates compiler to use/test, e.g., stage 0 uses the
     /// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)
     pub stage: Option<u32>,
 
-    #[arg(global(true), long, value_name = "N")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
     /// stage(s) to keep without recompiling
     /// (pass multiple times to keep e.g., both stages 0 and 1)
     pub keep_stage: Vec<u32>,
-    #[arg(global(true), long, value_name = "N")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
     /// stage(s) of the standard library to keep without recompiling
     /// (pass multiple times to keep e.g., both stages 0 and 1)
     pub keep_stage_std: Vec<u32>,
@@ -103,6 +103,7 @@
         global(true),
         short,
         long,
+        value_hint = clap::ValueHint::Other,
         default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get),
         value_name = "JOBS"
     )]
@@ -117,7 +118,7 @@
     /// otherwise, use the default configured behaviour
     pub warnings: Warnings,
 
-    #[arg(global(true), long, value_name = "FORMAT")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "FORMAT")]
     /// rustc error format
     pub error_format: Option<String>,
     #[arg(global(true), long)]
@@ -133,13 +134,13 @@
     #[arg(global(true), long, value_name = "VALUE")]
     pub llvm_skip_rebuild: Option<bool>,
     /// generate PGO profile with rustc build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub rust_profile_generate: Option<String>,
     /// use PGO profile for rustc build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub rust_profile_use: Option<String>,
     /// use PGO profile for LLVM build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub llvm_profile_use: Option<String>,
     // LLVM doesn't support a custom location for generating profile
     // information.
@@ -152,11 +153,14 @@
     #[arg(global(true), long)]
     pub llvm_bolt_profile_generate: bool,
     /// use BOLT profile for LLVM build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub llvm_bolt_profile_use: Option<String>,
     #[arg(global(true))]
     /// paths for the subcommand
     pub paths: Vec<PathBuf>,
+    /// override options in config.toml
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "section.option=value")]
+    pub set: Vec<String>,
     /// arguments passed to subcommands
     #[arg(global(true), last(true), value_name = "ARGS")]
     pub free_args: Vec<String>,
@@ -364,7 +368,7 @@
         #[arg(long)]
         all: bool,
     },
-    /// Duild distribution artifacts
+    /// Build distribution artifacts
     Dist,
     /// Install distribution artifacts
     Install,
@@ -524,3 +528,23 @@
         }
     }
 }
+
+/// Returns the shell completion for a given shell, if the result differs from the current
+/// content of `path`. If `path` does not exist, always returns `Some`.
+pub fn get_completion<G: clap_complete::Generator>(shell: G, path: &Path) -> Option<String> {
+    let mut cmd = Flags::command();
+    let current = if !path.exists() {
+        String::new()
+    } else {
+        std::fs::read_to_string(path).unwrap_or_else(|_| {
+            eprintln!("couldn't read {}", path.display());
+            crate::detail_exit(1)
+        })
+    };
+    let mut buf = Vec::new();
+    clap_complete::generate(shell, &mut cmd, "x.py", &mut buf);
+    if buf == current.as_bytes() {
+        return None;
+    }
+    Some(String::from_utf8(buf).expect("completion script should be UTF-8"))
+}
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 9943369..6ee50ee 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -414,6 +414,7 @@
                 bootstrap_out.display()
             )
         }
+        config.check_build_rustc_version();
 
         if rust_info.is_from_tarball() && config.description.is_none() {
             config.description = Some("built from a source tarball".to_owned());
@@ -1323,7 +1324,7 @@
         match &self.config.channel[..] {
             "stable" => num.to_string(),
             "beta" => {
-                if self.rust_info().is_managed_git_subrepository() && !self.config.omit_git_hash {
+                if !self.config.omit_git_hash {
                     format!("{}-beta.{}", num, self.beta_prerelease_version())
                 } else {
                     format!("{}-beta", num)
@@ -1335,18 +1336,28 @@
     }
 
     fn beta_prerelease_version(&self) -> u32 {
+        fn extract_beta_rev_from_file<P: AsRef<Path>>(version_file: P) -> Option<String> {
+            let version = fs::read_to_string(version_file).ok()?;
+
+            extract_beta_rev(&version)
+        }
+
         if let Some(s) = self.prerelease_version.get() {
             return s;
         }
 
-        // Figure out how many merge commits happened since we branched off master.
-        // That's our beta number!
-        // (Note that we use a `..` range, not the `...` symmetric difference.)
-        let count =
+        // First check if there is a version file available.
+        // If available, we read the beta revision from that file.
+        // This only happens when building from a source tarball when Git should not be used.
+        let count = extract_beta_rev_from_file(self.src.join("version")).unwrap_or_else(|| {
+            // Figure out how many merge commits happened since we branched off master.
+            // That's our beta number!
+            // (Note that we use a `..` range, not the `...` symmetric difference.)
             output(self.config.git().arg("rev-list").arg("--count").arg("--merges").arg(format!(
                 "refs/remotes/origin/{}..HEAD",
                 self.config.stage0_metadata.config.nightly_branch
-            )));
+            )))
+        });
         let n = count.trim().parse().unwrap();
         self.prerelease_version.set(Some(n));
         n
@@ -1706,6 +1717,17 @@
     }
 }
 
+/// Extract the beta revision from the full version string.
+///
+/// The full version string looks like "a.b.c-beta.y". And we need to extract
+/// the "y" part from the string.
+pub fn extract_beta_rev(version: &str) -> Option<String> {
+    let parts = version.splitn(2, "-beta.").collect::<Vec<_>>();
+    let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string()));
+
+    count
+}
+
 #[cfg(unix)]
 fn chmod(path: &Path, perms: u32) {
     use std::os::unix::fs::*;
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index 67cb883..040a12f 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -185,6 +185,7 @@
         ("arm-unknown-linux-gnueabi", false),
         ("arm-unknown-linux-gnueabihf", false),
         ("armv7-unknown-linux-gnueabihf", false),
+        ("loongarch64-unknown-linux-gnu", false),
         ("mips-unknown-linux-gnu", false),
         ("mips64-unknown-linux-gnuabi64", false),
         ("mips64el-unknown-linux-gnuabi64", false),
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index bedf34d..fa0a480 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -168,9 +168,14 @@
         if !self.failures.is_empty() {
             println!("\nfailures:\n");
             for failure in &self.failures {
-                if let Some(stdout) = &failure.stdout {
+                if failure.stdout.is_some() || failure.message.is_some() {
                     println!("---- {} stdout ----", failure.name);
-                    println!("{stdout}");
+                    if let Some(stdout) = &failure.stdout {
+                        println!("{stdout}");
+                    }
+                    if let Some(message) = &failure.message {
+                        println!("note: {message}");
+                    }
                 }
             }
 
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index 57f3119..ec01f74 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -1,9 +1,12 @@
 use std::path::PathBuf;
 use std::process::Command;
 
+use clap_complete::shells;
+
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::config::TargetSelection;
 use crate::dist::distdir;
+use crate::flags::get_completion;
 use crate::test;
 use crate::tool::{self, SourceType, Tool};
 use crate::util::output;
@@ -275,3 +278,34 @@
         builder.run(&mut cmd);
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct GenerateCompletions;
+
+impl Step for GenerateCompletions {
+    type Output = ();
+
+    /// Uses `clap_complete` to generate shell completions.
+    fn run(self, builder: &Builder<'_>) {
+        // FIXME(clubby789): enable zsh when clap#4898 is fixed
+        let [bash, fish, powershell] = ["x.py.sh", "x.py.fish", "x.py.ps1"]
+            .map(|filename| builder.src.join("src/etc/completions").join(filename));
+        if let Some(comp) = get_completion(shells::Bash, &bash) {
+            std::fs::write(&bash, comp).expect("writing bash completion");
+        }
+        if let Some(comp) = get_completion(shells::Fish, &fish) {
+            std::fs::write(&fish, comp).expect("writing fish completion");
+        }
+        if let Some(comp) = get_completion(shells::PowerShell, &powershell) {
+            std::fs::write(&powershell, comp).expect("writing powershell completion");
+        }
+    }
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.alias("generate-completions")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(GenerateCompletions);
+    }
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 374b6ca..2b72d6c 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -10,6 +10,8 @@
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 
+use clap_complete::shells;
+
 use crate::builder::crate_description;
 use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::Interned;
@@ -618,6 +620,8 @@
             cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
             // Optimizations can change backtraces
             cargo.env("MIRI_SKIP_UI_CHECKS", "1");
+            // `MIRI_SKIP_UI_CHECKS` and `MIRI_BLESS` are incompatible
+            cargo.env_remove("MIRI_BLESS");
             // Optimizations can change error locations and remove UB so don't run `fail` tests.
             cargo.args(&["tests/pass", "tests/panic"]);
 
@@ -1138,7 +1142,24 @@
         builder.info("tidy check");
         try_run(builder, &mut cmd);
 
-        builder.ensure(ExpandYamlAnchors {});
+        builder.ensure(ExpandYamlAnchors);
+
+        builder.info("x.py completions check");
+        let [bash, fish, powershell] = ["x.py.sh", "x.py.fish", "x.py.ps1"]
+            .map(|filename| builder.src.join("src/etc/completions").join(filename));
+        if builder.config.cmd.bless() {
+            builder.ensure(crate::run::GenerateCompletions);
+        } else {
+            if crate::flags::get_completion(shells::Bash, &bash).is_some()
+                || crate::flags::get_completion(shells::Fish, &fish).is_some()
+                || crate::flags::get_completion(shells::PowerShell, &powershell).is_some()
+            {
+                eprintln!(
+                    "x.py completions were changed; run `x.py run generate-completions` to update them"
+                );
+                crate::detail_exit(1);
+            }
+        }
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index 5898a21..e799d7c 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -257,6 +257,22 @@
 (\*) Compressed debug is enabled by default for gas (assembly) on Linux/x86 targets,
      but that makes our `compiler_builtins` incompatible with binutils < 2.32.
 
+### `loongarch64-linux-gnu.defconfig`
+
+For targets: `loongarch64-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Target options > Target Architecture = loongarch
+- Target options > Bitness = 64-bit
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 5.19.16
+- Binary utilities > Version of binutils = 2.40
+- C-library > glibc version = 2.36
+- C compiler > gcc version = 12.2.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
 ### `mips-linux-gnu.defconfig`
 
 For targets: `mips-unknown-linux-gnu`
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
index 3ac5343..420c42b 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
@@ -33,6 +33,11 @@
 
 ENV HOSTS=arm-unknown-linux-gnueabi,aarch64-unknown-linux-musl
 
-ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs --musl-root-aarch64=/usr/local/aarch64-linux-musl \
-    --set target.aarch64-unknown-linux-musl.crt-static=false
+ENV RUST_CONFIGURE_ARGS \
+      --enable-full-tools \
+      --disable-docs \
+      --musl-root-aarch64=/usr/local/aarch64-linux-musl \
+      --enable-sanitizers \
+      --enable-profiler \
+      --set target.aarch64-unknown-linux-musl.crt-static=false
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
new file mode 100644
index 0000000..78689c4
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
@@ -0,0 +1,30 @@
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+# The latest released version does not support LoongArch.
+COPY scripts/crosstool-ng-git.sh /scripts/
+RUN sh /scripts/crosstool-ng-git.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV PATH=$PATH:/x-tools/loongarch64-unknown-linux-gnu/bin
+
+ENV CC_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-gcc \
+    AR_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-ar \
+    CXX_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-g++
+
+ENV HOSTS=loongarch64-unknown-linux-gnu
+
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
new file mode 100644
index 0000000..576f363
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
@@ -0,0 +1,14 @@
+CT_CONFIG_VERSION="4"
+CT_EXPERIMENTAL=y
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_LOONGARCH=y
+# CT_DEMULTILIB is not set
+CT_ARCH_USE_MMU=y
+CT_ARCH_ARCH="loongarch64"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_5_19=y
+CT_GLIBC_V_2_36=y
+CT_CC_GCC_ENABLE_DEFAULT_PIE=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index d183d4a..806935b 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.16.0
\ No newline at end of file
+0.16.4
\ No newline at end of file
diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh
index 2f8bf11..398362c 100644
--- a/src/ci/docker/scripts/cross-apt-packages.sh
+++ b/src/ci/docker/scripts/cross-apt-packages.sh
@@ -22,6 +22,7 @@
   patch \
   pkg-config \
   python3 \
+  rsync \
   sudo \
   texinfo \
   unzip \
diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh
new file mode 100644
index 0000000..449cc47
--- /dev/null
+++ b/src/ci/docker/scripts/crosstool-ng-git.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -ex
+
+URL=https://github.com/crosstool-ng/crosstool-ng
+REV=943364711a650d9b9e84c1b42c91cc0265b6ab5c
+
+mkdir crosstool-ng
+cd crosstool-ng
+git init
+git fetch --depth=1 ${URL} ${REV}
+git reset --hard FETCH_HEAD
+./bootstrap
+./configure --prefix=/usr/local
+make -j$(nproc)
+make install
+cd ..
+rm -rf crosstool-ng
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index f81e740..fd61946 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -359,6 +359,9 @@
           - name: dist-i686-linux
             <<: *job-linux-8c
 
+          - name: dist-loongarch64-linux
+            <<: *job-linux-8c
+
           - name: dist-mips-linux
             <<: *job-linux-8c
 
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index 7cd5e88..8d03d37 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -48,7 +48,6 @@
 
 LLVM_BOLT_CRATES = LLVM_PGO_CRATES
 
-
 class Pipeline:
     # Paths
     def checkout_path(self) -> Path:
@@ -451,6 +450,44 @@
             )
     return subprocess.run(args, env=environment, check=True)
 
+class BenchmarkRunner:
+    def run_rustc(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+    def run_llvm(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+    def run_bolt(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+class DefaultBenchmarkRunner(BenchmarkRunner):
+    def run_rustc(self, pipeline: Pipeline):
+        # Here we're profiling the `rustc` frontend, so we also include `Check`.
+        # The benchmark set includes various stress tests that put the frontend under pressure.
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Check", "Debug", "Opt"],
+            scenarios=["All"],
+            crates=RUSTC_PGO_CRATES,
+            env=dict(
+                LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
+            )
+        )
+    def run_llvm(self, pipeline: Pipeline):
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Debug", "Opt"],
+            scenarios=["Full"],
+            crates=LLVM_PGO_CRATES
+        )
+
+    def run_bolt(self, pipeline: Pipeline):
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Check", "Debug", "Opt"],
+            scenarios=["Full"],
+            crates=LLVM_BOLT_CRATES
+        )
 
 def run_compiler_benchmarks(
         pipeline: Pipeline,
@@ -580,14 +617,10 @@
         raise Exception(f"Optimized build is not supported for platform {sys.platform}")
 
 
-def gather_llvm_profiles(pipeline: Pipeline):
+def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with PGO instrumented LLVM")
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Debug", "Opt"],
-        scenarios=["Full"],
-        crates=LLVM_PGO_CRATES
-    )
+
+    runner.run_llvm(pipeline)
 
     profile_path = pipeline.llvm_profile_merged_file()
     LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}")
@@ -609,20 +642,12 @@
     delete_directory(pipeline.llvm_profile_dir_root())
 
 
-def gather_rustc_profiles(pipeline: Pipeline):
+def gather_rustc_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with PGO instrumented rustc")
 
-    # Here we're profiling the `rustc` frontend, so we also include `Check`.
-    # The benchmark set includes various stress tests that put the frontend under pressure.
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Check", "Debug", "Opt"],
-        scenarios=["All"],
-        crates=RUSTC_PGO_CRATES,
-        env=dict(
-            LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
-        )
-    )
+
+    runner.run_rustc(pipeline)
+
 
     profile_path = pipeline.rustc_profile_merged_file()
     LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}")
@@ -644,14 +669,10 @@
     delete_directory(pipeline.rustc_profile_dir_root())
 
 
-def gather_llvm_bolt_profiles(pipeline: Pipeline):
+def gather_llvm_bolt_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with BOLT instrumented LLVM")
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Check", "Debug", "Opt"],
-        scenarios=["Full"],
-        crates=LLVM_BOLT_CRATES
-    )
+
+    runner.run_bolt(pipeline)
 
     merged_profile_path = pipeline.llvm_bolt_profile_merged_file()
     profile_files_path = Path("/tmp/prof.fdata")
@@ -744,7 +765,7 @@
     log_metrics(metrics)
 
 
-def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: List[str]):
+def execute_build_pipeline(timer: Timer, pipeline: Pipeline, runner: BenchmarkRunner, final_build_args: List[str]):
     # Clear and prepare tmp directory
     shutil.rmtree(pipeline.opt_artifacts(), ignore_errors=True)
     os.makedirs(pipeline.opt_artifacts(), exist_ok=True)
@@ -762,7 +783,7 @@
             record_metrics(pipeline, rustc_build)
 
         with stage1.section("Gather profiles"):
-            gather_llvm_profiles(pipeline)
+            gather_llvm_profiles(pipeline, runner)
         print_free_disk_space(pipeline)
 
     clear_llvm_files(pipeline)
@@ -781,7 +802,7 @@
             record_metrics(pipeline, rustc_build)
 
         with stage2.section("Gather profiles"):
-            gather_rustc_profiles(pipeline)
+            gather_rustc_profiles(pipeline, runner)
         print_free_disk_space(pipeline)
 
     clear_llvm_files(pipeline)
@@ -804,7 +825,7 @@
                 record_metrics(pipeline, rustc_build)
 
             with stage3.section("Gather profiles"):
-                gather_llvm_bolt_profiles(pipeline)
+                gather_llvm_bolt_profiles(pipeline, runner)
 
         # LLVM is not being cleared here, we want to reuse the previous build
         print_free_disk_space(pipeline)
@@ -819,7 +840,7 @@
         record_metrics(pipeline, stage4)
 
 
-if __name__ == "__main__":
+def run(runner: BenchmarkRunner):
     logging.basicConfig(
         level=logging.DEBUG,
         format="%(name)s %(levelname)-4s: %(message)s",
@@ -832,8 +853,9 @@
 
     timer = Timer()
     pipeline = create_pipeline()
+
     try:
-        execute_build_pipeline(timer, pipeline, build_args)
+        execute_build_pipeline(timer, pipeline, runner, build_args)
     except BaseException as e:
         LOGGER.error("The multi-stage build has failed")
         raise e
@@ -842,3 +864,7 @@
         print_free_disk_space(pipeline)
 
     print_binary_sizes(pipeline)
+
+if __name__ == "__main__":
+    runner = DefaultBenchmarkRunner()
+    run(runner)
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index d9eb4c3..f2aed2f 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit d9eb4c3f75435b008881062ffa77bf0d1527b37d
+Subproject commit f2aed2fe8e9f55508c86ba3aa4b6789b18a08a22
diff --git a/src/doc/nomicon b/src/doc/nomicon
index b5f7500..b5f018f 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit b5f7500fc40775096c2bbd204eae096612cf9047
+Subproject commit b5f018fb5930cb733b0a8aaf2eed975d4771e74d
diff --git a/src/doc/reference b/src/doc/reference
index 28dc0f3..553d99b 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 28dc0f3576b55f5e57c5d6e65cd68ba3161e9fd5
+Subproject commit 553d99b02a53b4133a40d5bd2e19958c67487c00
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index 28dbeaf..f1e6378 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit 28dbeaf5c44bc7f5111ad412e99f2d7c5cec6c90
+Subproject commit f1e637883fafeb83bdd5906ee7f467e4d35b7337
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index 98b49e0..a82a532 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -115,9 +115,9 @@
   <tr>
    <td>Stack smashing protection
    </td>
-   <td>No
+   <td>Yes
    </td>
-   <td>
+   <td>Nightly
    </td>
   </tr>
   <tr>
@@ -432,18 +432,16 @@
 when returning from a function. This is also known as “Stack Protector” or
 “Stack Smashing Protector (SSP)”.
 
-The Rust compiler does not support stack smashing protection. However, more
-comprehensive alternatives to stack smashing protection exist, such as
-shadow and safe stack (see backward-edge control flow protection).
+The Rust compiler supports stack smashing protection on nightly builds[42].
 
 ![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.")
 Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in
 hello-rust.
 
 To check if stack smashing protection is enabled for a given binary, search
-for cross references to `__stack_chk_fail`. The only cross references to
-`__stack_chk_fail` in hello-rust are from the statically-linked libbacktrace
-library (see Fig. 14).
+for cross references to `__stack_chk_fail`. The presence of these
+cross-references in Rust-compiled code (e.g., `hello_rust::main`) indicates
+that the stack smashing protection is enabled (see Fig. 14).
 
 
 ### Forward-edge control flow protection
@@ -697,3 +695,6 @@
 
 41. “ControlFlowIntegrity.” The Rust Unstable Book.
     [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
+
+42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.”
+    GitHub. <https://github.com/rust-lang/rust/pull/84197>
diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
index a49e14b..ef02c60 100644
--- a/src/doc/rustc/src/images/image3.png
+++ b/src/doc/rustc/src/images/image3.png
Binary files differ
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index d22e1cf..3b2463a 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -88,6 +88,7 @@
 `arm-unknown-linux-gnueabi` | ARMv6 Linux (kernel 3.2, glibc 2.17)
 `arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17)
 `armv7-unknown-linux-gnueabihf` | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17)
+[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36)
 `mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23)
 `mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23)
 `mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23)
@@ -266,7 +267,6 @@
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
-[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI)
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
 [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL
diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md
index 16ccaf4..999e71f 100644
--- a/src/doc/rustc/src/platform-support/loongarch-linux.md
+++ b/src/doc/rustc/src/platform-support/loongarch-linux.md
@@ -1,6 +1,6 @@
 # loongarch\*-unknown-linux-\*
 
-**Tier: 3**
+**Tier: 2**
 
 [LoongArch] is a new RISC ISA developed by Loongson Technology Corporation Limited.
 
diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md
index 38fd1db..1fa9f81 100644
--- a/src/doc/rustdoc/src/how-to-write-documentation.md
+++ b/src/doc/rustdoc/src/how-to-write-documentation.md
@@ -165,15 +165,15 @@
 ### Strikethrough
 
 Text may be rendered with a horizontal line through the center by wrapping the
-text with two tilde characters on each side:
+text with one or two tilde characters on each side:
 
 ```text
-An example of ~~strikethrough text~~.
+An example of ~~strikethrough text~~. You can also use ~single tildes~.
 ```
 
 This example will render as:
 
-> An example of ~~strikethrough text~~.
+> An example of ~~strikethrough text~~. You can also use ~single tildes~.
 
 This follows the [GitHub Strikethrough extension][strikethrough].
 
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
new file mode 100644
index 0000000..9f65f1e
--- /dev/null
+++ b/src/etc/completions/x.py.fish
@@ -0,0 +1,490 @@
+complete -c x.py -n "__fish_use_subcommand" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_use_subcommand" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_use_subcommand" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_use_subcommand" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_use_subcommand" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_use_subcommand" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_use_subcommand" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_use_subcommand" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_use_subcommand" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_use_subcommand" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_use_subcommand" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_use_subcommand" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_use_subcommand" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_use_subcommand" -f -a "build" -d 'Compile either the compiler or libraries'
+complete -c x.py -n "__fish_use_subcommand" -f -a "check" -d 'Compile either the compiler or libraries, using cargo check'
+complete -c x.py -n "__fish_use_subcommand" -f -a "clippy" -d 'Run Clippy (uses rustup/cargo-installed clippy binary)'
+complete -c x.py -n "__fish_use_subcommand" -f -a "fix" -d 'Run cargo fix'
+complete -c x.py -n "__fish_use_subcommand" -f -a "fmt" -d 'Run rustfmt'
+complete -c x.py -n "__fish_use_subcommand" -f -a "doc" -d 'Build documentation'
+complete -c x.py -n "__fish_use_subcommand" -f -a "test" -d 'Build and run some test suites'
+complete -c x.py -n "__fish_use_subcommand" -f -a "bench" -d 'Build and run some benchmarks'
+complete -c x.py -n "__fish_use_subcommand" -f -a "clean" -d 'Clean out build directories'
+complete -c x.py -n "__fish_use_subcommand" -f -a "dist" -d 'Build distribution artifacts'
+complete -c x.py -n "__fish_use_subcommand" -f -a "install" -d 'Install distribution artifacts'
+complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained in this repository'
+complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development'
+complete -c x.py -n "__fish_use_subcommand" -f -a "suggest" -d 'Suggest a subset of tests to run, based on modified files'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from build" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from build" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l all-targets -d 'Check all targets'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s A -d 'clippy lints to allow' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s D -d 'clippy lints to deny' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s W -d 'clippy lints to warn on' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s F -d 'clippy lints to forbid' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l fix
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l open -d 'open the docs in a browser'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running tests' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l run -d 'whether to execute run-* tests' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l no-fail-fast -d 'run all tests regardless of failure'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l no-doc -d 'do not run doc tests'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l doc -d 'only run doc tests'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l bless -d 'whether to automatically update stderr/stdout files'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l force-rerun -d 'rerun tests even if the inputs are unchanged'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l only-modified -d 'only run tests that result has been changed'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustfix-coverage -d 'enable this to generate a Rustfix coverage file, which is saved in `/<build_base>/rustfix_missing_coverage.txt`'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l test-args -r
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l all
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from install" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from install" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l args -d 'arguments for the tool' -r
+complete -c x.py -n "__fish_seen_subcommand_from run" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from run" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from run" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l run -d 'run suggested tests'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s h -l help -d 'Print help (see more with \'--help\')'
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
new file mode 100644
index 0000000..569c186
--- /dev/null
+++ b/src/etc/completions/x.py.ps1
@@ -0,0 +1,622 @@
+
+using namespace System.Management.Automation
+using namespace System.Management.Automation.Language
+
+Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
+    param($wordToComplete, $commandAst, $cursorPosition)
+
+    $commandElements = $commandAst.CommandElements
+    $command = @(
+        'x.py'
+        for ($i = 1; $i -lt $commandElements.Count; $i++) {
+            $element = $commandElements[$i]
+            if ($element -isnot [StringConstantExpressionAst] -or
+                $element.StringConstantType -ne [StringConstantType]::BareWord -or
+                $element.Value.StartsWith('-') -or
+                $element.Value -eq $wordToComplete) {
+                break
+        }
+        $element.Value
+    }) -join ';'
+
+    $completions = @(switch ($command) {
+        'x.py' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('build', 'build', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries')
+            [CompletionResult]::new('check', 'check', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries, using cargo check')
+            [CompletionResult]::new('clippy', 'clippy', [CompletionResultType]::ParameterValue, 'Run Clippy (uses rustup/cargo-installed clippy binary)')
+            [CompletionResult]::new('fix', 'fix', [CompletionResultType]::ParameterValue, 'Run cargo fix')
+            [CompletionResult]::new('fmt', 'fmt', [CompletionResultType]::ParameterValue, 'Run rustfmt')
+            [CompletionResult]::new('doc', 'doc', [CompletionResultType]::ParameterValue, 'Build documentation')
+            [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'Build and run some test suites')
+            [CompletionResult]::new('bench', 'bench', [CompletionResultType]::ParameterValue, 'Build and run some benchmarks')
+            [CompletionResult]::new('clean', 'clean', [CompletionResultType]::ParameterValue, 'Clean out build directories')
+            [CompletionResult]::new('dist', 'dist', [CompletionResultType]::ParameterValue, 'Build distribution artifacts')
+            [CompletionResult]::new('install', 'install', [CompletionResultType]::ParameterValue, 'Install distribution artifacts')
+            [CompletionResult]::new('run', 'run', [CompletionResultType]::ParameterValue, 'Run tools contained in this repository')
+            [CompletionResult]::new('setup', 'setup', [CompletionResultType]::ParameterValue, 'Set up the environment for development')
+            [CompletionResult]::new('suggest', 'suggest', [CompletionResultType]::ParameterValue, 'Suggest a subset of tests to run, based on modified files')
+            break
+        }
+        'x.py;build' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;check' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('--all-targets', 'all-targets', [CompletionResultType]::ParameterName, 'Check all targets')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;clippy' {
+            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'clippy lints to allow')
+            [CompletionResult]::new('-D', 'D', [CompletionResultType]::ParameterName, 'clippy lints to deny')
+            [CompletionResult]::new('-W', 'W', [CompletionResultType]::ParameterName, 'clippy lints to warn on')
+            [CompletionResult]::new('-F', 'F', [CompletionResultType]::ParameterName, 'clippy lints to forbid')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;fix' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;fmt' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;doc' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'open the docs in a browser')
+            [CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;test' {
+            [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times')
+            [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)')
+            [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests')
+            [CompletionResult]::new('--compare-mode', 'compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to')
+            [CompletionResult]::new('--pass', 'pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode')
+            [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('--no-fail-fast', 'no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure')
+            [CompletionResult]::new('--no-doc', 'no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests')
+            [CompletionResult]::new('--doc', 'doc', [CompletionResultType]::ParameterName, 'only run doc tests')
+            [CompletionResult]::new('--bless', 'bless', [CompletionResultType]::ParameterName, 'whether to automatically update stderr/stdout files')
+            [CompletionResult]::new('--force-rerun', 'force-rerun', [CompletionResultType]::ParameterName, 'rerun tests even if the inputs are unchanged')
+            [CompletionResult]::new('--only-modified', 'only-modified', [CompletionResultType]::ParameterName, 'only run tests that result has been changed')
+            [CompletionResult]::new('--rustfix-coverage', 'rustfix-coverage', [CompletionResultType]::ParameterName, 'enable this to generate a Rustfix coverage file, which is saved in `/<build_base>/rustfix_missing_coverage.txt`')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;bench' {
+            [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'test-args')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;clean' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'all')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;dist' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;install' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;run' {
+            [CompletionResult]::new('--args', 'args', [CompletionResultType]::ParameterName, 'arguments for the tool')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;setup' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;suggest' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+            [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'run suggested tests')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+    })
+
+    $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
+        Sort-Object -Property ListItemText
+}
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
new file mode 100644
index 0000000..322afdb
--- /dev/null
+++ b/src/etc/completions/x.py.sh
@@ -0,0 +1,1704 @@
+_x.py() {
+    local i cur prev opts cmd
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    prev="${COMP_WORDS[COMP_CWORD-1]}"
+    cmd=""
+    opts=""
+
+    for i in ${COMP_WORDS[@]}
+    do
+        case "${cmd},${i}" in
+            ",$1")
+                cmd="x.py"
+                ;;
+            bootstrap,bench)
+                cmd="bootstrap__bench"
+                ;;
+            bootstrap,build)
+                cmd="bootstrap__build"
+                ;;
+            bootstrap,check)
+                cmd="bootstrap__check"
+                ;;
+            bootstrap,clean)
+                cmd="bootstrap__clean"
+                ;;
+            bootstrap,clippy)
+                cmd="bootstrap__clippy"
+                ;;
+            bootstrap,dist)
+                cmd="bootstrap__dist"
+                ;;
+            bootstrap,doc)
+                cmd="bootstrap__doc"
+                ;;
+            bootstrap,fix)
+                cmd="bootstrap__fix"
+                ;;
+            bootstrap,fmt)
+                cmd="bootstrap__fmt"
+                ;;
+            bootstrap,install)
+                cmd="bootstrap__install"
+                ;;
+            bootstrap,run)
+                cmd="bootstrap__run"
+                ;;
+            bootstrap,setup)
+                cmd="bootstrap__setup"
+                ;;
+            bootstrap,suggest)
+                cmd="bootstrap__suggest"
+                ;;
+            bootstrap,test)
+                cmd="bootstrap__test"
+                ;;
+            *)
+                ;;
+        esac
+    done
+
+    case "${cmd}" in
+        x.py)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__bench)
+            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --test-args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__build)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__check)
+            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__clean)
+            opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__clippy)
+            opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                -A)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                -D)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                -W)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                -F)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__dist)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__doc)
+            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__fix)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__fmt)
+            opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__install)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__run)
+            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__setup)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__suggest)
+            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__test)
+            opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --skip)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --test-args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --compare-mode)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --pass)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --run)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+    esac
+}
+
+complete -F _x.py -o bashdefault -o default x.py
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 38664c3..e9ccea2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -401,12 +401,18 @@
             .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
     }
 
-    /// Finds the `doc` attribute as a NameValue and returns the corresponding
-    /// value found.
-    pub(crate) fn doc_value(&self) -> Option<String> {
+    /// Combine all doc strings into a single value handling indentation and newlines as needed.
+    pub(crate) fn doc_value(&self) -> String {
         self.attrs.doc_value()
     }
 
+    /// Combine all doc strings into a single value handling indentation and newlines as needed.
+    /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
+    /// documentation but it is empty (e.g. `#[doc = ""]`).
+    pub(crate) fn opt_doc_value(&self) -> Option<String> {
+        self.attrs.opt_doc_value()
+    }
+
     pub(crate) fn from_def_id_and_parts(
         def_id: DefId,
         name: Option<Symbol>,
@@ -443,12 +449,6 @@
         }
     }
 
-    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
-    /// with newlines.
-    pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
-        self.attrs.collapsed_doc_value()
-    }
-
     pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
         use crate::html::format::{href, link_tooltip};
 
@@ -1068,17 +1068,6 @@
     }
 }
 
-/// Collapse a collection of [`DocFragment`]s into one string,
-/// handling indentation and newlines as needed.
-pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
-    let mut acc = String::new();
-    for frag in doc_strings {
-        add_doc_fragment(&mut acc, frag);
-    }
-    acc.pop();
-    acc
-}
-
 /// A link that has not yet been rendered.
 ///
 /// This link will be turned into a rendered link by [`Item::links`].
@@ -1163,29 +1152,23 @@
         Attributes { doc_strings, other_attrs }
     }
 
-    /// Finds the `doc` attribute as a NameValue and returns the corresponding
-    /// value found.
-    pub(crate) fn doc_value(&self) -> Option<String> {
-        let mut iter = self.doc_strings.iter();
-
-        let ori = iter.next()?;
-        let mut out = String::new();
-        add_doc_fragment(&mut out, ori);
-        for new_frag in iter {
-            add_doc_fragment(&mut out, new_frag);
-        }
-        out.pop();
-        if out.is_empty() { None } else { Some(out) }
+    /// Combine all doc strings into a single value handling indentation and newlines as needed.
+    pub(crate) fn doc_value(&self) -> String {
+        self.opt_doc_value().unwrap_or_default()
     }
 
-    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
-    /// with newlines.
-    pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
-        if self.doc_strings.is_empty() {
-            None
-        } else {
-            Some(collapse_doc_fragments(&self.doc_strings))
-        }
+    /// Combine all doc strings into a single value handling indentation and newlines as needed.
+    /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
+    /// documentation but it is empty (e.g. `#[doc = ""]`).
+    pub(crate) fn opt_doc_value(&self) -> Option<String> {
+        (!self.doc_strings.is_empty()).then(|| {
+            let mut res = String::new();
+            for frag in &self.doc_strings {
+                add_doc_fragment(&mut res, frag);
+            }
+            res.pop();
+            res
+        })
     }
 
     pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index d8c91a9..3949542 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -1,7 +1,5 @@
 use super::*;
 
-use crate::clean::collapse_doc_fragments;
-
 use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragment, DocFragmentKind};
 use rustc_span::create_default_session_globals_then;
 use rustc_span::source_map::DUMMY_SP;
@@ -22,7 +20,8 @@
     create_default_session_globals_then(|| {
         let mut s = create_doc_fragment(input);
         unindent_doc_fragments(&mut s);
-        assert_eq!(collapse_doc_fragments(&s), expected);
+        let attrs = Attributes { doc_strings: s, other_attrs: Default::default() };
+        assert_eq!(attrs.doc_value(), expected);
     });
 }
 
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index b802fd0..17aa6b3 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -594,9 +594,8 @@
     def_id: DefId,
     vis: ty::Visibility<DefId>,
 ) -> String {
-    let tts: Vec<_> = def.body.tokens.clone().into_trees().collect();
     // Extract the spans of all matchers. They represent the "interface" of the macro.
-    let matchers = tts.chunks(4).map(|arm| &arm[0]);
+    let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
 
     if def.macro_rules {
         format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx.tcx, matchers, ";"))
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a6be132..e10a629 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -367,7 +367,7 @@
 
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 
-    if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
+    if krate.module.doc_value().is_empty() {
         let help = format!(
             "The following guide may be of use:\n\
             {}/rustdoc/how-to-write-documentation.html",
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 575d8ee..f6631b6 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1237,7 +1237,7 @@
         // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us.
         let attrs = Attributes::from_ast(ast_attrs);
-        if let Some(doc) = attrs.collapsed_doc_value() {
+        if let Some(doc) = attrs.opt_doc_value() {
             // Use the outermost invocation, so that doctest names come from where the docs were written.
             let span = ast_attrs
                 .iter()
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index c0730e9..c4758fd 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -327,9 +327,8 @@
                     // which should not be indexed. The crate-item itself is
                     // inserted later on when serializing the search-index.
                     if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) {
-                        let desc = item.doc_value().map_or_else(String::new, |x| {
-                            short_markdown_summary(x.as_str(), &item.link_names(self.cache))
-                        });
+                        let desc =
+                            short_markdown_summary(&item.doc_value(), &item.link_names(self.cache));
                         let ty = item.type_();
                         if ty != ItemType::StructField
                             || u16::from_str_radix(s.as_str(), 10).is_err()
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 4b0aee9..09e7ed2 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -551,7 +551,15 @@
 }
 
 fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
-    matches!(t, Tag::Paragraph | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote)
+    matches!(
+        t,
+        Tag::Paragraph
+            | Tag::Emphasis
+            | Tag::Strong
+            | Tag::Strikethrough
+            | Tag::Link(..)
+            | Tag::BlockQuote
+    )
 }
 
 fn is_forbidden_tag(t: &Tag<'_>) -> bool {
@@ -773,7 +781,7 @@
         ExtraInfo { def_id, sp, tcx }
     }
 
-    fn error_invalid_codeblock_attr(&self, msg: &str, help: &str) {
+    fn error_invalid_codeblock_attr(&self, msg: String, help: &str) {
         if let Some(def_id) = self.def_id.as_local() {
             self.tcx.struct_span_lint_hir(
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
@@ -948,7 +956,7 @@
                     } {
                         if let Some(extra) = extra {
                             extra.error_invalid_codeblock_attr(
-                                &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
+                                format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
                                 help,
                             );
                         }
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 01a92f6..56af257 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -184,11 +184,8 @@
         };
         title.push_str(" - Rust");
         let tyname = it.type_();
-        let desc = it
-            .doc_value()
-            .as_ref()
-            .map(|doc| plain_text_summary(doc, &it.link_names(&self.cache())));
-        let desc = if let Some(desc) = desc {
+        let desc = plain_text_summary(&it.doc_value(), &it.link_names(&self.cache()));
+        let desc = if !desc.is_empty() {
             desc
         } else if it.is_crate() {
             format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index d677316..42e27d3 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -468,7 +468,8 @@
         if !show_def_docs {
             return Ok(());
         }
-        if let Some(s) = item.doc_value() {
+        let s = item.doc_value();
+        if !s.is_empty() {
             let (mut summary_html, has_more_content) =
                 MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
 
@@ -511,7 +512,7 @@
     heading_offset: HeadingOffset,
 ) -> impl fmt::Display + 'a + Captures<'cx> {
     display_fn(move |f| {
-        if let Some(s) = item.collapsed_doc_value() {
+        if let Some(s) = item.opt_doc_value() {
             debug!("Doc block: =====\n{}\n=====", s);
             if is_collapsible {
                 write!(
@@ -1476,7 +1477,7 @@
                     if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
                         // We need the stability of the item from the trait
                         // because impls can't have a stability.
-                        if item.doc_value().is_some() {
+                        if !item.doc_value().is_empty() {
                             document_item_info(cx, it, Some(parent))
                                 .render_into(&mut info_buffer)
                                 .unwrap();
@@ -1747,11 +1748,11 @@
             write!(w, "</summary>")
         }
 
-        if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
+        if let Some(ref dox) = i.impl_item.opt_doc_value() {
             if trait_.is_none() && i.inner_impl().items.is_empty() {
                 w.write_str(
                     "<div class=\"item-info\">\
-                    <div class=\"stab empty-impl\">This impl block contains no items.</div>
+                    <div class=\"stab empty-impl\">This impl block contains no items.</div>\
                 </div>",
                 );
             }
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 4cc81e8..76c8e08 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -420,9 +420,9 @@
                     _ => "",
                 };
 
-                let doc_value = myitem.doc_value().unwrap_or_default();
                 w.write_str(ITEM_TABLE_ROW_OPEN);
-                let docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string();
+                let docs =
+                    MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
                 let (docs_before, docs_after) = if docs.is_empty() {
                     ("", "")
                 } else {
@@ -1338,7 +1338,7 @@
                 clean::VariantKind::Tuple(fields) => {
                     // Documentation on tuple variant fields is rare, so to reduce noise we only emit
                     // the section if at least one field is documented.
-                    if fields.iter().any(|f| f.doc_value().is_some()) {
+                    if fields.iter().any(|f| !f.doc_value().is_empty()) {
                         Some(("Tuple Fields", fields))
                     } else {
                         None
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index a3be6dd..846299f 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -28,9 +28,7 @@
     // has since been learned.
     for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
         if let Some((fqp, _)) = cache.paths.get(&parent) {
-            let desc = item
-                .doc_value()
-                .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache)));
+            let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
             cache.search_index.push(IndexItem {
                 ty: item.type_(),
                 name: item.name.unwrap(),
@@ -45,10 +43,8 @@
         }
     }
 
-    let crate_doc = krate
-        .module
-        .doc_value()
-        .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(cache)));
+    let crate_doc =
+        short_markdown_summary(&krate.module.doc_value(), &krate.module.link_names(cache));
 
     // Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
     // we need the alias element to have an array of items.
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 99cf8e4..c1324c0 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -1,6 +1,5 @@
 .setting-line {
 	margin: 1.2em 0.6em;
-	position: relative;
 }
 
 .setting-radio input, .setting-check input {
@@ -15,11 +14,6 @@
 .setting-radio input {
 	border-radius: 50%;
 }
-.setting-check input:checked {
-	content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
-		<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
-		<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
-}
 
 .setting-radio span, .setting-check span {
 	padding-bottom: 1px;
@@ -52,6 +46,9 @@
 .setting-check input:checked {
 	background-color: var(--settings-input-color);
 	border-width: 1px;
+	content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
+		<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
+		<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
 }
 .setting-radio input:focus, .setting-check input:focus {
 	box-shadow: 0 0 1px 1px var(--settings-input-color);
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index b1cef20..935bb72 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -40,7 +40,7 @@
                 (String::from(&**link), id_from_item_default(id.into(), self.tcx))
             })
             .collect();
-        let docs = item.attrs.collapsed_doc_value();
+        let docs = item.opt_doc_value();
         let attrs = item.attributes(self.tcx, true);
         let span = item.span(self.tcx);
         let visibility = item.visibility(self.tcx);
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b6eb450..0a56916 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -192,11 +192,11 @@
         Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(),
         Ok(value) => early_error(
             ErrorOutputType::default(),
-            &format!("invalid log color value '{}': expected one of always, never, or auto", value),
+            format!("invalid log color value '{}': expected one of always, never, or auto", value),
         ),
         Err(VarError::NotUnicode(value)) => early_error(
             ErrorOutputType::default(),
-            &format!(
+            format!(
                 "invalid log color value '{}': expected one of always, never, or auto",
                 value.to_string_lossy()
             ),
@@ -228,7 +228,7 @@
                 .map_err(|arg| {
                     early_warn(
                         ErrorOutputType::default(),
-                        &format!("Argument {} is not valid Unicode: {:?}", i, arg),
+                        format!("Argument {} is not valid Unicode: {:?}", i, arg),
                     );
                 })
                 .ok()
@@ -721,7 +721,7 @@
     let matches = match options.parse(&args[1..]) {
         Ok(m) => m,
         Err(err) => {
-            early_error(ErrorOutputType::default(), &err.to_string());
+            early_error(ErrorOutputType::default(), err.to_string());
         }
     };
 
@@ -739,6 +739,9 @@
         }
     };
 
+    // Set parallel mode before error handler creation, which will create `Lock`s.
+    interface::set_thread_safe_mode(&options.unstable_opts);
+
     let diag = core::new_handler(
         options.error_format,
         None,
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index be5286b..6ead0cd 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -206,13 +206,7 @@
                 let has_docs = !i.attrs.doc_strings.is_empty();
                 let mut tests = Tests { found_tests: 0 };
 
-                find_testable_code(
-                    &i.attrs.collapsed_doc_value().unwrap_or_default(),
-                    &mut tests,
-                    ErrorCodes::No,
-                    false,
-                    None,
-                );
+                find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None);
 
                 let has_doc_example = tests.found_tests != 0;
                 let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 10295cb..b6cd897 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -34,9 +34,7 @@
 
 impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
-        let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
-
-        look_for_tests(self.cx, &dox, item);
+        look_for_tests(self.cx, &item.doc_value(), item);
 
         self.visit_item_recur(item)
     }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index a885ff0..9e6894a 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -8,7 +8,7 @@
     fx::{FxHashMap, FxHashSet},
     intern::Interned,
 };
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticMessage};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
@@ -24,6 +24,7 @@
 use smallvec::{smallvec, SmallVec};
 
 use std::borrow::Cow;
+use std::fmt::Display;
 use std::mem;
 use std::ops::Range;
 
@@ -148,7 +149,7 @@
             Def(kind, id) => Ok(Res::Def(kind, id)),
             PrimTy(prim) => Ok(Res::Primitive(PrimitiveType::from_hir(prim))),
             // e.g. `#[derive]`
-            NonMacroAttr(..) | Err => Result::Err(()),
+            ToolMod | NonMacroAttr(..) | Err => Result::Err(()),
             other => bug!("unrecognized res {:?}", other),
         }
     }
@@ -841,7 +842,7 @@
         match self {
             PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
             PreprocessingError::Disambiguator(range, msg) => {
-                disambiguator_error(cx, diag_info, range.clone(), msg)
+                disambiguator_error(cx, diag_info, range.clone(), msg.as_str())
             }
             PreprocessingError::MalformedGenerics(err, path_str) => {
                 report_malformed_generics(cx, diag_info, *err, path_str)
@@ -1185,7 +1186,7 @@
             }
             suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
         };
-        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, callback);
+        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, callback);
     }
 
     fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &Range<usize>, item: &Item) {
@@ -1581,7 +1582,7 @@
 fn report_diagnostic(
     tcx: TyCtxt<'_>,
     lint: &'static Lint,
-    msg: &str,
+    msg: impl Into<DiagnosticMessage> + Display,
     DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
     decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
 ) {
@@ -1649,7 +1650,7 @@
     report_diagnostic(
         tcx,
         BROKEN_INTRA_DOC_LINKS,
-        &format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{}`", path_str),
         &diag_info,
         |diag, sp| {
             let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx),);
@@ -1865,20 +1866,20 @@
 
 fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
     let msg = format!("`{}` contains multiple anchors", diag_info.ori_link);
-    anchor_failure(cx, diag_info, &msg, 1)
+    anchor_failure(cx, diag_info, msg, 1)
 }
 
 fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, def_id: DefId) {
     let (link, kind) = (diag_info.ori_link, Res::from_def_id(cx.tcx, def_id).descr());
     let msg = format!("`{link}` contains an anchor, but links to {kind}s are already anchored");
-    anchor_failure(cx, diag_info, &msg, 0)
+    anchor_failure(cx, diag_info, msg, 0)
 }
 
 /// Report an anchor failure.
 fn anchor_failure(
     cx: &DocContext<'_>,
     diag_info: DiagnosticInfo<'_>,
-    msg: &str,
+    msg: String,
     anchor_idx: usize,
 ) {
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp| {
@@ -1898,7 +1899,7 @@
     cx: &DocContext<'_>,
     mut diag_info: DiagnosticInfo<'_>,
     disambiguator_range: Range<usize>,
-    msg: &str,
+    msg: impl Into<DiagnosticMessage> + Display,
 ) {
     diag_info.link_range = disambiguator_range;
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
@@ -1919,7 +1920,7 @@
     report_diagnostic(
         cx.tcx,
         BROKEN_INTRA_DOC_LINKS,
-        &format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{}`", path_str),
         &diag_info,
         |diag, sp| {
             let note = match err {
@@ -1994,7 +1995,7 @@
         }
     }
 
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "ambiguous link");
         } else {
@@ -2046,7 +2047,7 @@
     let msg =
         format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
 
-    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "this item is private");
         }
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index 423230c..a10d5fd 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -18,7 +18,7 @@
             // If non-local, no need to check anything.
             return;
         };
-    let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+    let dox = item.doc_value();
     if !dox.is_empty() {
         let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
             let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 8f873db..f489f50 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -17,7 +17,7 @@
 use crate::passes::source_span_for_markdown_range;
 
 pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) {
-    if let Some(dox) = &item.attrs.collapsed_doc_value() {
+    if let Some(dox) = &item.opt_doc_value() {
         let sp = item.attr_span(cx.tcx);
         let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp);
         for code_block in markdown::rust_code_blocks(dox, &extra) {
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 4f72df5..f040364 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -15,7 +15,7 @@
     let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
     // If non-local, no need to check anything.
     else { return };
-    let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+    let dox = item.doc_value();
     if !dox.is_empty() {
         let report_diag = |msg: &str, range: &Range<usize>, is_open_tag: bool| {
             let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs) {
diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs
index 33cef82..683c224 100644
--- a/src/librustdoc/passes/lint/unescaped_backticks.rs
+++ b/src/librustdoc/passes/lint/unescaped_backticks.rs
@@ -16,7 +16,7 @@
         return;
     };
 
-    let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+    let dox = item.doc_value();
     if dox.is_empty() {
         return;
     }
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index cba55e5..73fc26a 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -194,7 +194,7 @@
                     })
                 {
                     return None;
-                } else if imp.items.is_empty() && i.doc_value().is_none() {
+                } else if imp.items.is_empty() && i.doc_value().is_empty() {
                     return None;
                 }
             }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index ff13daa..8f8dc6b 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,7 +5,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
-use rustc_hir::intravisit::{walk_item, Visitor};
+use rustc_hir::intravisit::{walk_body, walk_item, Visitor};
 use rustc_hir::{Node, CRATE_HIR_ID};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
@@ -106,6 +106,7 @@
     exact_paths: DefIdMap<Vec<Symbol>>,
     modules: Vec<Module<'tcx>>,
     is_importable_from_parent: bool,
+    inside_body: bool,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -129,6 +130,7 @@
             exact_paths: Default::default(),
             modules: vec![om],
             is_importable_from_parent: true,
+            inside_body: false,
         }
     }
 
@@ -368,6 +370,26 @@
         import_id: Option<LocalDefId>,
     ) {
         debug!("visiting item {:?}", item);
+        if self.inside_body {
+            // Only impls can be "seen" outside a body. For example:
+            //
+            // ```
+            // struct Bar;
+            //
+            // fn foo() {
+            //     impl Bar { fn bar() {} }
+            // }
+            // Bar::bar();
+            // ```
+            if let hir::ItemKind::Impl(impl_) = item.kind &&
+                // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+                // them up regardless of where they're located.
+                impl_.of_trait.is_none()
+            {
+                self.add_to_current_mod(item, None, None);
+            }
+            return;
+        }
         let name = renamed.unwrap_or(item.ident.name);
         let tcx = self.cx.tcx;
 
@@ -564,4 +586,10 @@
     fn visit_lifetime(&mut self, _: &hir::Lifetime) {
         // Unneeded.
     }
+
+    fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) {
+        let prev = mem::replace(&mut self.inside_body, true);
+        walk_body(self, b);
+        self.inside_body = prev;
+    }
 }
diff --git a/src/llvm-project b/src/llvm-project
index ea6fa9c..533d3f3 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit ea6fa9c2d43aaf0f11559719eda9b54d356d5416
+Subproject commit 533d3f338b804d54e5d0ac4fba6276af23002d9c
diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml
index d63caa7..d354803 100644
--- a/src/rustdoc-json-types/Cargo.toml
+++ b/src/rustdoc-json-types/Cargo.toml
@@ -12,3 +12,4 @@
 
 [dev-dependencies]
 serde_json = "1.0"
+bincode = "1"
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 3556834..ba8eeaa 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -8,7 +8,7 @@
 use std::path::PathBuf;
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 25;
+pub const FORMAT_VERSION: u32 = 26;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -83,7 +83,6 @@
     /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
     pub attrs: Vec<String>,
     pub deprecation: Option<Deprecation>,
-    #[serde(flatten)]
     pub inner: ItemEnum,
 }
 
@@ -222,7 +221,7 @@
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-#[serde(tag = "kind", content = "inner", rename_all = "snake_case")]
+#[serde(rename_all = "snake_case")]
 pub enum ItemEnum {
     Module(Module),
     ExternCrate {
@@ -543,7 +542,6 @@
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
-#[serde(tag = "kind", content = "inner")]
 pub enum Type {
     /// Structs, enums, and unions
     ResolvedPath(Path),
diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs
index 399ff54..1126d5f 100644
--- a/src/rustdoc-json-types/tests.rs
+++ b/src/rustdoc-json-types/tests.rs
@@ -8,11 +8,15 @@
         impls: vec![],
     });
 
+    // JSON
     let struct_json = serde_json::to_string(&s).unwrap();
-
     let de_s = serde_json::from_str(&struct_json).unwrap();
-
     assert_eq!(s, de_s);
+
+    // Bincode
+    let encoded: Vec<u8> = bincode::serialize(&s).unwrap();
+    let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
+    assert_eq!(s, decoded);
 }
 
 #[test]
@@ -24,9 +28,13 @@
         impls: vec![],
     });
 
+    // JSON
     let union_json = serde_json::to_string(&u).unwrap();
-
     let de_u = serde_json::from_str(&union_json).unwrap();
-
     assert_eq!(u, de_u);
+
+    // Bincode
+    let encoded: Vec<u8> = bincode::serialize(&u).unwrap();
+    let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
+    assert_eq!(u, decoded);
 }
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 21dad9e..8b28c68 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -24,6 +24,7 @@
     "i686-pc-windows-gnu",
     "i686-pc-windows-msvc",
     "i686-unknown-linux-gnu",
+    "loongarch64-unknown-linux-gnu",
     "mips-unknown-linux-gnu",
     "mips64-unknown-linux-gnuabi64",
     "mips64el-unknown-linux-gnuabi64",
@@ -97,6 +98,7 @@
     "i686-unknown-linux-gnu",
     "i686-unknown-linux-musl",
     "i686-unknown-uefi",
+    "loongarch64-unknown-linux-gnu",
     "m68k-unknown-linux-gnu",
     "mips-unknown-linux-gnu",
     "mips-unknown-linux-musl",
diff --git a/src/tools/cargo b/src/tools/cargo
index 13413c6..64fb38c 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 13413c64ff88dd6c2824e9eb9374fc5f10895d28
+Subproject commit 64fb38c97ac4d3a327fc9032c862dd28c8833b17
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index b992130..a9d4215 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -39,7 +39,7 @@
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 93198aa..30a156c 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -27,7 +27,7 @@
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
       with:
         ref: ${{ github.ref }}
 
@@ -83,7 +83,7 @@
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -149,7 +149,7 @@
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -173,7 +173,7 @@
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -233,7 +233,7 @@
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 14f2021..514706d 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -25,7 +25,7 @@
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     # Run
     - name: Build
diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml
index 71d71d1..f42928c 100644
--- a/src/tools/clippy/.github/workflows/deploy.yml
+++ b/src/tools/clippy/.github/workflows/deploy.yml
@@ -21,10 +21,10 @@
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
       with:
         ref: ${{ env.TARGET_BRANCH }}
         path: 'out'
diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml
index 0bc2f49..7d25b6a 100644
--- a/src/tools/clippy/.github/workflows/remark.yml
+++ b/src/tools/clippy/.github/workflows/remark.yml
@@ -16,10 +16,10 @@
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Setup Node.js
-      uses: actions/setup-node@v1.4.4
+      uses: actions/setup-node@v3
       with:
         node-version: '14.x'
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index ebf5b58..79f2a47 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4620,6 +4620,7 @@
 [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
 [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
 [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
+[`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
 [`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
 [`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
 [`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_structs_with_brackets
@@ -4785,6 +4786,7 @@
 [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
 [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
 [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
+[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back
 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
@@ -4897,6 +4899,7 @@
 [`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
 [`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
 [`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
+[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 [`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
 [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
@@ -4978,6 +4981,7 @@
 [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
+[`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns
 [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
 [`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
 [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 6745e15..d712d3e 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -278,7 +278,7 @@
 
 <!-- REUSE-IgnoreStart -->
 
-Copyright 2014-2022 The Rust Project Developers
+Copyright 2014-2023 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md
index 225de84..d7c2775 100644
--- a/src/tools/clippy/book/src/development/type_checking.md
+++ b/src/tools/clippy/book/src/development/type_checking.md
@@ -133,7 +133,7 @@
 - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
 - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
 
-[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
+[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt
 [AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html
 [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty
 [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type
@@ -142,9 +142,9 @@
 [kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind
 [LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
 [LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
-[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
+[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/typeck_results/struct.TypeckResults.html#method.pat_ty
 [Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
-[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
+[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html
 [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html
 [middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html
 [hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 37e1e6a..98e69c7 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -17,7 +17,7 @@
 itertools = "0.10.1"
 pulldown-cmark = { version = "0.9", default-features = false }
 quine-mc_cluskey = "0.2"
-regex-syntax = "0.6"
+regex-syntax = "0.7"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
 tempfile = { version = "3.2", optional = true }
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index a36df55..a8dc0cb 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -38,7 +38,7 @@
             _ => return,
         };
         let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return };
-        let Some((Constant::Bool(val), _)) = constant(cx, cx.typeck_results(), condition) else { return };
+        let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else { return };
         if val {
             span_lint_and_help(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 751c262..897495b 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -178,6 +178,52 @@
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for empty lines after documenation comments.
+    ///
+    /// ### Why is this bad?
+    /// The documentation comment was most likely meant to be an inner attribute or regular comment.
+    /// If it was intended to be a documentation comment, then the empty line should be removed to
+    /// be more idiomatic.
+    ///
+    /// ### Known problems
+    /// Only detects empty lines immediately following the documentation. If the doc comment is followed
+    /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
+    /// in combination with this lint to detect both cases.
+    ///
+    /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
+    ///
+    /// ### Example
+    /// ```rust
+    /// /// Some doc comment with a blank line after it.
+    ///
+    /// fn not_quite_good_code() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// /// Good (no blank line)
+    /// fn this_is_fine() { }
+    /// ```
+    ///
+    /// ```rust
+    /// // Good (convert to a regular comment)
+    ///
+    /// fn this_is_fine_too() { }
+    /// ```
+    ///
+    /// ```rust
+    /// //! Good (convert to a comment on an inner attribute)
+    ///
+    /// fn this_is_fine_as_well() { }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub EMPTY_LINE_AFTER_DOC_COMMENTS,
+    nursery,
+    "empty line after documentation comments"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
     ///
     /// ### Why is this bad?
@@ -292,6 +338,30 @@
     "ensures that all `allow` and `expect` attributes have a reason"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `any` and `all` combinators in `cfg` with only one condition.
+    ///
+    /// ### Why is this bad?
+    /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
+    ///
+    /// ### Example
+    /// ```rust
+    /// #[cfg(any(unix))]
+    /// pub struct Bar;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// #[cfg(unix)]
+    /// pub struct Bar;
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub NON_MINIMAL_CFG,
+    style,
+    "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
+}
+
 declare_lint_pass!(Attributes => [
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
@@ -604,6 +674,8 @@
     DEPRECATED_CFG_ATTR,
     MISMATCHED_TARGET_OS,
     EMPTY_LINE_AFTER_OUTER_ATTR,
+    EMPTY_LINE_AFTER_DOC_COMMENTS,
+    NON_MINIMAL_CFG,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
@@ -614,15 +686,22 @@
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
         check_deprecated_cfg_attr(cx, attr, &self.msrv);
         check_mismatched_target_os(cx, attr);
+        check_minimal_cfg_condition(cx, attr);
     }
 
     extract_msrv_attr!(EarlyContext);
 }
 
+/// Check for empty lines after outer attributes.
+///
+/// Attributes and documenation comments are both considered outer attributes
+/// by the AST. However, the average user likely considers them to be different.
+/// Checking for empty lines after each of these attributes is split into two different
+/// lints but can share the same logic.
 fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
     let mut iter = item.attrs.iter().peekable();
     while let Some(attr) = iter.next() {
-        if matches!(attr.kind, AttrKind::Normal(..))
+        if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
             && attr.style == AttrStyle::Outer
             && is_present_in_source(cx, attr.span)
         {
@@ -639,13 +718,20 @@
                 let lines = without_block_comments(lines);
 
                 if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
-                    span_lint(
-                        cx,
-                        EMPTY_LINE_AFTER_OUTER_ATTR,
-                        begin_of_attr_to_item,
-                        "found an empty line after an outer attribute. \
-                        Perhaps you forgot to add a `!` to make it an inner attribute?",
-                    );
+                    let (lint_msg, lint_type) = match attr.kind {
+                        AttrKind::DocComment(..) => (
+                            "found an empty line after a doc comment. \
+                            Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
+                            EMPTY_LINE_AFTER_DOC_COMMENTS,
+                        ),
+                        AttrKind::Normal(..) => (
+                            "found an empty line after an outer attribute. \
+                            Perhaps you forgot to add a `!` to make it an inner attribute?",
+                            EMPTY_LINE_AFTER_OUTER_ATTR,
+                        ),
+                    };
+
+                    span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
                 }
             }
         }
@@ -690,6 +776,48 @@
     }
 }
 
+fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
+    for item in items.iter() {
+        if let NestedMetaItem::MetaItem(meta) = item {
+            if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
+                continue;
+            }
+            if let MetaItemKind::List(list) = &meta.kind {
+                check_nested_cfg(cx, list);
+                if list.len() == 1 {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is only one condition",
+                        |diag| {
+                            if let Some(snippet) = snippet_opt(cx, list[0].span()) {
+                                diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
+                            }
+                        },
+                    );
+                } else if list.is_empty() && meta.has_name(sym::all) {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is no condition",
+                        |_| {},
+                    );
+                }
+            }
+        }
+    }
+}
+
+fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg) &&
+        let Some(items) = attr.meta_item_list()
+    {
+        check_nested_cfg(cx, &items);
+    }
+}
+
 fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
     fn find_os(name: &str) -> Option<&'static str> {
         UNIX_SYSTEMS
diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
index c4520d0..814108e 100644
--- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
@@ -1,5 +1,6 @@
 use crate::reference::DEREF_ADDROF;
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{get_parent_expr, is_lint_allowed};
@@ -47,8 +48,8 @@
 
 declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
 
-impl LateLintPass<'_> for BorrowDerefRef {
-    fn check_expr(&mut self, cx: &LateContext<'_>, e: &rustc_hir::Expr<'_>) {
+impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
         if_chain! {
             if !e.span.from_expansion();
             if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind;
@@ -58,6 +59,7 @@
             if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) );
             let ref_ty = cx.typeck_results().expr_ty(deref_target);
             if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind();
+            if !is_from_proc_macro(cx, e);
             then{
 
                 if let Some(parent_expr) = get_parent_expr(cx, e){
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index dfa949d..e42c3fe 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -8,7 +8,9 @@
     Block, Expr, ExprKind, Local, Node, QPath, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
+use rustc_middle::ty::IsSuggestable;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
@@ -49,7 +51,6 @@
             && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
             && is_default_equivalent(cx, arg)
         {
-            let arg_ty = cx.typeck_results().expr_ty(arg);
             span_lint_and_sugg(
                 cx,
                 BOX_DEFAULT,
@@ -58,8 +59,10 @@
                 "try",
                 if is_plain_default(arg_path) || given_type(cx, expr) {
                     "Box::default()".into()
-                } else {
+                } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
                     with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
+                } else {
+                    return
                 },
                 Applicability::MachineApplicable
             );
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
index 322dc41..da75612 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
@@ -21,8 +21,8 @@
 
 fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
     match constant(cx, cx.typeck_results(), e) {
-        Some((Constant::F64(n), _)) => n.is_nan(),
-        Some((Constant::F32(n), _)) => n.is_nan(),
+        Some(Constant::F64(n)) => n.is_nan(),
+        Some(Constant::F32(n)) => n.is_nan(),
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 95c2ecb..84b99ad 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -15,7 +15,7 @@
 use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
 
 fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
-    if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) {
+    if let Some(Constant::Int(c)) = constant(cx, cx.typeck_results(), expr) {
         Some(c)
     } else {
         None
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index a20a97d..a83dfd9 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -29,7 +29,7 @@
             // Don't lint for positive constants.
             let const_val = constant(cx, cx.typeck_results(), cast_op);
             if_chain! {
-                if let Some((Constant::Int(n), _)) = const_val;
+                if let Some(Constant::Int(n)) = const_val;
                 if let ty::Int(ity) = *cast_from.kind();
                 if sext(cx.tcx, n, ity) >= 0;
                 then {
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 799e71e..ea17e7a 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -3,10 +3,10 @@
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_hir::{Expr, ExprKind, Node};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::sym;
+use rustc_span::{sym, BytePos, Pos, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -31,6 +31,31 @@
     "`dbg!` macro is intended as a debugging tool"
 }
 
+/// Gets the span of the statement up to the next semicolon, if and only if the next
+/// non-whitespace character actually is a semicolon.
+/// E.g.
+/// ```rust,ignore
+/// 
+///    dbg!();
+///    ^^^^^^^  this span is returned
+///
+///   foo!(dbg!());
+///             no span is returned
+/// ```
+fn span_including_semi(cx: &LateContext<'_>, span: Span) -> Option<Span> {
+    let sm = cx.sess().source_map();
+    let sf = sm.lookup_source_file(span.hi());
+    let src = sf.src.as_ref()?.get(span.hi().to_usize()..)?;
+    let first_non_whitespace = src.find(|c: char| !c.is_whitespace())?;
+
+    if src.as_bytes()[first_non_whitespace] == b';' {
+        let hi = span.hi() + BytePos::from_usize(first_non_whitespace + 1);
+        Some(span.with_hi(hi))
+    } else {
+        None
+    }
+}
+
 #[derive(Copy, Clone)]
 pub struct DbgMacro {
     allow_dbg_in_tests: bool,
@@ -55,13 +80,25 @@
                 return;
             }
             let mut applicability = Applicability::MachineApplicable;
-            let suggestion = match expr.peel_drop_temps().kind {
+
+            let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
                 // dbg!()
-                ExprKind::Block(_, _) => String::new(),
-                // dbg!(1)
-                ExprKind::Match(val, ..) => {
-                    snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string()
+                ExprKind::Block(..) => {
+                    // If the `dbg!` macro is a "free" statement and not contained within other expressions,
+                    // remove the whole statement.
+                    if let Some(Node::Stmt(stmt)) = cx.tcx.hir().find_parent(expr.hir_id)
+                        && let Some(span) = span_including_semi(cx, stmt.span.source_callsite())
+                    {
+                        (span, String::new())
+                    } else {
+                        (macro_call.span, String::from("()"))
+                    }
                 },
+                // dbg!(1)
+                ExprKind::Match(val, ..) => (
+                    macro_call.span,
+                    snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
+                ),
                 // dbg!(2, 3)
                 ExprKind::Tup(
                     [
@@ -82,7 +119,7 @@
                         "..",
                         &mut applicability,
                     );
-                    format!("({snippet})")
+                    (macro_call.span, format!("({snippet})"))
                 },
                 _ => return,
             };
@@ -90,7 +127,7 @@
             span_lint_and_sugg(
                 cx,
                 DBG_MACRO,
-                macro_call.span,
+                sugg_span,
                 "the `dbg!` macro is intended as a debugging tool",
                 "remove the invocation before committing it to a version control system",
                 suggestion,
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 04993e4..423eee4 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -48,9 +48,11 @@
     crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
     crate::attrs::DEPRECATED_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_SEMVER_INFO,
+    crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
     crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
     crate::attrs::MISMATCHED_TARGET_OS_INFO,
+    crate::attrs::NON_MINIMAL_CFG_INFO,
     crate::attrs::USELESS_ATTRIBUTE_INFO,
     crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
     crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
@@ -347,6 +349,7 @@
     crate::methods::ITER_WITH_DRAIN_INFO,
     crate::methods::MANUAL_FILTER_MAP_INFO,
     crate::methods::MANUAL_FIND_MAP_INFO,
+    crate::methods::MANUAL_NEXT_BACK_INFO,
     crate::methods::MANUAL_OK_OR_INFO,
     crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
     crate::methods::MANUAL_SPLIT_ONCE_INFO,
@@ -485,7 +488,6 @@
     crate::operators::FLOAT_EQUALITY_WITHOUT_ABS_INFO,
     crate::operators::IDENTITY_OP_INFO,
     crate::operators::INEFFECTIVE_BIT_MASK_INFO,
-    crate::operators::INTEGER_ARITHMETIC_INFO,
     crate::operators::INTEGER_DIVISION_INFO,
     crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
     crate::operators::MODULO_ARITHMETIC_INFO,
@@ -535,6 +537,7 @@
     crate::redundant_slicing::REDUNDANT_SLICING_INFO,
     crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
     crate::ref_option_ref::REF_OPTION_REF_INFO,
+    crate::ref_patterns::REF_PATTERNS_INFO,
     crate::reference::DEREF_ADDROF_INFO,
     crate::regex::INVALID_REGEX_INFO,
     crate::regex::TRIVIAL_REGEX_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
index e529d81..9bd7a0d 100644
--- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,4 +1,4 @@
-use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, match_def_path, paths};
+use clippy_utils::{diagnostics::span_lint_and_sugg, match_def_path, paths};
 use hir::{def::Res, ExprKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -55,7 +55,8 @@
             if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind();
             if def.is_struct();
             if let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant();
-            if !var.is_field_list_non_exhaustive() && !is_from_proc_macro(cx, expr);
+            if !var.is_field_list_non_exhaustive();
+            if !expr.span.from_expansion() && !qpath.span().from_expansion();
             then {
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index b2f7d02..9c60edb 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -98,7 +98,7 @@
             let is_copy = is_copy(cx, arg_ty);
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             let (lint, msg) = match fn_name {
-                // early return for uplifted lints: drop_ref, drop_copy, forget_ref, forget_copy
+                // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types
                 sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
                 sym::mem_forget if arg_ty.is_ref() => return,
                 sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index a1a2c39..3c55a56 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -114,7 +114,7 @@
 // Returns the specialized log method for a given base if base is constant
 // and is one of 2, 10 and e
 fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), base) {
+    if let Some(value) = constant(cx, cx.typeck_results(), base) {
         if F32(2.0) == value || F64(2.0) == value {
             return Some("log2");
         } else if F32(10.0) == value || F64(10.0) == value {
@@ -193,8 +193,8 @@
             constant(cx, cx.typeck_results(), lhs),
             constant(cx, cx.typeck_results(), rhs),
         ) {
-            (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
-            (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
+            (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs,
+            (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs,
             _ => return,
         };
 
@@ -237,7 +237,7 @@
 
 fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
     // Check receiver
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), receiver) {
+    if let Some(value) = constant(cx, cx.typeck_results(), receiver) {
         if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
             Some("exp")
         } else if F32(2.0) == value || F64(2.0) == value {
@@ -258,7 +258,7 @@
     }
 
     // Check argument
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+    if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
         let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
             (
                 SUBOPTIMAL_FLOPS,
@@ -298,7 +298,7 @@
 }
 
 fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+    if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
         if value == Int(2) {
             if let Some(parent) = get_parent_expr(cx, expr) {
                 if let Some(grandparent) = get_parent_expr(cx, parent) {
@@ -384,8 +384,8 @@
                 _
             ) = &add_rhs.kind;
             if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
-            if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), largs_1);
-            if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), rargs_1);
+            if let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1);
+            if let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1);
             if Int(2) == lvalue && Int(2) == rvalue;
             then {
                 return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, "..").maybe_par(), Sugg::hir(cx, rargs_0, "..")));
@@ -416,7 +416,7 @@
     if_chain! {
         if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind;
         if cx.typeck_results().expr_ty(lhs).is_floating_point();
-        if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
+        if let Some(value) = constant(cx, cx.typeck_results(), rhs);
         if F32(1.0) == value || F64(1.0) == value;
         if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind;
         if cx.typeck_results().expr_ty(self_arg).is_floating_point();
@@ -669,8 +669,8 @@
             mul_lhs,
             mul_rhs,
         ) = &div_lhs.kind;
-        if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), div_rhs);
-        if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), mul_rhs);
+        if let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs);
+        if let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs);
         then {
             // TODO: also check for constant values near PI/180 or 180/PI
             if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
index d8f4a5f..521045a 100644
--- a/src/tools/clippy/clippy_lints/src/fn_null_check.rs
+++ b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
@@ -89,11 +89,7 @@
 
                     // Catching:
                     // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
-                    _ if matches!(
-                        constant(cx, cx.typeck_results(), to_check),
-                        Some((Constant::RawPtr(0), _))
-                    ) =>
-                    {
+                    _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => {
                         lint_expr(cx, expr);
                     },
 
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index 012aa5a..ee7973b 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -101,10 +101,10 @@
 fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
     if let ExprKind::Binary(op, l, r) = expr.kind {
         let tr = cx.typeck_results();
-        if let Some((Constant::Int(c), _)) = constant(cx, tr, r) {
+        if let Some(Constant::Int(c)) = constant(cx, tr, r) {
             return Some((c, op.node, l));
         };
-        if let Some((Constant::Int(c), _)) = constant(cx, tr, l) {
+        if let Some(Constant::Int(c)) = constant(cx, tr, l) {
             return Some((c, invert_op(op.node)?, r));
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index bdeddf4..7a269e9 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -254,7 +254,7 @@
                 let parent_id = map.parent_id(expr.hir_id);
                 if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id);
                 if let hir::ExprKind::Index(_, index_expr) = parent_expr.kind;
-                if let Some((Constant::Int(index_value), _)) = constant(cx, cx.typeck_results(), index_expr);
+                if let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr);
                 if let Ok(index_value) = index_value.try_into();
                 if index_value < max_suggested_slice;
 
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index 924a361..22c14d9 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -191,18 +191,14 @@
 /// Returns a tuple of options with the start and end (exclusive) values of
 /// the range. If the start or end is not constant, None is returned.
 fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u128) -> (Option<u128>, Option<u128>) {
-    let s = range
-        .start
-        .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+    let s = range.start.map(|expr| constant(cx, cx.typeck_results(), expr));
     let start = match s {
         Some(Some(Constant::Int(x))) => Some(x),
         Some(_) => None,
         None => Some(0),
     };
 
-    let e = range
-        .end
-        .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+    let e = range.end.map(|expr| constant(cx, cx.typeck_results(), expr));
     let end = match e {
         Some(Some(Constant::Int(x))) => {
             if range.limits == RangeLimits::Closed {
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 16772a9..e661418 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,10 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
 use clippy_utils::{is_must_use_func_call, paths};
-use rustc_hir::{ExprKind, Local, PatKind};
+use rustc_hir::{Local, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::IsSuggestable;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{BytePos, Span};
 
@@ -138,7 +140,7 @@
 ];
 
 impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
-    fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
+    fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) {
         if !in_external_macro(cx.tcx.sess, local.span)
             && let PatKind::Wild = local.pat.kind
             && let Some(init) = local.init
@@ -191,15 +193,17 @@
             if local.pat.default_binding_modes && local.ty.is_none() {
                 // When `default_binding_modes` is true, the `let` keyword is present.
 
-				// Ignore function calls that return impl traits...
-				if let Some(init) = local.init &&
-				matches!(init.kind, ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _)) {
-					let expr_ty = cx.typeck_results().expr_ty(init);
-					if expr_ty.is_impl_trait() {
-						return;
-					}
-				}
+                // Ignore unnameable types
+                if let Some(init) = local.init
+                    && !cx.typeck_results().expr_ty(init).is_suggestable(cx.tcx, true)
+                {
+                    return;
+                }
 
+                // Ignore if it is from a procedural macro...
+                if is_from_proc_macro(cx, init) {
+                    return;
+                }
 
 				span_lint_and_help(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 3517842..b442a4a 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -266,6 +266,7 @@
 mod redundant_slicing;
 mod redundant_static_lifetimes;
 mod ref_option_ref;
+mod ref_patterns;
 mod reference;
 mod regex;
 mod return_self_not_must_use;
@@ -331,8 +332,11 @@
 mod zero_sized_map_values;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
-use crate::utils::conf::{format_error, TryConf};
 pub use crate::utils::conf::{lookup_conf_file, Conf};
+use crate::utils::{
+    conf::{format_error, metadata::get_configuration_metadata, TryConf},
+    FindAll,
+};
 
 /// Register all pre expansion lints
 ///
@@ -471,7 +475,22 @@
 pub fn explain(name: &str) {
     let target = format!("clippy::{}", name.to_ascii_uppercase());
     match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
-        Some(info) => print!("{}", info.explanation),
+        Some(info) => {
+            println!("{}", info.explanation);
+            // Check if the lint has configuration
+            let mdconf = get_configuration_metadata();
+            if let Some(config_vec_positions) = mdconf
+                .iter()
+                .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
+            {
+                // If it has, print it
+                println!("### Configuration for {}:\n", info.lint.name_lower());
+                for position in config_vec_positions {
+                    let conf = &mdconf[position];
+                    println!("  - {}: {} (default: {})", conf.name, conf.doc, conf.default);
+                }
+            }
+        },
         None => println!("unknown lint: {name}"),
     }
 }
@@ -971,6 +990,7 @@
     store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
     store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
     store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule));
+    store.register_early_pass(|| Box::new(ref_patterns::RefPatterns));
     store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index bba9bb4..09b2032 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -25,7 +25,7 @@
     ///
     /// ### Known problems
     /// This lint suggests replacing `filter_map()` or `flat_map()` applied to a `Lines`
-    /// instance in all cases. There two cases where the suggestion might not be
+    /// instance in all cases. There are two cases where the suggestion might not be
     /// appropriate or necessary:
     ///
     /// - If the `Lines` instance can never produce any error, or if an error is produced
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index 1247370..3f8b42f 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -38,7 +38,6 @@
     /// Could be written:
     ///
     /// ```rust
-    /// # #![feature(let_else)]
     /// # fn main () {
     /// # let w = Some(0);
     /// let Some(v) = w else { return };
@@ -69,29 +68,23 @@
 
 impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
     fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
-        let if_let_or_match = if_chain! {
-            if self.msrv.meets(msrvs::LET_ELSE);
-            if !in_external_macro(cx.sess(), stmt.span);
-            if let StmtKind::Local(local) = stmt.kind;
-            if let Some(init) = local.init;
-            if local.els.is_none();
-            if local.ty.is_none();
-            if init.span.ctxt() == stmt.span.ctxt();
-            if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init);
-            then {
-                if_let_or_match
-            } else {
-                return;
-            }
-        };
+        if !self.msrv.meets(msrvs::LET_ELSE) || in_external_macro(cx.sess(), stmt.span) {
+            return;
+        }
 
+        if let StmtKind::Local(local) = stmt.kind &&
+            let Some(init) = local.init &&
+            local.els.is_none() &&
+            local.ty.is_none() &&
+            init.span.ctxt() == stmt.span.ctxt() &&
+            let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) {
         match if_let_or_match {
             IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! {
                 if expr_is_simple_identity(let_pat, if_then);
                 if let Some(if_else) = if_else;
                 if expr_diverges(cx, if_else);
                 then {
-                    emit_manual_let_else(cx, stmt.span, if_let_expr, let_pat, if_else);
+                    emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else);
                 }
             },
             IfLetOrMatch::Match(match_expr, arms, source) => {
@@ -128,15 +121,23 @@
                     return;
                 }
 
-                emit_manual_let_else(cx, stmt.span, match_expr, pat_arm.pat, diverging_arm.body);
+                emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body);
             },
         }
+        };
     }
 
     extract_msrv_attr!(LateContext);
 }
 
-fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat: &Pat<'_>, else_body: &Expr<'_>) {
+fn emit_manual_let_else(
+    cx: &LateContext<'_>,
+    span: Span,
+    expr: &Expr<'_>,
+    local: &Pat<'_>,
+    pat: &Pat<'_>,
+    else_body: &Expr<'_>,
+) {
     span_lint_and_then(
         cx,
         MANUAL_LET_ELSE,
@@ -145,12 +146,11 @@
         |diag| {
             // This is far from perfect, for example there needs to be:
             // * mut additions for the bindings
-            // * renamings of the bindings
+            // * renamings of the bindings for `PatKind::Or`
             // * unused binding collision detection with existing ones
             // * putting patterns with at the top level | inside ()
             // for this to be machine applicable.
             let mut app = Applicability::HasPlaceholders;
-            let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
             let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app);
             let (sn_else, _) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app);
 
@@ -159,10 +159,21 @@
             } else {
                 format!("{{ {sn_else} }}")
             };
-            let sn_bl = if matches!(pat.kind, PatKind::Or(..)) {
-                format!("({sn_pat})")
-            } else {
-                sn_pat.into_owned()
+            let sn_bl = match pat.kind {
+                PatKind::Or(..) => {
+                    let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+                    format!("({sn_pat})")
+                },
+                // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
+                PatKind::TupleStruct(ref w, args, ..) if args.len() == 1 => {
+                    let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
+                    let (sn_inner, _) = snippet_with_context(cx, local.span, span.ctxt(), "", &mut app);
+                    format!("{sn_wrapper}({sn_inner})")
+                },
+                _ => {
+                    let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+                    sn_pat.into_owned()
+                },
             };
             let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
             diag.span_suggestion(span, "consider writing", sugg, app);
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 7d28c11..93d977a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -144,7 +144,7 @@
 
 // Returns the length of the `expr` if it's a constant string or char.
 fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
-    let (value, _) = constant(cx, cx.typeck_results(), expr)?;
+    let value = constant(cx, cx.typeck_results(), expr)?;
     match value {
         Constant::Str(value) => Some(value.len() as u128),
         Constant::Char(value) => Some(value.len_utf8() as u128),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 33bc20d..0064619 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -1,10 +1,12 @@
+use super::REDUNDANT_PATTERN_MATCHING;
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_lint_allowed;
 use clippy_utils::is_wild;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::span_contains_comment;
 use rustc_ast::{Attribute, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat};
+use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat, PatKind, QPath};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
 use rustc_span::source_map::Spanned;
@@ -99,6 +101,14 @@
                 }
             }
 
+            for arm in iter_without_last.clone() {
+                if let Some(pat) = arm.1 {
+                    if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) {
+                        return false;
+                    }
+                }
+            }
+
             // The suggestion may be incorrect, because some arms can have `cfg` attributes
             // evaluated into `false` and so such arms will be stripped before.
             let mut applicability = Applicability::MaybeIncorrect;
@@ -170,3 +180,13 @@
         _ => None,
     }
 }
+
+fn is_some(path_kind: PatKind<'_>) -> bool {
+    match path_kind {
+        PatKind::TupleStruct(QPath::Resolved(_, path), [first, ..], _) if is_wild(first) => {
+            let name = path.segments[0].ident;
+            name.name == rustc_span::sym::Some
+        },
+        _ => false,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index a48f4c7..ae8262a 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -282,9 +282,8 @@
                 // TODO: Handle negative integers. They're currently treated as a wild match.
                 ExprKind::Lit(lit) => match lit.node {
                     LitKind::Str(sym, _) => Self::LitStr(sym),
-                    LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
+                    LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Byte(val) => Self::LitInt(val.into()),
-                    LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Char(val) => Self::LitInt(val.into()),
                     LitKind::Int(val, _) => Self::LitInt(val),
                     LitKind::Bool(val) => Self::LitBool(val),
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 87b63ee..55ec9d4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -25,9 +25,9 @@
 
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet_opt, walk_span_to_context};
-use clippy_utils::{higher, in_constant, is_span_match};
+use clippy_utils::{higher, in_constant, is_span_match, tokenize_with_text};
 use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::TokenKind;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -1147,12 +1147,7 @@
         // Assume true. This would require either an invalid span, or one which crosses file boundaries.
         return true;
     };
-    let mut pos = 0usize;
-    let mut iter = tokenize(&snip).map(|t| {
-        let start = pos;
-        pos += t.len as usize;
-        (t.kind, start..pos)
-    });
+    let mut iter = tokenize_with_text(&snip);
 
     // Search for the token sequence [`#`, `[`, `cfg`]
     while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
@@ -1163,7 +1158,7 @@
             )
         });
         if matches!(iter.next(), Some((TokenKind::OpenBracket, _)))
-            && matches!(iter.next(), Some((TokenKind::Ident, range)) if &snip[range.clone()] == "cfg")
+            && matches!(iter.next(), Some((TokenKind::Ident, "cfg")))
         {
             return true;
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index ae69ca8..abf2525 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -34,7 +34,7 @@
             if let Arm { pat, guard: None, .. } = *arm {
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs_const = match lhs {
-                        Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
+                        Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
                         None => {
                             let min_val_const = ty.numeric_min_val(cx.tcx)?;
                             let min_constant = mir::ConstantKind::from_value(
@@ -45,7 +45,7 @@
                         },
                     };
                     let rhs_const = match rhs {
-                        Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
+                        Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
                         None => {
                             let max_val_const = ty.numeric_max_val(cx.tcx)?;
                             let max_constant = mir::ConstantKind::from_value(
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index af121f3..e81e09da 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -189,73 +189,7 @@
     if arms.len() == 2 {
         let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind);
 
-        let found_good_method = match node_pair {
-            (
-                PatKind::TupleStruct(ref path_left, patterns_left, _),
-                PatKind::TupleStruct(ref path_right, patterns_right, _),
-            ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
-                if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
-                    find_good_method_for_match(
-                        cx,
-                        arms,
-                        path_left,
-                        path_right,
-                        Item::Lang(ResultOk),
-                        Item::Lang(ResultErr),
-                        "is_ok()",
-                        "is_err()",
-                    )
-                    .or_else(|| {
-                        find_good_method_for_match(
-                            cx,
-                            arms,
-                            path_left,
-                            path_right,
-                            Item::Diag(sym::IpAddr, sym!(V4)),
-                            Item::Diag(sym::IpAddr, sym!(V6)),
-                            "is_ipv4()",
-                            "is_ipv6()",
-                        )
-                    })
-                } else {
-                    None
-                }
-            },
-            (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
-            | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
-                if patterns.len() == 1 =>
-            {
-                if let PatKind::Wild = patterns[0].kind {
-                    find_good_method_for_match(
-                        cx,
-                        arms,
-                        path_left,
-                        path_right,
-                        Item::Lang(OptionSome),
-                        Item::Lang(OptionNone),
-                        "is_some()",
-                        "is_none()",
-                    )
-                    .or_else(|| {
-                        find_good_method_for_match(
-                            cx,
-                            arms,
-                            path_left,
-                            path_right,
-                            Item::Lang(PollReady),
-                            Item::Lang(PollPending),
-                            "is_ready()",
-                            "is_pending()",
-                        )
-                    })
-                } else {
-                    None
-                }
-            },
-            _ => None,
-        };
-
-        if let Some(good_method) = found_good_method {
+        if let Some(good_method) = found_good_method(cx, arms, node_pair) {
             let span = expr.span.to(op.span);
             let result_expr = match &op.kind {
                 ExprKind::AddrOf(_, _, borrowed) => borrowed,
@@ -279,6 +213,127 @@
     }
 }
 
+fn found_good_method<'a>(
+    cx: &LateContext<'_>,
+    arms: &[Arm<'_>],
+    node: (&PatKind<'_>, &PatKind<'_>),
+) -> Option<&'a str> {
+    match node {
+        (
+            PatKind::TupleStruct(ref path_left, patterns_left, _),
+            PatKind::TupleStruct(ref path_right, patterns_right, _),
+        ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
+            if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
+                find_good_method_for_match(
+                    cx,
+                    arms,
+                    path_left,
+                    path_right,
+                    Item::Lang(ResultOk),
+                    Item::Lang(ResultErr),
+                    "is_ok()",
+                    "is_err()",
+                )
+                .or_else(|| {
+                    find_good_method_for_match(
+                        cx,
+                        arms,
+                        path_left,
+                        path_right,
+                        Item::Diag(sym::IpAddr, sym!(V4)),
+                        Item::Diag(sym::IpAddr, sym!(V6)),
+                        "is_ipv4()",
+                        "is_ipv6()",
+                    )
+                })
+            } else {
+                None
+            }
+        },
+        (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
+        | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
+            if patterns.len() == 1 =>
+        {
+            if let PatKind::Wild = patterns[0].kind {
+                find_good_method_for_match(
+                    cx,
+                    arms,
+                    path_left,
+                    path_right,
+                    Item::Lang(OptionSome),
+                    Item::Lang(OptionNone),
+                    "is_some()",
+                    "is_none()",
+                )
+                .or_else(|| {
+                    find_good_method_for_match(
+                        cx,
+                        arms,
+                        path_left,
+                        path_right,
+                        Item::Lang(PollReady),
+                        Item::Lang(PollPending),
+                        "is_ready()",
+                        "is_pending()",
+                    )
+                })
+            } else {
+                None
+            }
+        },
+        (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Wild) if patterns.len() == 1 => {
+            if let PatKind::Wild = patterns[0].kind {
+                get_good_method(cx, arms, path_left)
+            } else {
+                None
+            }
+        },
+        (PatKind::Path(ref path_left), PatKind::Wild) => get_good_method(cx, arms, path_left),
+        _ => None,
+    }
+}
+
+fn get_ident(path: &QPath<'_>) -> Option<rustc_span::symbol::Ident> {
+    match path {
+        QPath::Resolved(_, path) => {
+            let name = path.segments[0].ident;
+            Some(name)
+        },
+        _ => None,
+    }
+}
+
+fn get_good_method<'a>(cx: &LateContext<'_>, arms: &[Arm<'_>], path_left: &QPath<'_>) -> Option<&'a str> {
+    if let Some(name) = get_ident(path_left) {
+        return match name.as_str() {
+            "Ok" => {
+                find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultOk), "is_ok()", "is_err()")
+            },
+            "Err" => {
+                find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultErr), "is_err()", "is_ok()")
+            },
+            "Some" => find_good_method_for_matches_macro(
+                cx,
+                arms,
+                path_left,
+                Item::Lang(OptionSome),
+                "is_some()",
+                "is_none()",
+            ),
+            "None" => find_good_method_for_matches_macro(
+                cx,
+                arms,
+                path_left,
+                Item::Lang(OptionNone),
+                "is_none()",
+                "is_some()",
+            ),
+            _ => None,
+        };
+    }
+    None
+}
+
 #[derive(Clone, Copy)]
 enum Item {
     Lang(LangItem),
@@ -289,10 +344,11 @@
     let Some(id) = cx.typeck_results().qpath_res(path, pat.hir_id).opt_def_id() else { return false };
 
     match expected_item {
-        Item::Lang(expected_lang_item) => {
-            let expected_id = cx.tcx.lang_items().require(expected_lang_item).unwrap();
-            cx.tcx.parent(id) == expected_id
-        },
+        Item::Lang(expected_lang_item) => cx
+            .tcx
+            .lang_items()
+            .get(expected_lang_item)
+            .map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
         Item::Diag(expected_ty, expected_variant) => {
             let ty = cx.typeck_results().pat_ty(pat);
 
@@ -345,3 +401,29 @@
         _ => None,
     }
 }
+
+fn find_good_method_for_matches_macro<'a>(
+    cx: &LateContext<'_>,
+    arms: &[Arm<'_>],
+    path_left: &QPath<'_>,
+    expected_item_left: Item,
+    should_be_left: &'a str,
+    should_be_right: &'a str,
+) -> Option<&'a str> {
+    let first_pat = arms[0].pat;
+
+    let body_node_pair = if is_pat_variant(cx, first_pat, path_left, expected_item_left) {
+        (&arms[0].body.kind, &arms[1].body.kind)
+    } else {
+        return None;
+    };
+
+    match body_node_pair {
+        (ExprKind::Lit(lit_left), ExprKind::Lit(lit_right)) => match (&lit_left.node, &lit_right.node) {
+            (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
+            (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
+            _ => None,
+        },
+        _ => None,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
index c830958..d1609ee 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
@@ -13,7 +13,7 @@
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
     if_chain! {
         if is_trait_method(cx, expr, sym::Iterator);
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg);
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg);
         then {
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index 64c0921..b631cd0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -9,7 +9,7 @@
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
     if is_trait_method(cx, expr, sym::Iterator) {
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg) {
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) {
             span_lint(
                 cx,
                 ITERATOR_STEP_BY_ZERO,
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
new file mode 100644
index 0000000..5f3fec5
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::ty::implements_trait;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_span::symbol::sym;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'_>,
+    rev_call: &'tcx Expr<'_>,
+    rev_recv: &'tcx Expr<'_>,
+) {
+    let rev_recv_ty = cx.typeck_results().expr_ty(rev_recv);
+
+    // check that the receiver of `rev` implements `DoubleEndedIterator` and
+    // that `rev` and `next` come from `Iterator`
+    if cx
+        .tcx
+        .get_diagnostic_item(sym::DoubleEndedIterator)
+        .map_or(false, |double_ended_iterator| {
+            implements_trait(cx, rev_recv_ty, double_ended_iterator, &[])
+        })
+        && is_trait_method(cx, rev_call, sym::Iterator)
+        && is_trait_method(cx, expr, sym::Iterator)
+    {
+        span_lint_and_sugg(
+            cx,
+            super::MANUAL_NEXT_BACK,
+            expr.span.with_lo(rev_recv.span.hi()),
+            "manual backwards iteration",
+            "use",
+            String::from(".next_back()"),
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 06b88e3..9a594d9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -45,6 +45,7 @@
 mod iter_skip_next;
 mod iter_with_drain;
 mod iterator_step_by_zero;
+mod manual_next_back;
 mod manual_ok_or;
 mod manual_saturating_arithmetic;
 mod manual_str_repeat;
@@ -3132,8 +3133,11 @@
     /// ### Example
     /// ```rust
     /// # let iterator = vec![1].into_iter();
-    /// let len = iterator.clone().collect::<Vec<_>>().len();
-    /// // should be
+    /// let len = iterator.collect::<Vec<_>>().len();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let iterator = vec![1].into_iter();
     /// let len = iterator.count();
     /// ```
     #[clippy::version = "1.30.0"]
@@ -3193,6 +3197,29 @@
     "calling `drain` in order to `clear` a container"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `.rev().next()` on a `DoubleEndedIterator`
+    ///
+    /// ### Why is this bad?
+    /// `.next_back()` is cleaner.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let foo = [0; 10];
+    /// foo.iter().rev().next();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let foo = [0; 10];
+    /// foo.iter().next_back();
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub MANUAL_NEXT_BACK,
+    style,
+    "manual reverse iteration of `DoubleEndedIterator`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3321,6 +3348,7 @@
     NEEDLESS_COLLECT,
     SUSPICIOUS_COMMAND_ARG_SPACE,
     CLEAR_WITH_DRAIN,
+    MANUAL_NEXT_BACK,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3677,6 +3705,7 @@
                             ("iter", []) => iter_next_slice::check(cx, expr, recv2),
                             ("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg),
                             ("skip_while", [_]) => skip_while_next::check(cx, expr),
+                            ("rev", [])=> manual_next_back::check(cx, expr, recv, recv2),
                             _ => {},
                         }
                     }
@@ -3741,13 +3770,13 @@
                     unnecessary_sort_by::check(cx, expr, recv, arg, true);
                 },
                 ("splitn" | "rsplitn", [count_arg, pat_arg]) => {
-                    if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
                         suspicious_splitn::check(cx, name, expr, recv, count);
                         str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv);
                     }
                 },
                 ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
-                    if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
                         suspicious_splitn::check(cx, name, expr, recv, count);
                     }
                 },
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 0b0c6ad..6841aaf 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -1,6 +1,5 @@
 use super::NEEDLESS_COLLECT;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::higher;
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
@@ -8,6 +7,7 @@
     can_move_expr_to_closure, get_enclosing_block, get_parent_node, is_trait_method, path_to_local, path_to_local_id,
     CaptureKind,
 };
+use clippy_utils::{fn_def_id, higher};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
@@ -16,7 +16,7 @@
 };
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, AssocKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
+use rustc_middle::ty::{self, AssocKind, Clause, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol};
 
@@ -32,6 +32,8 @@
     if let Some(parent) = get_parent_node(cx.tcx, collect_expr.hir_id) {
         match parent {
             Node::Expr(parent) => {
+                check_collect_into_intoiterator(cx, parent, collect_expr, call_span, iter_expr);
+
                 if let ExprKind::MethodCall(name, _, args @ ([] | [_]), _) = parent.kind {
                     let mut app = Applicability::MachineApplicable;
                     let name = name.ident.as_str();
@@ -134,6 +136,68 @@
     }
 }
 
+/// checks for for collecting into a (generic) method or function argument
+/// taking an `IntoIterator`
+fn check_collect_into_intoiterator<'tcx>(
+    cx: &LateContext<'tcx>,
+    parent: &'tcx Expr<'tcx>,
+    collect_expr: &'tcx Expr<'tcx>,
+    call_span: Span,
+    iter_expr: &'tcx Expr<'tcx>,
+) {
+    if let Some(id) = fn_def_id(cx, parent) {
+        let args = match parent.kind {
+            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => args,
+            _ => &[],
+        };
+        // find the argument index of the `collect_expr` in the
+        // function / method call
+        if let Some(arg_idx) = args.iter().position(|e| e.hir_id == collect_expr.hir_id).map(|i| {
+            if matches!(parent.kind, ExprKind::MethodCall(_, _, _, _)) {
+                i + 1
+            } else {
+                i
+            }
+        }) {
+            // extract the input types of the function/method call
+            // that contains `collect_expr`
+            let inputs = cx
+                .tcx
+                .liberate_late_bound_regions(id, cx.tcx.fn_sig(id).subst_identity())
+                .inputs();
+
+            // map IntoIterator generic bounds to their signature
+            // types and check whether the argument type is an
+            // `IntoIterator`
+            if cx
+                .tcx
+                .param_env(id)
+                .caller_bounds()
+                .into_iter()
+                .filter_map(|p| {
+                    if let PredicateKind::Clause(Clause::Trait(t)) = p.kind().skip_binder()
+                            && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) {
+                                Some(t.self_ty())
+                            } else {
+                                None
+                            }
+                })
+                .any(|ty| ty == inputs[arg_idx])
+            {
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_COLLECT,
+                    call_span.with_lo(iter_expr.span.hi()),
+                    NEEDLESS_COLLECT_MSG,
+                    "remove this call",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
+
 /// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool`
 fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
     cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| {
diff --git a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
index a345ec8..bb4cdd2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_lang_item;
@@ -14,7 +14,7 @@
     recv: &'tcx Expr<'_>,
     repeat_arg: &'tcx Expr<'_>,
 ) {
-    if constant_context(cx, cx.typeck_results()).expr(repeat_arg) == Some(Constant::Int(1)) {
+    if constant(cx, cx.typeck_results(), repeat_arg) == Some(Constant::Int(1)) {
         let ty = cx.typeck_results().expr_ty(recv).peel_refs();
         if ty.is_str() {
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 91f7ce1..5ea12c4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -316,7 +316,7 @@
                     };
                 },
                 ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
-                    if let Some((Constant::Int(idx), _)) = constant(cx, cx.typeck_results(), idx_expr) {
+                    if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) {
                         let span = if name.ident.as_str() == "nth" {
                             e.span
                         } else {
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 3752b9a9..303f012 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -16,9 +16,12 @@
 
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+    get_parent_expr, in_constant, is_integer_literal, is_lint_allowed, is_no_std_crate, iter_input_pats,
+    last_path_segment, SpanlessEq,
 };
 
+use crate::ref_patterns::REF_PATTERNS;
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for function arguments and let bindings denoted as
@@ -162,6 +165,10 @@
             return;
         }
         for arg in iter_input_pats(decl, body) {
+            // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+            if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) {
+                return;
+            }
             if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind {
                 span_lint(
                     cx,
@@ -180,6 +187,8 @@
             if let StmtKind::Local(local) = stmt.kind;
             if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
             if let Some(init) = local.init;
+            // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+            if is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id);
             then {
                 let ctxt = local.span.ctxt();
                 let mut app = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index 71281a0..62af42a 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -146,7 +146,7 @@
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
-        if e.span.from_expansion() {
+        if e.span.from_expansion() || !span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty() {
             return;
         }
         if let Some(higher::If {
@@ -209,8 +209,7 @@
             }
             if let Some((lhs_a, a)) = fetch_assign(then) &&
                 let Some((lhs_b, b)) = fetch_assign(r#else) &&
-                SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b) &&
-                span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty()
+                SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b)
             {
                 let mut applicability = Applicability::MachineApplicable;
                 let cond = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index d29ca37..f486360 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -121,7 +121,7 @@
 fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
     let ty = cx.typeck_results().expr_ty(expr);
 
-    let cv = constant(cx, cx.typeck_results(), expr)?.0;
+    let cv = constant(cx, cx.typeck_results(), expr)?;
 
     let which = match (ty.kind(), cv) {
         (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum,
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index f725959..5c24027 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -21,7 +21,7 @@
     ["f64", "f64"],
     ["std::num::Saturating", "std::num::Saturating"],
     ["std::num::Wrapping", "std::num::Wrapping"],
-    ["std::string::String", "&str"],
+    ["std::string::String", "str"],
 ];
 const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
 const INTEGER_METHODS: &[&str] = &["saturating_div", "wrapping_div", "wrapping_rem", "wrapping_rem_euclid"];
@@ -113,7 +113,7 @@
         if let hir::ExprKind::Lit(lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
             return Some(n)
         }
-        if let Some((Constant::Int(n), _)) = constant(cx, cx.typeck_results(), expr) {
+        if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
             return Some(n);
         }
         None
@@ -144,8 +144,10 @@
         ) {
             return;
         };
-        let lhs_ty = cx.typeck_results().expr_ty(lhs);
-        let rhs_ty = cx.typeck_results().expr_ty(rhs);
+        let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
+        let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
+        let lhs_ty = cx.typeck_results().expr_ty(actual_lhs).peel_refs();
+        let rhs_ty = cx.typeck_results().expr_ty(actual_rhs).peel_refs();
         if self.has_allowed_binary(lhs_ty, rhs_ty) {
             return;
         }
@@ -154,8 +156,6 @@
                 // At least for integers, shifts are already handled by the CTFE
                 return;
             }
-            let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
-            let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
             match (
                 Self::literal_integer(cx, actual_lhs),
                 Self::literal_integer(cx, actual_rhs),
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 1369b3e..1fddf0f 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -166,7 +166,7 @@
 }
 
 fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option<u128> {
-    match constant(cx, cx.typeck_results(), lit)?.0 {
+    match constant(cx, cx.typeck_results(), lit)? {
         Constant::Int(n) => Some(n),
         _ => None,
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
index 786ae15..e18064b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
@@ -18,7 +18,7 @@
 }
 
 fn is_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), e) {
+    if let Some(value) = constant(cx, cx.typeck_results(), e) {
         match value {
             Constant::F32(num) => num.is_nan(),
             Constant::F64(num) => num.is_nan(),
diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
index 49e662c..f120be1 100644
--- a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
@@ -19,7 +19,7 @@
     if op == BinOpKind::Div
         && let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
         && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
-        && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right)
+        && let Some(Constant::Int(divisor)) = constant(cx, cx.typeck_results(), right)
     {
         let suggested_fn = match (method_path.ident.as_str(), divisor) {
             ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
index 97ddcdb..15dff12 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{constant_with_source, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::get_item_name;
 use clippy_utils::sugg::Sugg;
@@ -18,9 +18,16 @@
     right: &'tcx Expr<'_>,
 ) {
     if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
-        if is_allowed(cx, left) || is_allowed(cx, right) {
-            return;
-        }
+        let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) {
+            Some((c, s)) if !is_allowed(&c) => s.is_local(),
+            Some(_) => return,
+            None => true,
+        };
+        let right_is_local = match constant_with_source(cx, cx.typeck_results(), right) {
+            Some((c, s)) if !is_allowed(&c) => s.is_local(),
+            Some(_) => return,
+            None => true,
+        };
 
         // Allow comparing the results of signum()
         if is_signum(cx, left) && is_signum(cx, right) {
@@ -34,10 +41,7 @@
             }
         }
         let is_comparing_arrays = is_array(cx, left) || is_array(cx, right);
-        let (lint, msg) = get_lint_and_message(
-            is_named_constant(cx, left) || is_named_constant(cx, right),
-            is_comparing_arrays,
-        );
+        let (lint, msg) = get_lint_and_message(left_is_local && right_is_local, is_comparing_arrays);
         span_lint_and_then(cx, lint, expr.span, msg, |diag| {
             let lhs = Sugg::hir(cx, left, "..");
             let rhs = Sugg::hir(cx, right, "..");
@@ -59,20 +63,8 @@
     }
 }
 
-fn get_lint_and_message(
-    is_comparing_constants: bool,
-    is_comparing_arrays: bool,
-) -> (&'static rustc_lint::Lint, &'static str) {
-    if is_comparing_constants {
-        (
-            FLOAT_CMP_CONST,
-            if is_comparing_arrays {
-                "strict comparison of `f32` or `f64` constant arrays"
-            } else {
-                "strict comparison of `f32` or `f64` constant"
-            },
-        )
-    } else {
+fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static rustc_lint::Lint, &'static str) {
+    if is_local {
         (
             FLOAT_CMP,
             if is_comparing_arrays {
@@ -81,22 +73,23 @@
                 "strict comparison of `f32` or `f64`"
             },
         )
-    }
-}
-
-fn is_named_constant<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
-    if let Some((_, res)) = constant(cx, cx.typeck_results(), expr) {
-        res
     } else {
-        false
+        (
+            FLOAT_CMP_CONST,
+            if is_comparing_arrays {
+                "strict comparison of `f32` or `f64` constant arrays"
+            } else {
+                "strict comparison of `f32` or `f64` constant"
+            },
+        )
     }
 }
 
-fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
-    match constant(cx, cx.typeck_results(), expr) {
-        Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(),
-        Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(),
-        Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f {
+fn is_allowed(val: &Constant) -> bool {
+    match val {
+        &Constant::F32(f) => f == 0.0 || f.is_infinite(),
+        &Constant::F64(f) => f == 0.0 || f.is_infinite(),
+        Constant::Vec(vec) => vec.iter().all(|f| match f {
             Constant::F32(f) => *f == 0.0 || (*f).is_infinite(),
             Constant::F64(f) => *f == 0.0 || (*f).is_infinite(),
             _ => false,
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index 1959973..d63a836 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -98,32 +98,6 @@
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for integer arithmetic operations which could overflow or panic.
-    ///
-    /// Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable
-    /// of overflowing according to the [Rust
-    /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
-    /// or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is
-    /// attempted.
-    ///
-    /// ### Why is this bad?
-    /// Integer overflow will trigger a panic in debug builds or will wrap in
-    /// release mode. Division by zero will cause a panic in either mode. In some applications one
-    /// wants explicitly checked, wrapping or saturating arithmetic.
-    ///
-    /// ### Example
-    /// ```rust
-    /// # let a = 0;
-    /// a + 1;
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub INTEGER_ARITHMETIC,
-    restriction,
-    "any integer arithmetic expression which could overflow or panic"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for float arithmetic.
     ///
     /// ### Why is this bad?
@@ -787,7 +761,6 @@
 impl_lint_pass!(Operators => [
     ABSURD_EXTREME_COMPARISONS,
     ARITHMETIC_SIDE_EFFECTS,
-    INTEGER_ARITHMETIC,
     FLOAT_ARITHMETIC,
     ASSIGN_OP_PATTERN,
     MISREFACTORED_ASSIGN_OP,
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
index af4e749..a2c3a4d 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -40,7 +40,7 @@
 
 fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
     match constant(cx, cx.typeck_results(), operand) {
-        Some((Constant::Int(v), _)) => match *cx.typeck_results().expr_ty(expr).kind() {
+        Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
             ty::Int(ity) => {
                 let value = sext(cx.tcx, v, ity);
                 return Some(OperandInfo {
@@ -58,10 +58,10 @@
             },
             _ => {},
         },
-        Some((Constant::F32(f), _)) => {
+        Some(Constant::F32(f)) => {
             return Some(floating_point_operand_info(&f));
         },
-        Some((Constant::F64(f), _)) => {
+        Some(Constant::F64(f)) => {
             return Some(floating_point_operand_info(&f));
         },
         _ => {},
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 77fd45b..102845c 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -1,8 +1,6 @@
-use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC};
+use super::FLOAT_ARITHMETIC;
 use clippy_utils::consts::constant_simple;
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_from_proc_macro;
-use clippy_utils::is_integer_literal;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
@@ -45,31 +43,8 @@
             _ => (),
         }
 
-        let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
-        if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
-            if is_from_proc_macro(cx, expr) {
-                return;
-            }
-            match op {
-                hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
-                    hir::ExprKind::Lit(_lit) => (),
-                    hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
-                        if is_integer_literal(expr, 1) {
-                            span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                            self.expr_id = Some(expr.hir_id);
-                        }
-                    },
-                    _ => {
-                        span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                        self.expr_id = Some(expr.hir_id);
-                    },
-                },
-                _ => {
-                    span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                    self.expr_id = Some(expr.hir_id);
-                },
-            }
-        } else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
+        let (_, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
+        if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
             span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
             self.expr_id = Some(expr.hir_id);
         }
@@ -80,17 +55,9 @@
             return;
         }
         let ty = cx.typeck_results().expr_ty(arg);
-        if constant_simple(cx, cx.typeck_results(), expr).is_none() {
-            if ty.is_integral() {
-                if is_from_proc_macro(cx, expr) {
-                    return;
-                }
-                span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                self.expr_id = Some(expr.hir_id);
-            } else if ty.is_floating_point() {
-                span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
-                self.expr_id = Some(expr.hir_id);
-            }
+        if constant_simple(cx, cx.typeck_results(), expr).is_none() && ty.is_floating_point() {
+            span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
+            self.expr_id = Some(expr.hir_id);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index bbbcda0..aa6d400 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -122,7 +122,7 @@
         ExprKind::Unary(UnOp::Deref, inner_expr) | ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
         _ => expr,
     };
-    let inner_pat = try_get_inner_pat(cx, pat)?;
+    let (inner_pat, is_result) = try_get_inner_pat_and_is_result(cx, pat)?;
     if_chain! {
         if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind;
         if let Some(some_captures) = can_move_expr_to_closure(cx, if_then);
@@ -176,7 +176,7 @@
                 ),
                 none_expr: format!(
                     "{}{}",
-                    if method_sugg == "map_or" { "" } else { "|| " },
+                    if method_sugg == "map_or" { "" } else if is_result { "|_| " } else { "|| "},
                     Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
                 ),
             });
@@ -186,11 +186,13 @@
     None
 }
 
-fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'tcx>> {
+fn try_get_inner_pat_and_is_result<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<(&'tcx Pat<'tcx>, bool)> {
     if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind {
         let res = cx.qpath_res(qpath, pat.hir_id);
-        if is_res_lang_ctor(cx, res, OptionSome) || is_res_lang_ctor(cx, res, ResultOk) {
-            return Some(inner_pat);
+        if is_res_lang_ctor(cx, res, OptionSome) {
+            return Some((inner_pat, false));
+        } else if is_res_lang_ctor(cx, res, ResultOk) {
+            return Some((inner_pat, true));
         }
     }
     None
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index fc655fe..dd7ded4 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -319,7 +319,7 @@
             _ => return None,
         };
         if let Some(id) = path_to_local(l) {
-            if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {
+            if let Some(c) = constant(cx, cx.typeck_results(), r) {
                 return Some(RangeBounds {
                     val: c,
                     expr: r,
@@ -331,7 +331,7 @@
                 });
             }
         } else if let Some(id) = path_to_local(r) {
-            if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {
+            if let Some(c) = constant(cx, cx.typeck_results(), l) {
                 return Some(RangeBounds {
                     val: c,
                     expr: l,
@@ -451,8 +451,8 @@
         if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::Range::hir(expr);
         let ty = cx.typeck_results().expr_ty(start);
         if let ty::Int(_) | ty::Uint(_) = ty.kind();
-        if let Some((start_idx, _)) = constant(cx, cx.typeck_results(), start);
-        if let Some((end_idx, _)) = constant(cx, cx.typeck_results(), end);
+        if let Some(start_idx) = constant(cx, cx.typeck_results(), start);
+        if let Some(end_idx) = constant(cx, cx.typeck_results(), end);
         if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
         if is_empty_range(limits, ordering);
         then {
diff --git a/src/tools/clippy/clippy_lints/src/ref_patterns.rs b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
new file mode 100644
index 0000000..b1530ee
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
@@ -0,0 +1,44 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_ast::ast::{BindingAnnotation, Pat, PatKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usages of the `ref` keyword.
+    /// ### Why is this bad?
+    /// The `ref` keyword can be confusing for people unfamiliar with it, and often
+    /// it is more concise to use `&` instead.
+    /// ### Example
+    /// ```rust
+    /// let opt = Some(5);
+    /// if let Some(ref foo) = opt {}
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let opt = Some(5);
+    /// if let Some(foo) = &opt {}
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub REF_PATTERNS,
+    restriction,
+    "use of a ref pattern, e.g. Some(ref value)"
+}
+declare_lint_pass!(RefPatterns => [REF_PATTERNS]);
+
+impl EarlyLintPass for RefPatterns {
+    fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
+        if let PatKind::Ident(BindingAnnotation::REF, _, _) = pat.kind
+                && !pat.span.from_expansion()
+        {
+            span_lint_and_help(
+                cx,
+                REF_PATTERNS,
+                pat.span,
+                "usage of ref pattern",
+                None,
+                "consider using `&` for clarity instead",
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index b8b32df..ef19c6f 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -122,37 +122,39 @@
 }
 
 fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
-    constant(cx, cx.typeck_results(), e).and_then(|(c, _)| match c {
+    constant(cx, cx.typeck_results(), e).and_then(|c| match c {
         Constant::Str(s) => Some(s),
         _ => None,
     })
 }
 
 fn is_trivial_regex(s: &regex_syntax::hir::Hir) -> Option<&'static str> {
-    use regex_syntax::hir::Anchor::{EndText, StartText};
-    use regex_syntax::hir::HirKind::{Alternation, Anchor, Concat, Empty, Literal};
+    use regex_syntax::hir::HirKind::{Alternation, Concat, Empty, Literal, Look};
+    use regex_syntax::hir::Look as HirLook;
 
     let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| matches!(*e.kind(), Literal(_)));
 
     match *s.kind() {
-        Empty | Anchor(_) => Some("the regex is unlikely to be useful as it is"),
+        Empty | Look(_) => Some("the regex is unlikely to be useful as it is"),
         Literal(_) => Some("consider using `str::contains`"),
         Alternation(ref exprs) => {
-            if exprs.iter().all(|e| e.kind().is_empty()) {
+            if exprs.iter().all(|e| matches!(e.kind(), Empty)) {
                 Some("the regex is unlikely to be useful as it is")
             } else {
                 None
             }
         },
         Concat(ref exprs) => match (exprs[0].kind(), exprs[exprs.len() - 1].kind()) {
-            (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => {
+            (&Look(HirLook::Start), &Look(HirLook::End)) if exprs[1..(exprs.len() - 1)].is_empty() => {
                 Some("consider using `str::is_empty`")
             },
-            (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+            (&Look(HirLook::Start), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
                 Some("consider using `==` on `str`s")
             },
-            (&Anchor(StartText), &Literal(_)) if is_literal(&exprs[1..]) => Some("consider using `str::starts_with`"),
-            (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+            (&Look(HirLook::Start), &Literal(_)) if is_literal(&exprs[1..]) => {
+                Some("consider using `str::starts_with`")
+            },
+            (&Literal(_), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
                 Some("consider using `str::ends_with`")
             },
             _ if is_literal(exprs) => Some("consider using `str::contains`"),
@@ -175,10 +177,7 @@
 }
 
 fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
-    let mut parser = regex_syntax::ParserBuilder::new()
-        .unicode(true)
-        .allow_invalid_utf8(!utf8)
-        .build();
+    let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(!utf8).build();
 
     if let ExprKind::Lit(lit) = expr.kind {
         if let LitKind::Str(ref r, style) = lit.node {
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 52e22c0..b0db56b 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -15,6 +15,7 @@
     ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
     ("clippy::identity_conversion", "clippy::useless_conversion"),
     ("clippy::if_let_some_result", "clippy::match_result_ok"),
+    ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"),
     ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
     ("clippy::new_without_default_derive", "clippy::new_without_default"),
     ("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
@@ -32,13 +33,13 @@
     ("clippy::zero_width_space", "clippy::invisible_characters"),
     ("clippy::clone_double_ref", "suspicious_double_ref_op"),
     ("clippy::drop_bounds", "drop_bounds"),
-    ("clippy::drop_copy", "drop_copy"),
-    ("clippy::drop_ref", "drop_ref"),
+    ("clippy::drop_copy", "dropping_copy_types"),
+    ("clippy::drop_ref", "dropping_references"),
     ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
     ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
     ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
-    ("clippy::forget_copy", "forget_copy"),
-    ("clippy::forget_ref", "forget_ref"),
+    ("clippy::forget_copy", "forgetting_copy_types"),
+    ("clippy::forget_ref", "forgetting_references"),
     ("clippy::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 5b588e9..483f860 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -132,7 +132,7 @@
     /// Probably lots of false positives. If an index comes from a known valid position (e.g.
     /// obtained via `char_indices` over the same string), it is totally OK.
     ///
-    /// # Example
+    /// ### Example
     /// ```rust,should_panic
     /// &"Ölkanne"[1..];
     /// ```
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index b5f11b4..4ccda15 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -37,12 +37,12 @@
     #[clippy::version = "1.38.0"]
     pub TYPE_REPETITION_IN_BOUNDS,
     nursery,
-    "types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
+    "types are repeated unnecessarily in trait bounds, use `+` instead of using `T: _, T: _`"
 }
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for cases where generics are being used and multiple
+    /// Checks for cases where generics or trait objects are being used and multiple
     /// syntax specifications for trait bounds are used simultaneously.
     ///
     /// ### Why is this bad?
@@ -167,6 +167,61 @@
             }
         }
     }
+
+    fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
+        if_chain! {
+            if let TyKind::Ref(.., mut_ty) = &ty.kind;
+            if let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind;
+            if bounds.len() > 2;
+            then {
+
+                // Build up a hash of every trait we've seen
+                // When we see a trait for the first time, add it to unique_traits
+                // so we can later use it to build a string of all traits exactly once, without duplicates
+
+                let mut seen_def_ids = FxHashSet::default();
+                let mut unique_traits = Vec::new();
+
+                // Iterate the bounds and add them to our seen hash
+                // If we haven't yet seen it, add it to the fixed traits
+                for bound in bounds.iter() {
+                    let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; };
+
+                    let new_trait = seen_def_ids.insert(def_id);
+
+                    if new_trait {
+                        unique_traits.push(bound);
+                    }
+                }
+
+                // If the number of unique traits isn't the same as the number of traits in the bounds,
+                // there must be 1 or more duplicates
+                if bounds.len() != unique_traits.len() {
+                    let mut bounds_span = bounds[0].span;
+
+                    for bound in bounds.iter().skip(1) {
+                        bounds_span = bounds_span.to(bound.span);
+                    }
+
+                    let fixed_trait_snippet = unique_traits
+                        .iter()
+                        .filter_map(|b| snippet_opt(cx, b.span))
+                        .collect::<Vec<_>>()
+                        .join(" + ");
+
+                    span_lint_and_sugg(
+                        cx,
+                        TRAIT_DUPLICATION_IN_BOUNDS,
+                        bounds_span,
+                        "this trait bound is already specified in trait declaration",
+                        "try",
+                        fixed_trait_snippet,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+        }
+    }
 }
 
 impl TraitBounds {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
index e75d7f6..4944381 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
@@ -31,9 +31,7 @@
     match arg.kind {
         // Catching:
         // transmute over constants that resolve to `null`.
-        ExprKind::Path(ref _qpath)
-            if matches!(constant(cx, cx.typeck_results(), arg), Some((Constant::RawPtr(0), _))) =>
-        {
+        ExprKind::Path(ref _qpath) if matches!(constant(cx, cx.typeck_results(), arg), Some(Constant::RawPtr(0))) => {
             lint_expr(cx, expr);
             true
         },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index 1e407fc..770914e 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
 use rustc_hir::{Expr, ExprKind};
@@ -16,9 +16,8 @@
     }
 
     // Catching transmute over constants that resolve to `null`.
-    let mut const_eval_context = constant_context(cx, cx.typeck_results());
     if let ExprKind::Path(ref _qpath) = arg.kind &&
-        let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg)
+        let Some(Constant::RawPtr(0)) = constant(cx, cx.typeck_results(), arg)
     {
         span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
         return true;
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index ddbe6b2..28c3fc8 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::is_ty_alias;
 use clippy_utils::source::{snippet, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
@@ -138,6 +139,7 @@
                 if_chain! {
                     if let ExprKind::Path(ref qpath) = path.kind;
                     if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
+                    if !is_ty_alias(qpath);
                     then {
                         let a = cx.typeck_results().expr_ty(e);
                         let b = cx.typeck_results().expr_ty(arg);
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 935ea90..3c2bf5a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -308,7 +308,7 @@
                 bind!(self, vec);
                 kind!("CStr(ref {vec})");
                 chain!(self, "let [{:?}] = **{vec}", vec.value);
-            }
+            },
             LitKind::Str(s, _) => {
                 bind!(self, s);
                 kind!("Str({s}, _)");
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 5f05d97..f6de66b 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -174,16 +174,15 @@
             }
         }
 
-        #[cfg(feature = "internal")]
         pub mod metadata {
-            use crate::utils::internal_lints::metadata_collector::ClippyConfiguration;
+            use crate::utils::ClippyConfiguration;
 
             macro_rules! wrap_option {
                 () => (None);
                 ($x:literal) => (Some($x));
             }
 
-            pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
+            pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
                 vec![
                     $(
                         {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 3d0d4a5..7a1cd3e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -8,7 +8,11 @@
 //! a simple mistake)
 
 use crate::renamed_lints::RENAMED_LINTS;
-use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
+use crate::utils::{
+    collect_configs,
+    internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type},
+    ClippyConfiguration,
+};
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
@@ -520,111 +524,6 @@
     }
 }
 
-// ==================================================================
-// Configuration
-// ==================================================================
-#[derive(Debug, Clone, Default)]
-pub struct ClippyConfiguration {
-    name: String,
-    config_type: &'static str,
-    default: String,
-    lints: Vec<String>,
-    doc: String,
-    #[allow(dead_code)]
-    deprecation_reason: Option<&'static str>,
-}
-
-impl ClippyConfiguration {
-    pub fn new(
-        name: &'static str,
-        config_type: &'static str,
-        default: String,
-        doc_comment: &'static str,
-        deprecation_reason: Option<&'static str>,
-    ) -> Self {
-        let (lints, doc) = parse_config_field_doc(doc_comment)
-            .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
-
-        Self {
-            name: to_kebab(name),
-            lints,
-            doc,
-            config_type,
-            default,
-            deprecation_reason,
-        }
-    }
-
-    fn to_markdown_paragraph(&self) -> String {
-        format!(
-            "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
-            self.name,
-            self.doc
-                .lines()
-                .map(|line| line.strip_prefix("    ").unwrap_or(line))
-                .join("\n"),
-            self.default,
-            self.config_type,
-            self.lints
-                .iter()
-                .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
-                .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
-                .join("\n"),
-        )
-    }
-
-    fn to_markdown_table_entry(&self) -> String {
-        format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
-    }
-}
-
-fn collect_configs() -> Vec<ClippyConfiguration> {
-    crate::utils::conf::metadata::get_configuration_metadata()
-}
-
-/// This parses the field documentation of the config struct.
-///
-/// ```rust, ignore
-/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
-/// ```
-///
-/// Would yield:
-/// ```rust, ignore
-/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
-/// ```
-fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
-    const DOC_START: &str = " Lint: ";
-    if_chain! {
-        if doc_comment.starts_with(DOC_START);
-        if let Some(split_pos) = doc_comment.find('.');
-        then {
-            let mut doc_comment = doc_comment.to_string();
-            let mut documentation = doc_comment.split_off(split_pos);
-
-            // Extract lints
-            doc_comment.make_ascii_lowercase();
-            let lints: Vec<String> = doc_comment
-                .split_off(DOC_START.len())
-                .split(", ")
-                .map(str::to_string)
-                .collect();
-
-            // Format documentation correctly
-            // split off leading `.` from lint name list and indent for correct formatting
-            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
-
-            Some((lints, documentation))
-        } else {
-            None
-        }
-    }
-}
-
-/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
-fn to_kebab(config_name: &str) -> String {
-    config_name.replace('_', "-")
-}
-
 impl fmt::Display for ClippyConfiguration {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
         writeln!(
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index dc647af..d3ea7ca 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -4,3 +4,143 @@
 pub mod format_args_collector;
 #[cfg(feature = "internal")]
 pub mod internal_lints;
+#[cfg(feature = "internal")]
+use itertools::Itertools;
+
+/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
+fn to_kebab(config_name: &str) -> String {
+    config_name.replace('_', "-")
+}
+
+// ==================================================================
+// Configuration
+// ==================================================================
+#[derive(Debug, Clone, Default)] //~ ERROR no such field
+pub struct ClippyConfiguration {
+    pub name: String,
+    #[allow(dead_code)]
+    config_type: &'static str,
+    pub default: String,
+    pub lints: Vec<String>,
+    pub doc: String,
+    #[allow(dead_code)]
+    deprecation_reason: Option<&'static str>,
+}
+
+impl ClippyConfiguration {
+    pub fn new(
+        name: &'static str,
+        config_type: &'static str,
+        default: String,
+        doc_comment: &'static str,
+        deprecation_reason: Option<&'static str>,
+    ) -> Self {
+        let (lints, doc) = parse_config_field_doc(doc_comment)
+            .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
+
+        Self {
+            name: to_kebab(name),
+            lints,
+            doc,
+            config_type,
+            default,
+            deprecation_reason,
+        }
+    }
+
+    #[cfg(feature = "internal")]
+    fn to_markdown_paragraph(&self) -> String {
+        format!(
+            "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
+            self.name,
+            self.doc
+                .lines()
+                .map(|line| line.strip_prefix("    ").unwrap_or(line))
+                .join("\n"),
+            self.default,
+            self.config_type,
+            self.lints
+                .iter()
+                .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
+                .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
+                .join("\n"),
+        )
+    }
+
+    #[cfg(feature = "internal")]
+    fn to_markdown_table_entry(&self) -> String {
+        format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
+    }
+}
+
+#[cfg(feature = "internal")]
+fn collect_configs() -> Vec<ClippyConfiguration> {
+    crate::utils::conf::metadata::get_configuration_metadata()
+}
+
+/// This parses the field documentation of the config struct.
+///
+/// ```rust, ignore
+/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
+/// ```
+///
+/// Would yield:
+/// ```rust, ignore
+/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
+/// ```
+fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
+    const DOC_START: &str = " Lint: ";
+    if_chain! {
+        if doc_comment.starts_with(DOC_START);
+        if let Some(split_pos) = doc_comment.find('.');
+        then {
+            let mut doc_comment = doc_comment.to_string();
+            let mut documentation = doc_comment.split_off(split_pos);
+
+            // Extract lints
+            doc_comment.make_ascii_lowercase();
+            let lints: Vec<String> = doc_comment
+                .split_off(DOC_START.len())
+                .split(", ")
+                .map(str::to_string)
+                .collect();
+
+            // Format documentation correctly
+            // split off leading `.` from lint name list and indent for correct formatting
+            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
+
+            Some((lints, documentation))
+        } else {
+            None
+        }
+    }
+}
+
+// Shamelessly stolen from find_all (https://github.com/nectariner/find_all)
+pub trait FindAll: Iterator + Sized {
+    fn find_all<P>(&mut self, predicate: P) -> Option<Vec<usize>>
+    where
+        P: FnMut(&Self::Item) -> bool;
+}
+
+impl<I> FindAll for I
+where
+    I: Iterator,
+{
+    fn find_all<P>(&mut self, mut predicate: P) -> Option<Vec<usize>>
+    where
+        P: FnMut(&Self::Item) -> bool,
+    {
+        let mut occurences = Vec::<usize>::default();
+        for (index, element) in self.enumerate() {
+            if predicate(&element) {
+                occurences.push(index);
+            }
+        }
+
+        match occurences.len() {
+            0 => None,
+            _ => Some(occurences),
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 297a80e..7329e50 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -84,7 +84,7 @@
         let mut applicability = Applicability::MachineApplicable;
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
-                if let Some((Constant::Int(len_constant), _)) = constant(cx, cx.typeck_results(), len) {
+                if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
                     #[expect(clippy::cast_possible_truncation)]
                     if len_constant as u64 * size_of(cx, elem) > self.too_large_for_stack {
                         return;
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 36f910c..a9089fb 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -7,7 +7,7 @@
     def::{DefKind, Res},
     Item, ItemKind, PathSegment, UseKind,
 };
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::kw;
@@ -117,6 +117,10 @@
 
 impl LateLintPass<'_> for WildcardImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if cx.sess().is_test_crate() {
+            return;
+        }
+
         if is_test_module_or_function(cx.tcx, item) {
             self.test_modules_deep = self.test_modules_deep.saturating_add(1);
         }
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 8075881..fb77264 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -1,18 +1,21 @@
 #![allow(clippy::float_cmp)]
 
+use crate::source::{get_source_text, walk_span_to_context};
 use crate::{clip, is_direct_expn_of, sext, unsext};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{List, SubstsRef};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
+use rustc_span::SyntaxContext;
 use std::cmp::Ordering::{self, Equal};
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -210,8 +213,7 @@
     match *lit {
         LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
         LitKind::Byte(b) => Constant::Int(u128::from(b)),
-        LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
-        LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
+        LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
         LitKind::Char(c) => Constant::Char(c),
         LitKind::Int(n, _) => Constant::Int(n),
         LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
@@ -228,27 +230,46 @@
     }
 }
 
+/// The source of a constant value.
+pub enum ConstantSource {
+    /// The value is determined solely from the expression.
+    Local,
+    /// The value is dependent on a defined constant.
+    Constant,
+}
+impl ConstantSource {
+    pub fn is_local(&self) -> bool {
+        matches!(self, Self::Local)
+    }
+}
+
+/// Attempts to evaluate the expression as a constant.
 pub fn constant<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<(Constant, bool)> {
-    let mut cx = ConstEvalLateContext {
-        lcx,
-        typeck_results,
-        param_env: lcx.param_env,
-        needed_resolution: false,
-        substs: ty::List::empty(),
-    };
-    cx.expr(e).map(|cst| (cst, cx.needed_resolution))
+) -> Option<Constant> {
+    ConstEvalLateContext::new(lcx, typeck_results).expr(e)
 }
 
+/// Attempts to evaluate the expression as a constant.
+pub fn constant_with_source<'tcx>(
+    lcx: &LateContext<'tcx>,
+    typeck_results: &ty::TypeckResults<'tcx>,
+    e: &Expr<'_>,
+) -> Option<(Constant, ConstantSource)> {
+    let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
+    let res = ctxt.expr(e);
+    res.map(|x| (x, ctxt.source))
+}
+
+/// Attempts to evaluate an expression only if it's value is not dependent on other items.
 pub fn constant_simple<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
 ) -> Option<Constant> {
-    constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
+    constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
 }
 
 pub fn constant_full_int<'tcx>(
@@ -297,29 +318,25 @@
     }
 }
 
-/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
-pub fn constant_context<'a, 'tcx>(
-    lcx: &'a LateContext<'tcx>,
-    typeck_results: &'a ty::TypeckResults<'tcx>,
-) -> ConstEvalLateContext<'a, 'tcx> {
-    ConstEvalLateContext {
-        lcx,
-        typeck_results,
-        param_env: lcx.param_env,
-        needed_resolution: false,
-        substs: ty::List::empty(),
-    }
-}
-
 pub struct ConstEvalLateContext<'a, 'tcx> {
     lcx: &'a LateContext<'tcx>,
     typeck_results: &'a ty::TypeckResults<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    needed_resolution: bool,
+    source: ConstantSource,
     substs: SubstsRef<'tcx>,
 }
 
 impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
+    fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
+        Self {
+            lcx,
+            typeck_results,
+            param_env: lcx.param_env,
+            source: ConstantSource::Local,
+            substs: List::empty(),
+        }
+    }
+
     /// Simple constant folding: Insert an expression, get a constant or none.
     pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
         match e.kind {
@@ -454,11 +471,9 @@
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None)
                     .ok()
                     .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
-                let result = miri_to_const(self.lcx.tcx, result);
-                if result.is_some() {
-                    self.needed_resolution = true;
-                }
-                result
+                let result = miri_to_const(self.lcx.tcx, result)?;
+                self.source = ConstantSource::Constant;
+                Some(result)
             },
             // FIXME: cover all usable cases.
             _ => None,
@@ -492,8 +507,33 @@
 
     /// A block can only yield a constant if it only has one constant expression.
     fn block(&mut self, block: &Block<'_>) -> Option<Constant> {
-        if block.stmts.is_empty() {
-            block.expr.as_ref().and_then(|b| self.expr(b))
+        if block.stmts.is_empty()
+            && let Some(expr) = block.expr
+        {
+            // Try to detect any `cfg`ed statements or empty macro expansions.
+            let span = block.span.data();
+            if span.ctxt == SyntaxContext::root() {
+                if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
+                    && let expr_lo = expr_span.lo()
+                    && expr_lo >= span.lo
+                    && let Some(src) = get_source_text(self.lcx, span.lo..expr_lo)
+                    && let Some(src) = src.as_str()
+                {
+                    use rustc_lexer::TokenKind::{Whitespace, LineComment, BlockComment, Semi, OpenBrace};
+                    if !tokenize(src)
+                        .map(|t| t.kind)
+                        .filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
+                        .eq([OpenBrace])
+                    {
+                        self.source = ConstantSource::Constant;
+                    }
+                } else {
+                    // Unable to access the source. Assume a non-local dependency.
+                    self.source = ConstantSource::Constant;
+                }
+            }
+
+            self.expr(expr)
         } else {
             None
         }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 9b7408d..a49246a 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1,6 +1,7 @@
 use crate::consts::constant_simple;
 use crate::macros::macro_backtrace;
-use crate::source::snippet_opt;
+use crate::source::{get_source_text, snippet_opt, walk_span_to_context, SpanRange};
+use crate::tokenize_with_text;
 use rustc_ast::ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxHasher;
 use rustc_hir::def::Res;
@@ -13,8 +14,9 @@
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::TypeckResults;
-use rustc_span::{sym, Symbol};
+use rustc_span::{sym, BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext};
 use std::hash::{Hash, Hasher};
+use std::ops::Range;
 
 /// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but
 /// other conditions would make them equal.
@@ -65,6 +67,8 @@
     pub fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> {
         HirEqInterExpr {
             inner: self,
+            left_ctxt: SyntaxContext::root(),
+            right_ctxt: SyntaxContext::root(),
             locals: HirIdMap::default(),
         }
     }
@@ -92,6 +96,8 @@
 
 pub struct HirEqInterExpr<'a, 'b, 'tcx> {
     inner: &'a mut SpanlessEq<'b, 'tcx>,
+    left_ctxt: SyntaxContext,
+    right_ctxt: SyntaxContext,
 
     // When binding are declared, the binding ID in the left expression is mapped to the one on the
     // right. For example, when comparing `{ let x = 1; x + 2 }` and `{ let y = 1; y + 2 }`,
@@ -126,52 +132,88 @@
     }
 
     /// Checks whether two blocks are the same.
+    #[expect(clippy::similar_names)]
     fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
-        match (left.stmts, left.expr, right.stmts, right.expr) {
-            ([], None, [], None) => {
-                // For empty blocks, check to see if the tokens are equal. This will catch the case where a macro
-                // expanded to nothing, or the cfg attribute was used.
-                let (Some(left), Some(right)) = (
-                    snippet_opt(self.inner.cx, left.span),
-                    snippet_opt(self.inner.cx, right.span),
-                ) else { return true };
-                let mut left_pos = 0;
-                let left = tokenize(&left)
-                    .map(|t| {
-                        let end = left_pos + t.len as usize;
-                        let s = &left[left_pos..end];
-                        left_pos = end;
-                        (t, s)
-                    })
-                    .filter(|(t, _)| {
-                        !matches!(
-                            t.kind,
-                            TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
-                        )
-                    })
-                    .map(|(_, s)| s);
-                let mut right_pos = 0;
-                let right = tokenize(&right)
-                    .map(|t| {
-                        let end = right_pos + t.len as usize;
-                        let s = &right[right_pos..end];
-                        right_pos = end;
-                        (t, s)
-                    })
-                    .filter(|(t, _)| {
-                        !matches!(
-                            t.kind,
-                            TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
-                        )
-                    })
-                    .map(|(_, s)| s);
-                left.eq(right)
-            },
-            _ => {
-                over(left.stmts, right.stmts, |l, r| self.eq_stmt(l, r))
-                    && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
-            },
+        use TokenKind::{BlockComment, LineComment, Semi, Whitespace};
+        if left.stmts.len() != right.stmts.len() {
+            return false;
         }
+        let lspan = left.span.data();
+        let rspan = right.span.data();
+        if lspan.ctxt != SyntaxContext::root() && rspan.ctxt != SyntaxContext::root() {
+            // Don't try to check in between statements inside macros.
+            return over(left.stmts, right.stmts, |left, right| self.eq_stmt(left, right))
+                && both(&left.expr, &right.expr, |left, right| self.eq_expr(left, right));
+        }
+        if lspan.ctxt != rspan.ctxt {
+            return false;
+        }
+
+        let mut lstart = lspan.lo;
+        let mut rstart = rspan.lo;
+
+        for (left, right) in left.stmts.iter().zip(right.stmts) {
+            if !self.eq_stmt(left, right) {
+                return false;
+            }
+
+            // Try to detect any `cfg`ed statements or empty macro expansions.
+            let Some(lstmt_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+                return false;
+            };
+            let Some(rstmt_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+                return false;
+            };
+            let lstmt_span = lstmt_span.data();
+            let rstmt_span = rstmt_span.data();
+
+            if lstmt_span.lo < lstart && rstmt_span.lo < rstart {
+                // Can happen when macros expand to multiple statements, or rearrange statements.
+                // Nothing in between the statements to check in this case.
+                continue;
+            }
+            if lstmt_span.lo < lstart || rstmt_span.lo < rstart {
+                // Only one of the blocks had a weird macro.
+                return false;
+            }
+            if !eq_span_tokens(self.inner.cx, lstart..lstmt_span.lo, rstart..rstmt_span.lo, |t| {
+                !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+            }) {
+                return false;
+            }
+
+            lstart = lstmt_span.hi;
+            rstart = rstmt_span.hi;
+        }
+
+        let (lend, rend) = match (left.expr, right.expr) {
+            (Some(left), Some(right)) => {
+                if !self.eq_expr(left, right) {
+                    return false;
+                }
+                let Some(lexpr_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+                    return false;
+                };
+                let Some(rexpr_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+                    return false;
+                };
+                (lexpr_span.lo(), rexpr_span.lo())
+            },
+            (None, None) => (lspan.hi, rspan.hi),
+            (Some(_), None) | (None, Some(_)) => return false,
+        };
+
+        if lend < lstart && rend < rstart {
+            // Can happen when macros rearrange the input.
+            // Nothing in between the statements to check in this case.
+            return true;
+        } else if lend < lstart || rend < rstart {
+            // Only one of the blocks had a weird macro
+            return false;
+        }
+        eq_span_tokens(self.inner.cx, lstart..lend, rstart..rend, |t| {
+            !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+        })
     }
 
     fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
@@ -207,7 +249,7 @@
 
     #[expect(clippy::similar_names)]
     pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
-        if !self.inner.allow_side_effects && left.span.ctxt() != right.span.ctxt() {
+        if !self.check_ctxt(left.span.ctxt(), right.span.ctxt()) {
             return false;
         }
 
@@ -440,6 +482,45 @@
     fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool {
         left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty())
     }
+
+    fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {
+        if self.left_ctxt == left && self.right_ctxt == right {
+            return true;
+        } else if self.left_ctxt == left || self.right_ctxt == right {
+            // Only one context has changed. This can only happen if the two nodes are written differently.
+            return false;
+        } else if left != SyntaxContext::root() {
+            let mut left_data = left.outer_expn_data();
+            let mut right_data = right.outer_expn_data();
+            loop {
+                use TokenKind::{BlockComment, LineComment, Whitespace};
+                if left_data.macro_def_id != right_data.macro_def_id
+                    || (matches!(left_data.kind, ExpnKind::Macro(MacroKind::Bang, name) if name == sym::cfg)
+                        && !eq_span_tokens(self.inner.cx, left_data.call_site, right_data.call_site, |t| {
+                            !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. })
+                        }))
+                {
+                    // Either a different chain of macro calls, or different arguments to the `cfg` macro.
+                    return false;
+                }
+                let left_ctxt = left_data.call_site.ctxt();
+                let right_ctxt = right_data.call_site.ctxt();
+                if left_ctxt == SyntaxContext::root() && right_ctxt == SyntaxContext::root() {
+                    break;
+                }
+                if left_ctxt == SyntaxContext::root() || right_ctxt == SyntaxContext::root() {
+                    // Different lengths for the expansion stack. This can only happen if nodes are written differently,
+                    // or shouldn't be compared to start with.
+                    return false;
+                }
+                left_data = left_ctxt.outer_expn_data();
+                right_data = right_ctxt.outer_expn_data();
+            }
+        }
+        self.left_ctxt = left;
+        self.right_ctxt = right;
+        true
+    }
 }
 
 /// Some simple reductions like `{ return }` => `return`
@@ -1038,3 +1119,34 @@
     h.hash_expr(e);
     h.finish()
 }
+
+#[expect(clippy::similar_names)]
+fn eq_span_tokens(
+    cx: &LateContext<'_>,
+    left: impl SpanRange,
+    right: impl SpanRange,
+    pred: impl Fn(TokenKind) -> bool,
+) -> bool {
+    fn f(cx: &LateContext<'_>, left: Range<BytePos>, right: Range<BytePos>, pred: impl Fn(TokenKind) -> bool) -> bool {
+        if let Some(lsrc) = get_source_text(cx, left)
+            && let Some(lsrc) = lsrc.as_str()
+            && let Some(rsrc) = get_source_text(cx, right)
+            && let Some(rsrc) = rsrc.as_str()
+        {
+            let pred = |t: &(_, _)| pred(t.0);
+            let map = |(_, x)| x;
+
+            let ltok = tokenize_with_text(lsrc)
+                .filter(pred)
+                .map(map);
+            let rtok = tokenize_with_text(rsrc)
+                .filter(pred)
+                .map(map);
+            ltok.eq(rtok)
+        } else {
+            // Unable to access the source. Conservatively assume the blocks aren't equal.
+            false
+        }
+    }
+    f(cx, left.into_range(), right.into_range(), pred)
+}
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 964104f..575c29a 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,5 +1,6 @@
 #![feature(array_chunks)]
 #![feature(box_patterns)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
 #![feature(never_type)]
@@ -76,6 +77,7 @@
 use std::sync::{Mutex, MutexGuard};
 
 use if_chain::if_chain;
+use itertools::Itertools;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
@@ -282,6 +284,15 @@
     matches!(pat.kind, PatKind::Wild)
 }
 
+/// Checks if the given `QPath` belongs to a type alias.
+pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
+    match *qpath {
+        QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias, ..)),
+        QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) },
+        _ => false,
+    }
+}
+
 /// Checks if the method call given in `expr` belongs to the given trait.
 /// This is a deprecated function, consider using [`is_trait_method`].
 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
@@ -1488,7 +1499,7 @@
                 && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
                 && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
                 && let Some(min_const) = miri_to_const(cx.tcx, min_const_kind)
-                && let Some((start_const, _)) = constant(cx, cx.typeck_results(), start)
+                && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
             } else {
@@ -1504,7 +1515,7 @@
                         && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
                         && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
                         && let Some(max_const) = miri_to_const(cx.tcx, max_const_kind)
-                        && let Some((end_const, _)) = constant(cx, cx.typeck_results(), end)
+                        && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                     {
                         end_const == max_const
                     } else {
@@ -1536,7 +1547,7 @@
         return true;
     }
     let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
-    if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
+    if let Some(Constant::Int(v)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
         return value == v;
     }
     false
@@ -2480,6 +2491,17 @@
     None
 }
 
+/// Tokenizes the input while keeping the text associated with each token.
+pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str)> {
+    let mut pos = 0;
+    tokenize(s).map(move |t| {
+        let end = pos + t.len;
+        let range = pos as usize..end as usize;
+        pos = end;
+        (t.kind, s.get(range).unwrap_or_default())
+    })
+}
+
 /// Checks whether a given span has any comment token
 /// This checks for all types of comment: line "//", block "/**", doc "///" "//!"
 pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
@@ -2496,23 +2518,11 @@
 /// Comments are returned wrapped with their relevant delimiters
 pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
     let snippet = sm.span_to_snippet(span).unwrap_or_default();
-    let mut comments_buf: Vec<String> = Vec::new();
-    let mut index: usize = 0;
-
-    for token in tokenize(&snippet) {
-        let token_range = index..(index + token.len as usize);
-        index += token.len as usize;
-        match token.kind {
-            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => {
-                if let Some(comment) = snippet.get(token_range) {
-                    comments_buf.push(comment.to_string());
-                }
-            },
-            _ => (),
-        }
-    }
-
-    comments_buf.join("\n")
+    let res = tokenize_with_text(&snippet)
+        .filter(|(t, _)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
+        .map(|(_, s)| s)
+        .join("\n");
+    res
 }
 
 pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 62fa376..0f60290 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -2,14 +2,64 @@
 
 #![allow(clippy::module_name_repetitions)]
 
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_session::Session;
-use rustc_span::hygiene;
 use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::{hygiene, SourceFile};
 use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
 use std::borrow::Cow;
+use std::ops::Range;
+
+/// A type which can be converted to the range portion of a `Span`.
+pub trait SpanRange {
+    fn into_range(self) -> Range<BytePos>;
+}
+impl SpanRange for Span {
+    fn into_range(self) -> Range<BytePos> {
+        let data = self.data();
+        data.lo..data.hi
+    }
+}
+impl SpanRange for SpanData {
+    fn into_range(self) -> Range<BytePos> {
+        self.lo..self.hi
+    }
+}
+impl SpanRange for Range<BytePos> {
+    fn into_range(self) -> Range<BytePos> {
+        self
+    }
+}
+
+pub struct SourceFileRange {
+    pub sf: Lrc<SourceFile>,
+    pub range: Range<usize>,
+}
+impl SourceFileRange {
+    /// Attempts to get the text from the source file. This can fail if the source text isn't
+    /// loaded.
+    pub fn as_str(&self) -> Option<&str> {
+        self.sf.src.as_ref().and_then(|x| x.get(self.range.clone()))
+    }
+}
+
+/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
+/// extends through multiple files, or is malformed.
+pub fn get_source_text(cx: &impl LintContext, sp: impl SpanRange) -> Option<SourceFileRange> {
+    fn f(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
+        let start = sm.lookup_byte_offset(sp.start);
+        let end = sm.lookup_byte_offset(sp.end);
+        if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos {
+            return None;
+        }
+        let range = start.pos.to_usize()..end.pos.to_usize();
+        Some(SourceFileRange { sf: start.sf, range })
+    }
+    f(cx.sess().source_map(), sp.into_range())
+}
 
 /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
 pub fn expr_block<T: LintContext>(
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 60b8a5a..bc7fb71 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-05-05"
+channel = "nightly-2023-05-20"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
index acb98d7..99ce702 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -3,6 +3,7 @@
 //@normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
 //@normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
 //@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
+//@normalize-stderr-test: "running on .*" -> "running on <target>"
 //@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
 
 #![deny(clippy::internal)]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index b4619e9..0fc385c 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,12 +1,14 @@
 thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
-error: internal compiler error: unexpected panic
-
-note: the compiler unexpectedly panicked. this is a bug.
+error: the compiler unexpectedly panicked. this is a bug.
 
 note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new
 
+note: rustc 1.71.0-nightly (521f4dae1 2023-05-19) running on <target>
+
+note: compiler flags: -C prefer-dynamic -Z ui-testing
+
 note: Clippy version: foo
 
 thread panicked while panicking. aborting.
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index ab408bd..f95af10 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -458,4 +458,12 @@
     10 / a
 }
 
+pub fn issue_10767() {
+    let n = &1.0;
+    n + n;
+    3.1_f32 + &1.2_f32;
+    &3.4_f32 + 1.5_f32;
+    &3.5_f32 + &1.3_f32;
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
index 165e4bc..7552646 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
@@ -1,7 +1,11 @@
 //@run-rustfix
+//@aux-build: proc_macros.rs
 
 #![allow(dead_code, unused_variables)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn main() {}
 
 mod should_lint {
@@ -47,6 +51,17 @@
     }
 }
 
+with_span!(
+    span
+
+    fn just_returning(x: &u32) -> &u32 {
+        x
+    }
+
+    fn dont_lint_proc_macro() {
+        let a = &mut &*just_returning(&12);
+    }
+);
 // this mod explains why we should not lint `& &* (&T)`
 mod false_negative {
     fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
index 66c8d69..e319d36 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
@@ -1,7 +1,11 @@
 //@run-rustfix
+//@aux-build: proc_macros.rs
 
 #![allow(dead_code, unused_variables)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn main() {}
 
 mod should_lint {
@@ -47,6 +51,17 @@
     }
 }
 
+with_span!(
+    span
+
+    fn just_returning(x: &u32) -> &u32 {
+        x
+    }
+
+    fn dont_lint_proc_macro() {
+        let a = &mut &*just_returning(&12);
+    }
+);
 // this mod explains why we should not lint `& &* (&T)`
 mod false_negative {
     fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
index d72de37..1e47cda 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
@@ -1,5 +1,5 @@
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:10:17
+  --> $DIR/borrow_deref_ref.rs:14:17
    |
 LL |         let b = &*a;
    |                 ^^^ help: if you would like to reborrow, try removing `&*`: `a`
@@ -7,13 +7,13 @@
    = note: `-D clippy::borrow-deref-ref` implied by `-D warnings`
 
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:12:22
+  --> $DIR/borrow_deref_ref.rs:16:22
    |
 LL |         let b = &mut &*bar(&12);
    |                      ^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `bar(&12)`
 
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:55:23
+  --> $DIR/borrow_deref_ref.rs:70:23
    |
 LL |         let addr_y = &&*x as *const _ as usize; // assert ok
    |                       ^^^ help: if you would like to reborrow, try removing `&*`: `x`
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index e633129..840902b 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -35,6 +35,13 @@
     let _more = ret_ty_fn();
     call_ty_fn(Box::default());
     issue_10381();
+
+    // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+    // `Box::<Option<[closure@...]>::default()`
+    //
+    // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+    let mut unnameable = Box::new(Option::default());
+    let _ = unnameable.insert(|| {});
 }
 
 fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index 34a05a2..3618486 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -35,6 +35,13 @@
     let _more = ret_ty_fn();
     call_ty_fn(Box::new(u8::default()));
     issue_10381();
+
+    // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+    // `Box::<Option<[closure@...]>::default()`
+    //
+    // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+    let mut unnameable = Box::new(Option::default());
+    let _ = unnameable.insert(|| {});
 }
 
 fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index c983486..13dfc5a 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -73,25 +73,25 @@
    |                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:41:5
+  --> $DIR/box_default.rs:48:5
    |
 LL |     Box::new(bool::default())
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:58:28
+  --> $DIR/box_default.rs:65:28
    |
 LL |     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:67:17
+  --> $DIR/box_default.rs:74:17
    |
 LL |         let _ = Box::new(WeirdPathed::default());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:79:18
+  --> $DIR/box_default.rs:86:18
    |
 LL |             Some(Box::new(Foo::default()))
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index d2aba2a..c6514a5 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(
+    clippy::assertions_on_constants,
+    clippy::equatable_if_let,
+    clippy::nonminimal_bool,
+    clippy::eq_op
+)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index e0bef7f..2c85b68 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(
+    clippy::assertions_on_constants,
+    clippy::equatable_if_let,
+    clippy::nonminimal_bool,
+    clippy::eq_op
+)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index 6327444..c687bae 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -1,5 +1,5 @@
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:9:5
+  --> $DIR/collapsible_if.rs:14:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" {
@@ -17,7 +17,7 @@
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:15:5
+  --> $DIR/collapsible_if.rs:20:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -34,7 +34,7 @@
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:21:5
+  --> $DIR/collapsible_if.rs:26:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -51,7 +51,7 @@
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:27:5
+  --> $DIR/collapsible_if.rs:32:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -68,7 +68,7 @@
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:33:5
+  --> $DIR/collapsible_if.rs:38:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -85,7 +85,7 @@
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:39:5
+  --> $DIR/collapsible_if.rs:44:5
    |
 LL | /     if 42 == 1337 {
 LL | |         if 'a' != 'A' {
@@ -102,7 +102,7 @@
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:95:5
+  --> $DIR/collapsible_if.rs:100:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" { // Collapsible
@@ -119,7 +119,7 @@
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:154:5
+  --> $DIR/collapsible_if.rs:159:5
    |
 LL | /     if matches!(true, true) {
 LL | |         if matches!(true, true) {}
@@ -127,7 +127,7 @@
    | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:159:5
+  --> $DIR/collapsible_if.rs:164:5
    |
 LL | /     if matches!(true, true) && truth() {
 LL | |         if matches!(true, true) {}
diff --git a/src/tools/clippy/tests/ui/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro.rs
index 8701e3c..10788d4 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro.rs
@@ -4,6 +4,7 @@
 fn foo(n: u32) -> u32 {
     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
 }
+fn bar(_: ()) {}
 
 fn factorial(n: u32) -> u32 {
     if dbg!(n <= 1) {
@@ -21,6 +22,32 @@
     dbg!(1, 2, 3, 4, 5);
 }
 
+fn issue9914() {
+    macro_rules! foo {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! foo2 {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! expand_to_dbg {
+        () => {
+            dbg!();
+        };
+    }
+
+    dbg!();
+    #[allow(clippy::let_unit_value)]
+    let _ = dbg!();
+    bar(dbg!());
+    foo!(dbg!());
+    foo2!(foo!(dbg!()));
+    expand_to_dbg!();
+}
+
 mod issue7274 {
     trait Thing<'b> {
         fn foo(&self);
diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr
index ddb5f13..530e766 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro.stderr
@@ -11,7 +11,7 @@
    |                      ~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:9:8
+  --> $DIR/dbg_macro.rs:10:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
@@ -22,7 +22,7 @@
    |        ~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:10:9
+  --> $DIR/dbg_macro.rs:11:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
@@ -33,7 +33,7 @@
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:12:9
+  --> $DIR/dbg_macro.rs:13:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:17:5
+  --> $DIR/dbg_macro.rs:18:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
@@ -55,7 +55,7 @@
    |     ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:18:5
+  --> $DIR/dbg_macro.rs:19:5
    |
 LL |     dbg!(dbg!(dbg!(42)));
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@
    |     ~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:19:14
+  --> $DIR/dbg_macro.rs:20:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@
    |              ~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:20:5
+  --> $DIR/dbg_macro.rs:21:5
    |
 LL |     dbg!(1, 2, dbg!(3, 4));
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@
    |     ~~~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:21:5
+  --> $DIR/dbg_macro.rs:22:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -99,7 +99,63 @@
    |     ~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:41:9
+  --> $DIR/dbg_macro.rs:42:5
+   |
+LL |     dbg!();
+   |     ^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL -     dbg!();
+LL +     
+   |
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:44:13
+   |
+LL |     let _ = dbg!();
+   |             ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     let _ = ();
+   |             ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:45:9
+   |
+LL |     bar(dbg!());
+   |         ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     bar(());
+   |         ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:46:10
+   |
+LL |     foo!(dbg!());
+   |          ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     foo!(());
+   |          ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:47:16
+   |
+LL |     foo2!(foo!(dbg!()));
+   |                ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     foo2!(foo!(()));
+   |                ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:68:9
    |
 LL |         dbg!(2);
    |         ^^^^^^^
@@ -110,7 +166,7 @@
    |         ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:47:5
+  --> $DIR/dbg_macro.rs:74:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -121,7 +177,7 @@
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:52:5
+  --> $DIR/dbg_macro.rs:79:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -132,7 +188,7 @@
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:58:9
+  --> $DIR/dbg_macro.rs:85:9
    |
 LL |         dbg!(1);
    |         ^^^^^^^
@@ -142,5 +198,5 @@
 LL |         1;
    |         ~
 
-error: aborting due to 13 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
index 4c2d1ea..e1012f38 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
@@ -105,6 +105,7 @@
     // should lint
     let _ = PhantomData::<usize>;
     let _: PhantomData<i32> = PhantomData;
+    let _: PhantomData<i32> = std::marker::PhantomData;
     let _ = UnitStruct;
 
     // should not lint
@@ -116,4 +117,21 @@
     let _ = EmptyStruct::default();
     let _ = FakeDefault::default();
     let _ = <FakeDefault as Default>::default();
+
+    macro_rules! in_macro {
+        ($i:ident) => {{
+            let _ = UnitStruct::default();
+            let _ = $i::default();
+        }};
+    }
+
+    in_macro!(UnitStruct);
+
+    macro_rules! struct_from_macro {
+        () => {
+            UnitStruct
+        };
+    }
+
+    let _ = <struct_from_macro!()>::default();
 }
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
index 850793d..c7b4313 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
@@ -105,6 +105,7 @@
     // should lint
     let _ = PhantomData::<usize>::default();
     let _: PhantomData<i32> = PhantomData::default();
+    let _: PhantomData<i32> = std::marker::PhantomData::default();
     let _ = UnitStruct::default();
 
     // should not lint
@@ -116,4 +117,21 @@
     let _ = EmptyStruct::default();
     let _ = FakeDefault::default();
     let _ = <FakeDefault as Default>::default();
+
+    macro_rules! in_macro {
+        ($i:ident) => {{
+            let _ = UnitStruct::default();
+            let _ = $i::default();
+        }};
+    }
+
+    in_macro!(UnitStruct);
+
+    macro_rules! struct_from_macro {
+        () => {
+            UnitStruct
+        };
+    }
+
+    let _ = <struct_from_macro!()>::default();
 }
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
index 4058943..61a32fb 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
@@ -25,10 +25,16 @@
    |                                          ^^^^^^^^^^^ help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> $DIR/default_constructed_unit_structs.rs:108:23
+  --> $DIR/default_constructed_unit_structs.rs:108:55
+   |
+LL |     let _: PhantomData<i32> = std::marker::PhantomData::default();
+   |                                                       ^^^^^^^^^^^ help: remove this call to `default`
+
+error: use of `default` to create a unit struct
+  --> $DIR/default_constructed_unit_structs.rs:109:23
    |
 LL |     let _ = UnitStruct::default();
    |                       ^^^^^^^^^^^ help: remove this call to `default`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
index 9c91d93..51a3b0d 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
@@ -31,18 +31,10 @@
    |                          ^^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:36:30
-   |
-LL |                 _ => true || panic!("boo"),
-   |                              ^^^^^^^^^^^^^
-   |
-   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: sub-expression diverges
   --> $DIR/diverging_sub_expression.rs:38:26
    |
 LL |             _ => true || break,
    |                          ^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
new file mode 100644
index 0000000..e843770
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
@@ -0,0 +1,132 @@
+//@aux-build:proc_macro_attr.rs
+#![warn(clippy::empty_line_after_doc_comments)]
+#![allow(clippy::assertions_on_constants)]
+#![feature(custom_inner_attributes)]
+#![rustfmt::skip]
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+mod some_mod {
+    //! This doc comment should *NOT* produce a warning
+
+    mod some_inner_mod {
+        fn some_noop() {}
+    }
+}
+
+/// This should produce a warning
+
+fn with_doc_and_newline() { assert!(true)}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+/// some comment
+fn with_one_newline_and_comment() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+fn with_one_newline() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+
+fn with_two_newlines() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+enum Baz {
+    One,
+    Two
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+struct Foo {
+    one: isize,
+    two: isize
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+mod foo {
+}
+
+/// This doc comment should produce a warning
+
+/** This is also a doc comment and should produce a warning
+ */
+
+// This should *NOT* produce a warning
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(missing_docs)]
+fn three_attributes() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4
+}
+
+// This should *NOT* produce a warning because the empty line is inside a block comment
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct S;
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/* test */
+pub struct T;
+
+// This should *NOT* produce a warning
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[fake_async_trait]
+pub trait Bazz {
+    fn foo() -> Vec<u8> {
+        let _i = "";
+
+
+
+        vec![]
+    }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
new file mode 100644
index 0000000..2ca1b51
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
@@ -0,0 +1,36 @@
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:18:1
+   |
+LL | / /// This should produce a warning
+LL | |
+LL | | fn with_doc_and_newline() { assert!(true)}
+   | |_
+   |
+   = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:68:1
+   |
+LL | / /// This doc comment should produce a warning
+LL | |
+LL | | /** This is also a doc comment and should produce a warning
+LL | |  */
+...  |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+   | |_
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:70:1
+   |
+LL | / /** This is also a doc comment and should produce a warning
+LL | |  */
+LL | |
+LL | | // This should *NOT* produce a warning
+...  |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+   | |_
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/float_arithmetic.rs b/src/tools/clippy/tests/ui/float_arithmetic.rs
index 60fa756..a928c35 100644
--- a/src/tools/clippy/tests/ui/float_arithmetic.rs
+++ b/src/tools/clippy/tests/ui/float_arithmetic.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
+#![warn(clippy::arithmetic_side_effects, clippy::float_arithmetic)]
 #![allow(
     unused,
     clippy::shadow_reuse,
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.rs b/src/tools/clippy/tests/ui/integer_arithmetic.rs
deleted file mode 100644
index ab9b609..0000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-//@aux-build:proc_macro_derive.rs
-
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::op_ref)]
-
-extern crate proc_macro_derive;
-
-#[derive(proc_macro_derive::ShadowDerive)]
-pub struct Nothing;
-
-#[rustfmt::skip]
-fn main() {
-    let mut i = 1i32;
-    let mut var1 = 13i32;
-    let mut var2 = -1i32;
-    1 + i;
-    i * 2;
-    1 %
-    i / 2; // no error, this is part of the expression in the preceding line
-    i - 2 + 2 - i;
-    -i;
-    i >> 1;
-    i << 1;
-
-    // no error, overflows are checked by `overflowing_literals`
-    -1;
-    -(-1);
-
-    i & 1; // no wrapping
-    i | 1;
-    i ^ 1;
-
-    i += 1;
-    i -= 1;
-    i *= 2;
-    i /= 2;
-    i /= 0;
-    i /= -1;
-    i /= var1;
-    i /= var2;
-    i %= 2;
-    i %= 0;
-    i %= -1;
-    i %= var1;
-    i %= var2;
-    i <<= 3;
-    i >>= 2;
-
-    // no errors
-    i |= 1;
-    i &= 1;
-    i ^= i;
-
-    // No errors for the following items because they are constant expressions
-    enum Foo {
-        Bar = -2,
-    }
-    struct Baz([i32; 1 + 1]);
-    union Qux {
-        field: [i32; 1 + 1],
-    }
-    type Alias = [i32; 1 + 1];
-
-    const FOO: i32 = -2;
-    static BAR: i32 = -2;
-
-    let _: [i32; 1 + 1] = [0, 0];
-
-    let _: [i32; 1 + 1] = {
-        let a: [i32; 1 + 1] = [0, 0];
-        a
-    };
-
-    trait Trait {
-        const ASSOC: i32 = 1 + 1;
-    }
-
-    impl Trait for Foo {
-        const ASSOC: i32 = {
-            let _: [i32; 1 + 1];
-            fn foo() {}
-            1 + 1
-        };
-    }
-}
-
-// warn on references as well! (#5328)
-pub fn int_arith_ref() {
-    3 + &1;
-    &3 + 1;
-    &3 + &1;
-}
-
-pub fn foo(x: &i32) -> i32 {
-    let a = 5;
-    a + x
-}
-
-pub fn bar(x: &i32, y: &i32) -> i32 {
-    x + y
-}
-
-pub fn baz(x: i32, y: &i32) -> i32 {
-    x + y
-}
-
-pub fn qux(x: i32, y: i32) -> i32 {
-    (&x + &y)
-}
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.stderr b/src/tools/clippy/tests/ui/integer_arithmetic.stderr
deleted file mode 100644
index add3b6b..0000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.stderr
+++ /dev/null
@@ -1,169 +0,0 @@
-error: this operation will panic at runtime
-  --> $DIR/integer_arithmetic.rs:37:5
-   |
-LL |     i /= 0;
-   |     ^^^^^^ attempt to divide `_` by zero
-   |
-   = note: `#[deny(unconditional_panic)]` on by default
-
-error: this operation will panic at runtime
-  --> $DIR/integer_arithmetic.rs:42:5
-   |
-LL |     i %= 0;
-   |     ^^^^^^ attempt to calculate the remainder of `_` with a divisor of zero
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:16:5
-   |
-LL |     1 + i;
-   |     ^^^^^
-   |
-   = note: `-D clippy::integer-arithmetic` implied by `-D warnings`
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:17:5
-   |
-LL |     i * 2;
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:18:5
-   |
-LL | /     1 %
-LL | |     i / 2; // no error, this is part of the expression in the preceding line
-   | |_____^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:20:5
-   |
-LL |     i - 2 + 2 - i;
-   |     ^^^^^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:21:5
-   |
-LL |     -i;
-   |     ^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:22:5
-   |
-LL |     i >> 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:23:5
-   |
-LL |     i << 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:33:5
-   |
-LL |     i += 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:34:5
-   |
-LL |     i -= 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:35:5
-   |
-LL |     i *= 2;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:38:11
-   |
-LL |     i /= -1;
-   |           ^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:39:5
-   |
-LL |     i /= var1;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:40:5
-   |
-LL |     i /= var2;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:43:11
-   |
-LL |     i %= -1;
-   |           ^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:44:5
-   |
-LL |     i %= var1;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:45:5
-   |
-LL |     i %= var2;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:46:5
-   |
-LL |     i <<= 3;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:47:5
-   |
-LL |     i >>= 2;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:89:5
-   |
-LL |     3 + &1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:90:5
-   |
-LL |     &3 + 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:91:5
-   |
-LL |     &3 + &1;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:96:5
-   |
-LL |     a + x
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:100:5
-   |
-LL |     x + y
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:104:5
-   |
-LL |     x + y
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:108:5
-   |
-LL |     (&x + &y)
-   |     ^^^^^^^^^
-
-error: aborting due to 27 previous errors
-
diff --git a/src/tools/clippy/tests/ui/issue-111399.rs b/src/tools/clippy/tests/ui/issue-111399.rs
new file mode 100644
index 0000000..b65e6c7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/issue-111399.rs
@@ -0,0 +1,13 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that rustc doesn't crash on the trait bound `Self::Ty: std::marker::Freeze`.
+
+pub struct Struct;
+
+impl Struct {
+    pub type Ty = usize;
+    pub const CT: Self::Ty = 42;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
index 8486137..2c313ff 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -1,6 +1,12 @@
+//@aux-build: proc_macros.rs
+
 #![allow(unused)]
 #![warn(clippy::let_underscore_untyped)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
+use clippy_utils::is_from_proc_macro;
 use std::future::Future;
 use std::{boxed::Box, fmt::Display};
 
@@ -32,6 +38,14 @@
     || {}
 }
 
+with_span!(
+    span
+
+    fn dont_lint_proc_macro() {
+        let _ = a();
+    }
+);
+
 fn main() {
     let _ = a();
     let _ = b(1);
@@ -40,6 +54,7 @@
     let _ = e();
     let _ = f();
     let _ = g();
+    let closure = || {};
 
     _ = a();
     _ = b(1);
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
index 6844cb9..bbf2508 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
@@ -1,60 +1,60 @@
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:36:5
+  --> $DIR/let_underscore_untyped.rs:50:5
    |
 LL |     let _ = a();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:36:10
+  --> $DIR/let_underscore_untyped.rs:50:10
    |
 LL |     let _ = a();
    |          ^
    = note: `-D clippy::let-underscore-untyped` implied by `-D warnings`
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:37:5
+  --> $DIR/let_underscore_untyped.rs:51:5
    |
 LL |     let _ = b(1);
    |     ^^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:37:10
+  --> $DIR/let_underscore_untyped.rs:51:10
    |
 LL |     let _ = b(1);
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:39:5
+  --> $DIR/let_underscore_untyped.rs:53:5
    |
 LL |     let _ = d(&1);
    |     ^^^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:39:10
+  --> $DIR/let_underscore_untyped.rs:53:10
    |
 LL |     let _ = d(&1);
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:40:5
+  --> $DIR/let_underscore_untyped.rs:54:5
    |
 LL |     let _ = e();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:40:10
+  --> $DIR/let_underscore_untyped.rs:54:10
    |
 LL |     let _ = e();
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:41:5
+  --> $DIR/let_underscore_untyped.rs:55:5
    |
 LL |     let _ = f();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:41:10
+  --> $DIR/let_underscore_untyped.rs:55:10
    |
 LL |     let _ = f();
    |          ^
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index d175597..3996d77 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -8,6 +8,12 @@
 )]
 #![warn(clippy::manual_let_else)]
 
+enum Variant {
+    A(usize, usize),
+    B(usize),
+    C,
+}
+
 fn g() -> Option<()> {
     None
 }
@@ -135,6 +141,15 @@
         };
     }
     create_binding_if_some!(w, g());
+
+    fn e() -> Variant {
+        Variant::A(0, 0)
+    }
+
+    // Should not be renamed
+    let v = if let Variant::A(a, 0) = e() { a } else { return };
+    // Should be renamed
+    let v = if let Variant::B(b) = e() { b } else { return };
 }
 
 fn not_fire() {
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index 52aac6b..f6f56f7 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -1,13 +1,13 @@
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:18:5
+  --> $DIR/manual_let_else.rs:24:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { return };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { return };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
    |
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:19:5
+  --> $DIR/manual_let_else.rs:25:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -18,13 +18,13 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         return;
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:25:5
+  --> $DIR/manual_let_else.rs:31:5
    |
 LL | /     let v = if let Some(v) = g() {
 LL | |         // Blocks around the identity should have no impact
@@ -45,25 +45,25 @@
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:38:9
+  --> $DIR/manual_let_else.rs:44:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { continue };`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:39:9
+  --> $DIR/manual_let_else.rs:45:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { break };
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { break };`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:43:5
+  --> $DIR/manual_let_else.rs:49:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { panic!() };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:46:5
+  --> $DIR/manual_let_else.rs:52:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -74,13 +74,13 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         std::process::abort()
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:53:5
+  --> $DIR/manual_let_else.rs:59:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -91,13 +91,13 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         if true { return } else { panic!() }
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:60:5
+  --> $DIR/manual_let_else.rs:66:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -109,14 +109,14 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         if true {}
 LL +         panic!();
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:70:5
+  --> $DIR/manual_let_else.rs:76:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -129,7 +129,7 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match () {
 LL +             _ if panic!() => {},
 LL +             _ => panic!(),
@@ -138,13 +138,13 @@
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:80:5
+  --> $DIR/manual_let_else.rs:86:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { if panic!() {} };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:83:5
+  --> $DIR/manual_let_else.rs:89:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -157,7 +157,7 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match panic!() {
 LL +             _ => {},
 LL +         }
@@ -165,7 +165,7 @@
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:92:5
+  --> $DIR/manual_let_else.rs:98:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -178,7 +178,7 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else { if true {
+LL ~     let Some(v) = g() else { if true {
 LL +         return;
 LL +     } else {
 LL +         panic!("diverge");
@@ -186,7 +186,7 @@
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:101:5
+  --> $DIR/manual_let_else.rs:107:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -199,7 +199,7 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match (g(), g()) {
 LL +             (Some(_), None) => return,
 LL +             (None, Some(_)) => {
@@ -215,7 +215,7 @@
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:118:5
+  --> $DIR/manual_let_else.rs:124:5
    |
 LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
 LL | |         v_some
@@ -226,13 +226,13 @@
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g().map(|v| (v, 42)) else {
+LL ~     let Some((v, w)) = g().map(|v| (v, 42)) else {
 LL +         return;
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:125:5
+  --> $DIR/manual_let_else.rs:131:5
    |
 LL | /     let v = if let (Some(v_some), w_some) = (g(), 0) {
 LL | |         (w_some, v_some)
@@ -249,10 +249,10 @@
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:134:13
+  --> $DIR/manual_let_else.rs:140:13
    |
 LL |             let $n = if let Some(v) = $e { v } else { return };
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
 ...
 LL |     create_binding_if_some!(w, g());
    |     ------------------------------- in this macro invocation
@@ -260,13 +260,25 @@
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:247:5
+  --> $DIR/manual_let_else.rs:150:5
+   |
+LL |     let v = if let Variant::A(a, 0) = e() { a } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(a, 0) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:152:5
+   |
+LL |     let v = if let Variant::B(b) = e() { b } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(v) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:262:5
    |
 LL | /     let _ = match ff {
 LL | |         Some(value) => value,
 LL | |         _ => macro_call!(),
 LL | |     };
-   | |______^ help: consider writing: `let Some(value) = ff else { macro_call!() };`
+   | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
 
-error: aborting due to 18 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index 7abaa0b..bacc14d 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -5,7 +5,7 @@
 LL | |         Some(v_some) => v_some,
 LL | |         None => return,
 LL | |     };
-   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+   | |______^ help: consider writing: `let Some(v) = g() else { return };`
    |
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
@@ -16,7 +16,7 @@
 LL | |         Some(v_some) => v_some,
 LL | |         _ => return,
 LL | |     };
-   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+   | |______^ help: consider writing: `let Some(v) = g() else { return };`
 
 error: this could be rewritten as `let...else`
   --> $DIR/manual_let_else_match.rs:44:9
diff --git a/src/tools/clippy/tests/ui/manual_next_back.fixed b/src/tools/clippy/tests/ui/manual_next_back.fixed
new file mode 100644
index 0000000..e8a4706
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.fixed
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+    fn rev(self) -> Self {
+        self
+    }
+
+    fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back()
+    }
+}
+
+impl Iterator for FakeIter {
+    type Item = i32;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    // should not lint
+    FakeIter(0..10).rev().next();
+
+    // should lint
+    let _ = (0..10).next_back().unwrap();
+    let _ = "something".bytes().next_back();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.rs b/src/tools/clippy/tests/ui/manual_next_back.rs
new file mode 100644
index 0000000..9ec8924
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.rs
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+    fn rev(self) -> Self {
+        self
+    }
+
+    fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back()
+    }
+}
+
+impl Iterator for FakeIter {
+    type Item = i32;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    // should not lint
+    FakeIter(0..10).rev().next();
+
+    // should lint
+    let _ = (0..10).rev().next().unwrap();
+    let _ = "something".bytes().rev().next();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.stderr b/src/tools/clippy/tests/ui/manual_next_back.stderr
new file mode 100644
index 0000000..94ccaa9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.stderr
@@ -0,0 +1,16 @@
+error: manual backwards iteration
+  --> $DIR/manual_next_back.rs:34:20
+   |
+LL |     let _ = (0..10).rev().next().unwrap();
+   |                    ^^^^^^^^^^^^^ help: use: `.next_back()`
+   |
+   = note: `-D clippy::manual-next-back` implied by `-D warnings`
+
+error: manual backwards iteration
+  --> $DIR/manual_next_back.rs:35:32
+   |
+LL |     let _ = "something".bytes().rev().next();
+   |                                ^^^^^^^^^^^^^ help: use: `.next_back()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
index 7215660..60f5906 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
@@ -15,7 +15,7 @@
     let _y = matches!(x, Some(0));
 
     // Lint
-    let _w = matches!(x, Some(_));
+    let _w = x.is_some();
 
     // Turn into is_none
     let _z = x.is_none();
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
index 46f67ef..b72fe10 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
@@ -10,7 +10,7 @@
    |
    = note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
 
-error: match expression looks like `matches!` macro
+error: redundant pattern matching, consider using `is_some()`
   --> $DIR/match_expr_like_matches_macro.rs:21:14
    |
 LL |       let _w = match x {
@@ -18,7 +18,9 @@
 LL | |         Some(_) => true,
 LL | |         _ => false,
 LL | |     };
-   | |_____^ help: try this: `matches!(x, Some(_))`
+   | |_____^ help: try this: `x.is_some()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_none()`
   --> $DIR/match_expr_like_matches_macro.rs:27:14
@@ -29,8 +31,6 @@
 LL | |         None => true,
 LL | |     };
    | |_____^ help: try this: `x.is_none()`
-   |
-   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: match expression looks like `matches!` macro
   --> $DIR/match_expr_like_matches_macro.rs:33:15
diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs
index 0b9342c..3914b45 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms.rs
@@ -53,4 +53,84 @@
     }
 }
 
-fn main() {}
+macro_rules! m {
+    (foo) => {};
+    (bar) => {};
+}
+macro_rules! foo {
+    () => {
+        1
+    };
+}
+macro_rules! bar {
+    () => {
+        1
+    };
+}
+
+fn main() {
+    let x = 0;
+    let _ = match 0 {
+        0 => {
+            m!(foo);
+            x
+        },
+        1 => {
+            m!(bar);
+            x
+        },
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => {
+            m!(foo);
+            0
+        },
+        1 => {
+            m!(bar);
+            0
+        },
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => {
+            let mut x = 0;
+            #[cfg(not_enabled)]
+            {
+                x = 5;
+            }
+            #[cfg(not(not_enabled))]
+            {
+                x = 6;
+            }
+            x
+        },
+        1 => {
+            let mut x = 0;
+            #[cfg(also_not_enabled)]
+            {
+                x = 5;
+            }
+            #[cfg(not(also_not_enabled))]
+            {
+                x = 6;
+            }
+            x
+        },
+        _ => 0,
+    };
+
+    let _ = match 0 {
+        0 => foo!(),
+        1 => bar!(),
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => cfg!(not_enabled),
+        1 => cfg!(also_not_enabled),
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 82b2c43..60b2975 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -239,4 +239,10 @@
         3 => core::convert::identity::<u32>(todo!()),
         _ => 5,
     };
+
+    let _ = match 0 {
+        0 => cfg!(not_enable),
+        1 => cfg!(not_enable),
+        _ => false,
+    };
 }
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 06cd430..8fb461b 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -192,5 +192,20 @@
 LL |         Some(Bar { x: 0, y: 5, .. }) => 1,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error: this match arm has an identical body to another arm
+  --> $DIR/match_same_arms2.rs:245:9
+   |
+LL |         1 => cfg!(not_enable),
+   |         -^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: try merging the arm patterns: `1 | 0`
+   |
+   = help: or try changing either arm body
+note: other arm here
+  --> $DIR/match_same_arms2.rs:244:9
+   |
+LL |         0 => cfg!(not_enable),
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mem_forget.rs b/src/tools/clippy/tests/ui/mem_forget.rs
index 5137448..edb9d87 100644
--- a/src/tools/clippy/tests/ui/mem_forget.rs
+++ b/src/tools/clippy/tests/ui/mem_forget.rs
@@ -5,7 +5,7 @@
 use std::mem::forget as forgetSomething;
 
 #[warn(clippy::mem_forget)]
-#[allow(forget_copy)]
+#[allow(forgetting_copy_types)]
 fn main() {
     let five: i32 = 5;
     forgetSomething(five);
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index f28153e..4ef6f0c 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -2,7 +2,7 @@
 #![allow(unused)]
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 #![warn(clippy::multiple_unsafe_ops_per_block)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
index f860852..bf19118 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
@@ -63,6 +63,13 @@
     needless_bool2(x);
     needless_bool3(x);
     needless_bool_condition();
+
+    if a == b {
+        true
+    } else {
+        // Do not lint as this comment might be important
+        false
+    };
 }
 
 fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.rs b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
index 6680dab..a6c465d 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
@@ -99,6 +99,13 @@
     needless_bool2(x);
     needless_bool3(x);
     needless_bool_condition();
+
+    if a == b {
+        true
+    } else {
+        // Do not lint as this comment might be important
+        false
+    };
 }
 
 fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
index d2c4837..fa90637 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
@@ -91,7 +91,7 @@
    | |_____^ help: you can reduce it to: `a < b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:105:5
+  --> $DIR/fixable.rs:112:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -101,7 +101,7 @@
    | |_____^ help: you can reduce it to: `return x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:113:5
+  --> $DIR/fixable.rs:120:5
    |
 LL | /     if x {
 LL | |         return false;
@@ -111,7 +111,7 @@
    | |_____^ help: you can reduce it to: `return !x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:121:5
+  --> $DIR/fixable.rs:128:5
    |
 LL | /     if x && y {
 LL | |         return true;
@@ -121,7 +121,7 @@
    | |_____^ help: you can reduce it to: `return x && y`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:129:5
+  --> $DIR/fixable.rs:136:5
    |
 LL | /     if x && y {
 LL | |         return false;
@@ -131,7 +131,7 @@
    | |_____^ help: you can reduce it to: `return !(x && y)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:137:8
+  --> $DIR/fixable.rs:144:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -139,25 +139,25 @@
    = note: `-D clippy::bool-comparison` implied by `-D warnings`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:141:8
+  --> $DIR/fixable.rs:148:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:151:8
+  --> $DIR/fixable.rs:158:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:152:8
+  --> $DIR/fixable.rs:159:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:161:12
+  --> $DIR/fixable.rs:168:12
    |
 LL |       } else if returns_bool() {
    |  ____________^
@@ -168,7 +168,7 @@
    | |_____^ help: you can reduce it to: `{ !returns_bool() }`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:174:5
+  --> $DIR/fixable.rs:181:5
    |
 LL | /     if unsafe { no(4) } & 1 != 0 {
 LL | |         true
@@ -178,13 +178,13 @@
    | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:179:30
+  --> $DIR/fixable.rs:186:30
    |
 LL |     let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false };
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:182:9
+  --> $DIR/fixable.rs:189:9
    |
 LL |         if unsafe { no(4) } & 1 != 0 { true } else { false }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed
index 024c22d..b7e80af 100644
--- a/src/tools/clippy/tests/ui/needless_collect.fixed
+++ b/src/tools/clippy/tests/ui/needless_collect.fixed
@@ -62,4 +62,16 @@
 
     let _ = sample.iter().next().is_none();
     let _ = sample.iter().any(|x| x == &0);
+
+    #[allow(clippy::double_parens)]
+    {
+        Vec::<u8>::new().extend((0..10));
+        foo((0..10));
+        bar((0..10).collect::<Vec<_>>(), (0..10));
+        baz((0..10), (), ('a'..='z'))
+    }
 }
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs
index 7ed7bab..680b6fa 100644
--- a/src/tools/clippy/tests/ui/needless_collect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect.rs
@@ -62,4 +62,16 @@
 
     let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
+
+    #[allow(clippy::double_parens)]
+    {
+        Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+        foo((0..10).collect::<Vec<_>>());
+        bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+        baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+    }
 }
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.stderr b/src/tools/clippy/tests/ui/needless_collect.stderr
index 584d2a1..ad22a7b 100644
--- a/src/tools/clippy/tests/ui/needless_collect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect.stderr
@@ -90,5 +90,29 @@
 LL |     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
 
-error: aborting due to 15 previous errors
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:68:40
+   |
+LL |         Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+   |                                        ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:69:20
+   |
+LL |         foo((0..10).collect::<Vec<_>>());
+   |                    ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:70:49
+   |
+LL |         bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+   |                                                 ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:71:37
+   |
+LL |         baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+   |                                     ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index ee4e500..d49ae5d 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -231,8 +231,9 @@
 }
 
 fn issue_9361() -> i32 {
-    #[allow(clippy::integer_arithmetic)]
-    return 1 + 2;
+    let n = 1;
+    #[allow(clippy::arithmetic_side_effects)]
+    return n + n;
 }
 
 fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index cd999db..3676382 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -239,8 +239,9 @@
 }
 
 fn issue_9361() -> i32 {
-    #[allow(clippy::integer_arithmetic)]
-    return 1 + 2;
+    let n = 1;
+    #[allow(clippy::arithmetic_side_effects)]
+    return n + n;
 }
 
 fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 87d0cd3..05f6038 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -328,7 +328,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:249:9
+  --> $DIR/needless_return.rs:250:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^
@@ -336,7 +336,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:251:9
+  --> $DIR/needless_return.rs:252:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^
@@ -344,7 +344,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:258:13
+  --> $DIR/needless_return.rs:259:13
    |
 LL |             return 10;
    |             ^^^^^^^^^
@@ -352,7 +352,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:261:13
+  --> $DIR/needless_return.rs:262:13
    |
 LL |             return 100;
    |             ^^^^^^^^^^
@@ -360,7 +360,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:269:9
+  --> $DIR/needless_return.rs:270:9
    |
 LL |         return 0;
    |         ^^^^^^^^
@@ -368,7 +368,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:276:13
+  --> $DIR/needless_return.rs:277:13
    |
 LL |             return *(x as *const isize);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -376,7 +376,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:278:13
+  --> $DIR/needless_return.rs:279:13
    |
 LL |             return !*(x as *const isize);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -384,7 +384,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:285:20
+  --> $DIR/needless_return.rs:286:20
    |
 LL |           let _ = 42;
    |  ____________________^
@@ -395,7 +395,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:292:20
+  --> $DIR/needless_return.rs:293:20
    |
 LL |         let _ = 42; return;
    |                    ^^^^^^^
@@ -403,7 +403,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:304:9
+  --> $DIR/needless_return.rs:305:9
    |
 LL |         return Ok(format!("ok!"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -411,7 +411,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:306:9
+  --> $DIR/needless_return.rs:307:9
    |
 LL |         return Err(format!("err!"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -419,7 +419,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:312:9
+  --> $DIR/needless_return.rs:313:9
    |
 LL |         return if true { 1 } else { 2 };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -427,7 +427,7 @@
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:316:9
+  --> $DIR/needless_return.rs:317:9
    |
 LL |         return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.fixed b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
new file mode 100644
index 0000000..430caaf
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(windows)]
+fn hermit() {}
+
+#[cfg(windows)]
+fn wasi() {}
+
+#[cfg(all(unix, not(windows)))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.rs b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
new file mode 100644
index 0000000..a38ce1c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(all(windows))]
+fn hermit() {}
+
+#[cfg(any(windows))]
+fn wasi() {}
+
+#[cfg(all(any(unix), all(not(windows))))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
new file mode 100644
index 0000000..cdfd728
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
@@ -0,0 +1,28 @@
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:5:7
+   |
+LL | #[cfg(all(windows))]
+   |       ^^^^^^^^^^^^ help: try: `windows`
+   |
+   = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:8:7
+   |
+LL | #[cfg(any(windows))]
+   |       ^^^^^^^^^^^^ help: try: `windows`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:11:11
+   |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+   |           ^^^^^^^^^ help: try: `unix`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:11:22
+   |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+   |                      ^^^^^^^^^^^^^^^^^ help: try: `not(windows)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.rs b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
new file mode 100644
index 0000000..a4c6abc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
@@ -0,0 +1,6 @@
+#![allow(unused)]
+
+#[cfg(all())]
+fn all() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
new file mode 100644
index 0000000..2a9a36f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
@@ -0,0 +1,10 @@
+error: unneeded sub `cfg` when there is no condition
+  --> $DIR/non_minimal_cfg2.rs:3:7
+   |
+LL | #[cfg(all())]
+   |       ^^^^^
+   |
+   = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 57f341e..2b8ce54 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -92,6 +92,15 @@
         .collect::<Vec<_>>()
 }
 
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+    variable.map_or_else(|_| {
+        println!("Err");
+    }, |binding| {
+        println!("Ok {binding}");
+    })
+}
+
 enum DummyEnum {
     One(u8),
     Two,
@@ -113,6 +122,7 @@
     unop_bad(&None, None);
     let _ = longer_body(None);
     test_map_or_else(None);
+    test_result_impure_else(Ok(42));
     let _ = negative_tests(None);
     let _ = impure_else(None);
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 19f9f70..cfbec8c 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -115,6 +115,15 @@
         .collect::<Vec<_>>()
 }
 
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+    if let Ok(binding) = variable {
+        println!("Ok {binding}");
+    } else {
+        println!("Err");
+    }
+}
+
 enum DummyEnum {
     One(u8),
     Two,
@@ -136,6 +145,7 @@
     unop_bad(&None, None);
     let _ = longer_body(None);
     test_map_or_else(None);
+    test_result_impure_else(Ok(42));
     let _ = negative_tests(None);
     let _ = impure_else(None);
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index f5e4aff..91d52fc 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -152,14 +152,33 @@
 LL | |             }
    | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
 
+error: use Option::map_or_else instead of an if let/else
+  --> $DIR/option_if_let_else.rs:120:5
+   |
+LL | /     if let Ok(binding) = variable {
+LL | |         println!("Ok {binding}");
+LL | |     } else {
+LL | |         println!("Err");
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     variable.map_or_else(|_| {
+LL +         println!("Err");
+LL +     }, |binding| {
+LL +         println!("Ok {binding}");
+LL +     })
+   |
+
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:133:13
+  --> $DIR/option_if_let_else.rs:142:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:142:13
+  --> $DIR/option_if_let_else.rs:152:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -181,13 +200,13 @@
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:170:13
+  --> $DIR/option_if_let_else.rs:180:13
    |
 LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:174:13
+  --> $DIR/option_if_let_else.rs:184:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -207,7 +226,7 @@
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:213:13
+  --> $DIR/option_if_let_else.rs:223:13
    |
 LL |       let _ = match s {
    |  _____________^
@@ -217,7 +236,7 @@
    | |_____^ help: try: `s.map_or(1, |string| string.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:217:13
+  --> $DIR/option_if_let_else.rs:227:13
    |
 LL |       let _ = match Some(10) {
    |  _____________^
@@ -227,7 +246,7 @@
    | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:223:13
+  --> $DIR/option_if_let_else.rs:233:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -237,7 +256,7 @@
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:227:13
+  --> $DIR/option_if_let_else.rs:237:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -247,10 +266,10 @@
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:231:13
+  --> $DIR/option_if_let_else.rs:241:13
    |
 LL |     let _ = if let Ok(a) = res { a + 1 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
 
-error: aborting due to 20 previous errors
+error: aborting due to 21 previous errors
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.fixed b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
index 81a716b..2df87a2 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.fixed
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.rs b/src/tools/clippy/tests/ui/partialeq_to_none.rs
index f454715..df6233b 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.rs
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.stderr b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
index d06ab7a..4f84862 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.stderr
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
@@ -1,5 +1,5 @@
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:14:8
+  --> $DIR/partialeq_to_none.rs:15:8
    |
 LL |     if f != None { "yay" } else { "nay" }
    |        ^^^^^^^^^ help: use `Option::is_some()` instead: `f.is_some()`
@@ -7,55 +7,55 @@
    = note: `-D clippy::partialeq-to-none` implied by `-D warnings`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:44:13
+  --> $DIR/partialeq_to_none.rs:45:13
    |
 LL |     let _ = x == None;
    |             ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:45:13
+  --> $DIR/partialeq_to_none.rs:46:13
    |
 LL |     let _ = x != None;
    |             ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:46:13
+  --> $DIR/partialeq_to_none.rs:47:13
    |
 LL |     let _ = None == x;
    |             ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:47:13
+  --> $DIR/partialeq_to_none.rs:48:13
    |
 LL |     let _ = None != x;
    |             ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:49:8
+  --> $DIR/partialeq_to_none.rs:50:8
    |
 LL |     if foobar() == None {}
    |        ^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `foobar().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:51:8
+  --> $DIR/partialeq_to_none.rs:52:8
    |
 LL |     if bar().ok() != None {}
    |        ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `bar().ok().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:53:13
+  --> $DIR/partialeq_to_none.rs:54:13
    |
 LL |     let _ = Some(1 + 2) != None;
    |             ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `Some(1 + 2).is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:55:13
+  --> $DIR/partialeq_to_none.rs:56:13
    |
 LL |     let _ = { Some(0) } == None;
    |             ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `{ Some(0) }.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:57:13
+  --> $DIR/partialeq_to_none.rs:58:13
    |
 LL |       let _ = {
    |  _____________^
@@ -77,31 +77,31 @@
    |
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:67:13
+  --> $DIR/partialeq_to_none.rs:68:13
    |
 LL |     let _ = optref() == &&None;
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:68:13
+  --> $DIR/partialeq_to_none.rs:69:13
    |
 LL |     let _ = &&None != optref();
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:69:13
+  --> $DIR/partialeq_to_none.rs:70:13
    |
 LL |     let _ = **optref() == None;
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:70:13
+  --> $DIR/partialeq_to_none.rs:71:13
    |
 LL |     let _ = &None != *optref();
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:73:13
+  --> $DIR/partialeq_to_none.rs:74:13
    |
 LL |     let _ = None != *x;
    |             ^^^^^^^^^^ help: use `Option::is_some()` instead: `(*x).is_some()`
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
index d62f7d2..accdf1d 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
@@ -46,6 +46,7 @@
     let _ = if opt.is_some() { true } else { false };
 
     issue6067();
+    issue10726();
 
     let _ = if gen_opt().is_some() {
         1
@@ -88,3 +89,21 @@
     if (&None::<()>).is_none() {}
     if (&None::<()>).is_none() {}
 }
+
+fn issue10726() {
+    let x = Some(42);
+
+    x.is_some();
+
+    x.is_none();
+
+    x.is_none();
+
+    x.is_some();
+
+    // Don't lint
+    match x {
+        Some(21) => true,
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
index d642942..ec684bd 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
@@ -55,6 +55,7 @@
     let _ = if let Some(_) = opt { true } else { false };
 
     issue6067();
+    issue10726();
 
     let _ = if let Some(_) = gen_opt() {
         1
@@ -103,3 +104,33 @@
     if let None = *(&None::<()>) {}
     if let None = *&None::<()> {}
 }
+
+fn issue10726() {
+    let x = Some(42);
+
+    match x {
+        Some(_) => true,
+        _ => false,
+    };
+
+    match x {
+        None => true,
+        _ => false,
+    };
+
+    match x {
+        Some(_) => false,
+        _ => true,
+    };
+
+    match x {
+        None => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Some(21) => true,
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
index 7c5a047..a69eb39 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
@@ -77,49 +77,49 @@
    |             -------^^^^^^^------ help: try this: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:59:20
+  --> $DIR/redundant_pattern_matching_option.rs:60:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:61:19
+  --> $DIR/redundant_pattern_matching_option.rs:62:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try this: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:67:12
+  --> $DIR/redundant_pattern_matching_option.rs:68:12
    |
 LL |     if let Some(..) = gen_opt() {}
    |     -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:82:12
+  --> $DIR/redundant_pattern_matching_option.rs:83:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:84:12
+  --> $DIR/redundant_pattern_matching_option.rs:85:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:86:15
+  --> $DIR/redundant_pattern_matching_option.rs:87:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:88:15
+  --> $DIR/redundant_pattern_matching_option.rs:89:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:90:5
+  --> $DIR/redundant_pattern_matching_option.rs:91:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -128,7 +128,7 @@
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:95:5
+  --> $DIR/redundant_pattern_matching_option.rs:96:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -137,16 +137,52 @@
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:103:12
+  --> $DIR/redundant_pattern_matching_option.rs:104:12
    |
 LL |     if let None = *(&None::<()>) {}
    |     -------^^^^----------------- help: try this: `if (&None::<()>).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:104:12
+  --> $DIR/redundant_pattern_matching_option.rs:105:12
    |
 LL |     if let None = *&None::<()> {}
    |     -------^^^^--------------- help: try this: `if (&None::<()>).is_none()`
 
-error: aborting due to 22 previous errors
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_option.rs:111:5
+   |
+LL | /     match x {
+LL | |         Some(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_some()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching_option.rs:116:5
+   |
+LL | /     match x {
+LL | |         None => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching_option.rs:121:5
+   |
+LL | /     match x {
+LL | |         Some(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_option.rs:126:5
+   |
+LL | /     match x {
+LL | |         None => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_some()`
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
index c48d152..e4032ae 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
@@ -43,6 +43,7 @@
     issue5504();
     issue6067();
     issue6065();
+    issue10726();
 
     let _ = if gen_res().is_ok() {
         1
@@ -107,3 +108,28 @@
 
     Err::<i32, i32>(42).is_err();
 }
+
+fn issue10726() {
+    // This is optional, but it makes the examples easier
+    let x: Result<i32, i32> = Ok(42);
+
+    x.is_ok();
+
+    x.is_err();
+
+    x.is_err();
+
+    x.is_ok();
+
+    // Don't lint
+    match x {
+        Err(16) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Ok(16) => false,
+        _ => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
index 26f37d1..39eb10d 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
@@ -55,6 +55,7 @@
     issue5504();
     issue6067();
     issue6065();
+    issue10726();
 
     let _ = if let Ok(_) = gen_res() {
         1
@@ -125,3 +126,40 @@
         Err(_) => true,
     };
 }
+
+fn issue10726() {
+    // This is optional, but it makes the examples easier
+    let x: Result<i32, i32> = Ok(42);
+
+    match x {
+        Ok(_) => true,
+        _ => false,
+    };
+
+    match x {
+        Ok(_) => false,
+        _ => true,
+    };
+
+    match x {
+        Err(_) => true,
+        _ => false,
+    };
+
+    match x {
+        Err(_) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Err(16) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Ok(16) => false,
+        _ => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
index d6a46bab..5893ae4d 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
@@ -73,67 +73,67 @@
    |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:59:20
+  --> $DIR/redundant_pattern_matching_result.rs:60:20
    |
 LL |     let _ = if let Ok(_) = gen_res() {
    |             -------^^^^^------------ help: try this: `if gen_res().is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:61:19
+  --> $DIR/redundant_pattern_matching_result.rs:62:19
    |
 LL |     } else if let Err(_) = gen_res() {
    |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:84:19
+  --> $DIR/redundant_pattern_matching_result.rs:85:19
    |
 LL |         while let Some(_) = r#try!(result_opt()) {}
    |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:85:16
+  --> $DIR/redundant_pattern_matching_result.rs:86:16
    |
 LL |         if let Some(_) = r#try!(result_opt()) {}
    |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:91:12
+  --> $DIR/redundant_pattern_matching_result.rs:92:12
    |
 LL |     if let Some(_) = m!() {}
    |     -------^^^^^^^------- help: try this: `if m!().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:92:15
+  --> $DIR/redundant_pattern_matching_result.rs:93:15
    |
 LL |     while let Some(_) = m!() {}
    |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:110:12
+  --> $DIR/redundant_pattern_matching_result.rs:111:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:112:12
+  --> $DIR/redundant_pattern_matching_result.rs:113:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:114:15
+  --> $DIR/redundant_pattern_matching_result.rs:115:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:116:15
+  --> $DIR/redundant_pattern_matching_result.rs:117:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:118:5
+  --> $DIR/redundant_pattern_matching_result.rs:119:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -142,7 +142,7 @@
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:123:5
+  --> $DIR/redundant_pattern_matching_result.rs:124:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -150,5 +150,41 @@
 LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
 
-error: aborting due to 22 previous errors
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:134:5
+   |
+LL | /     match x {
+LL | |         Ok(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:139:5
+   |
+LL | /     match x {
+LL | |         Ok(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:144:5
+   |
+LL | /     match x {
+LL | |         Err(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:149:5
+   |
+LL | /     match x {
+LL | |         Err(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_ok()`
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ref_patterns.rs b/src/tools/clippy/tests/ui/ref_patterns.rs
new file mode 100644
index 0000000..c51e0bc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.rs
@@ -0,0 +1,19 @@
+#![allow(unused)]
+#![warn(clippy::ref_patterns)]
+
+fn use_in_pattern() {
+    let opt = Some(5);
+    match opt {
+        None => {},
+        Some(ref opt) => {},
+    }
+}
+
+fn use_in_binding() {
+    let x = 5;
+    let ref y = x;
+}
+
+fn use_in_parameter(ref x: i32) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/ref_patterns.stderr b/src/tools/clippy/tests/ui/ref_patterns.stderr
new file mode 100644
index 0000000..aa00778
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.stderr
@@ -0,0 +1,27 @@
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:8:14
+   |
+LL |         Some(ref opt) => {},
+   |              ^^^^^^^
+   |
+   = help: consider using `&` for clarity instead
+   = note: `-D clippy::ref-patterns` implied by `-D warnings`
+
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:14:9
+   |
+LL |     let ref y = x;
+   |         ^^^^^
+   |
+   = help: consider using `&` for clarity instead
+
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:17:21
+   |
+LL | fn use_in_parameter(ref x: i32) {}
+   |                     ^^^^^
+   |
+   = help: consider using `&` for clarity instead
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index ab8ac97..a5f79b1 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -34,8 +34,10 @@
     let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
 
+    // These following three cases are considering valid since regex-1.8.0
     let raw_string_error = Regex::new(r"[...\/...]");
     let raw_string_error = Regex::new(r#"[...\/...]"#);
+    let _ = Regex::new(r"(?<hi>hi)").unwrap();
 
     let escaped_string_span = Regex::new("\\b\\c");
 
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index c2440f3..6b8a772 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -82,23 +82,11 @@
 LL |     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
    |                                       ^^^^^^^^^^^^^
 
-error: regex syntax error: unrecognized escape sequence
-  --> $DIR/regex.rs:37:45
-   |
-LL |     let raw_string_error = Regex::new(r"[...//...]");
-   |                                             ^^
-
-error: regex syntax error: unrecognized escape sequence
-  --> $DIR/regex.rs:38:46
-   |
-LL |     let raw_string_error = Regex::new(r#"[...//...]"#);
-   |                                              ^^
-
 error: regex parse error:
            /b/c
              ^^
        error: unrecognized escape sequence
-  --> $DIR/regex.rs:40:42
+  --> $DIR/regex.rs:42:42
    |
 LL |     let escaped_string_span = Regex::new("/b/c");
    |                                          ^^^^^^^^
@@ -106,13 +94,13 @@
    = help: consider using a raw string literal: `r".."`
 
 error: regex syntax error: duplicate flag
-  --> $DIR/regex.rs:42:34
+  --> $DIR/regex.rs:44:34
    |
 LL |     let aux_span = Regex::new("(?ixi)");
    |                                  ^ ^
 
 error: trivial regex
-  --> $DIR/regex.rs:46:33
+  --> $DIR/regex.rs:48:33
    |
 LL |     let trivial_eq = Regex::new("^foobar$");
    |                                 ^^^^^^^^^^
@@ -120,7 +108,7 @@
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:48:48
+  --> $DIR/regex.rs:50:48
    |
 LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    |                                                ^^^^^^^^^^
@@ -128,7 +116,7 @@
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:50:42
+  --> $DIR/regex.rs:52:42
    |
 LL |     let trivial_starts_with = Regex::new("^foobar");
    |                                          ^^^^^^^^^
@@ -136,7 +124,7 @@
    = help: consider using `str::starts_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:52:40
+  --> $DIR/regex.rs:54:40
    |
 LL |     let trivial_ends_with = Regex::new("foobar$");
    |                                        ^^^^^^^^^
@@ -144,7 +132,7 @@
    = help: consider using `str::ends_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:54:39
+  --> $DIR/regex.rs:56:39
    |
 LL |     let trivial_contains = Regex::new("foobar");
    |                                       ^^^^^^^^
@@ -152,7 +140,7 @@
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:56:39
+  --> $DIR/regex.rs:58:39
    |
 LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    |                                       ^^^^^^^^^^^^^^^^
@@ -160,7 +148,7 @@
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:58:40
+  --> $DIR/regex.rs:60:40
    |
 LL |     let trivial_backslash = Regex::new("a/.b");
    |                                        ^^^^^^^
@@ -168,7 +156,7 @@
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:61:36
+  --> $DIR/regex.rs:63:36
    |
 LL |     let trivial_empty = Regex::new("");
    |                                    ^^
@@ -176,7 +164,7 @@
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:63:36
+  --> $DIR/regex.rs:65:36
    |
 LL |     let trivial_empty = Regex::new("^");
    |                                    ^^^
@@ -184,7 +172,7 @@
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:65:36
+  --> $DIR/regex.rs:67:36
    |
 LL |     let trivial_empty = Regex::new("^$");
    |                                    ^^^^
@@ -192,12 +180,12 @@
    = help: consider using `str::is_empty`
 
 error: trivial regex
-  --> $DIR/regex.rs:67:44
+  --> $DIR/regex.rs:69:44
    |
 LL |     let binary_trivial_empty = BRegex::new("^$");
    |                                            ^^^^
    |
    = help: consider using `str::is_empty`
 
-error: aborting due to 25 previous errors
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 9036f89..dfe45de 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -16,6 +16,7 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::bind_instead_of_map)]
@@ -29,11 +30,11 @@
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
 #![allow(drop_bounds)]
-#![allow(drop_copy)]
-#![allow(drop_ref)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 #![allow(for_loops_over_fallibles)]
-#![allow(forget_copy)]
-#![allow(forget_ref)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -58,6 +59,7 @@
 #![warn(clippy::mixed_read_write_in_expression)]
 #![warn(clippy::useless_conversion)]
 #![warn(clippy::match_result_ok)]
+#![warn(clippy::arithmetic_side_effects)]
 #![warn(clippy::overly_complex_bool_expr)]
 #![warn(clippy::new_without_default)]
 #![warn(clippy::bind_instead_of_map)]
@@ -75,13 +77,13 @@
 #![warn(clippy::invisible_characters)]
 #![warn(suspicious_double_ref_op)]
 #![warn(drop_bounds)]
-#![warn(drop_copy)]
-#![warn(drop_ref)]
+#![warn(dropping_copy_types)]
+#![warn(dropping_references)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
-#![warn(forget_copy)]
-#![warn(forget_ref)]
+#![warn(forgetting_copy_types)]
+#![warn(forgetting_references)]
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 43cabe8..ce8eca5 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -16,6 +16,7 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::bind_instead_of_map)]
@@ -29,11 +30,11 @@
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
 #![allow(drop_bounds)]
-#![allow(drop_copy)]
-#![allow(drop_ref)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 #![allow(for_loops_over_fallibles)]
-#![allow(forget_copy)]
-#![allow(forget_ref)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -58,6 +59,7 @@
 #![warn(clippy::eval_order_dependence)]
 #![warn(clippy::identity_conversion)]
 #![warn(clippy::if_let_some_result)]
+#![warn(clippy::integer_arithmetic)]
 #![warn(clippy::logic_bug)]
 #![warn(clippy::new_without_default_derive)]
 #![warn(clippy::option_and_then_some)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 1ad7cf4..3fca60a 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:48:9
+  --> $DIR/rename.rs:49:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,280 +7,286 @@
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:49:9
+  --> $DIR/rename.rs:50:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:51:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:51:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
+error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
+  --> $DIR/rename.rs:62:9
+   |
+LL | #![warn(clippy::integer_arithmetic)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
+
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
-error: lint `clippy::drop_copy` has been renamed to `drop_copy`
-  --> $DIR/rename.rs:78:9
+error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::drop_copy)]
-   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `drop_copy`
+   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
-error: lint `clippy::drop_ref` has been renamed to `drop_ref`
-  --> $DIR/rename.rs:79:9
+error: lint `clippy::drop_ref` has been renamed to `dropping_references`
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::drop_ref)]
-   |         ^^^^^^^^^^^^^^^^ help: use the new name: `drop_ref`
+   |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
-error: lint `clippy::forget_copy` has been renamed to `forget_copy`
-  --> $DIR/rename.rs:83:9
+error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::forget_copy)]
-   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forget_copy`
+   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
-error: lint `clippy::forget_ref` has been renamed to `forget_ref`
-  --> $DIR/rename.rs:84:9
+error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::forget_ref)]
-   |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forget_ref`
+   |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 47 previous errors
+error: aborting due to 48 previous errors
 
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
index eef8024..fdac0e4 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
@@ -2,6 +2,8 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
 
+use std::any::Any;
+
 fn bad_foo<T: Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
     unimplemented!();
 }
@@ -109,4 +111,12 @@
     unimplemented!();
 }
 
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
index a7a1caf..a0300da 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
@@ -2,6 +2,8 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
 
+use std::any::Any;
+
 fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
     unimplemented!();
 }
@@ -109,4 +111,12 @@
     unimplemented!();
 }
 
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+    unimplemented!();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
index af800ba..539b611 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
@@ -1,5 +1,5 @@
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:5:15
+  --> $DIR/trait_duplication_in_bounds.rs:7:15
    |
 LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
@@ -11,46 +11,52 @@
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:11:8
+  --> $DIR/trait_duplication_in_bounds.rs:13:8
    |
 LL |     T: Clone + Clone + Clone + Copy,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:39:26
+  --> $DIR/trait_duplication_in_bounds.rs:41:26
    |
 LL | trait BadSelfTraitBound: Clone + Clone + Clone {
    |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:46:15
+  --> $DIR/trait_duplication_in_bounds.rs:48:15
    |
 LL |         Self: Clone + Clone + Clone;
    |               ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:60:24
+  --> $DIR/trait_duplication_in_bounds.rs:62:24
    |
 LL | trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:67:12
+  --> $DIR/trait_duplication_in_bounds.rs:69:12
    |
 LL |         T: Clone + Clone + Clone + Copy,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:100:19
+  --> $DIR/trait_duplication_in_bounds.rs:102:19
    |
 LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u64> + GenericTrait<u32>`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:108:22
+  --> $DIR/trait_duplication_in_bounds.rs:110:22
    |
 LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::clone::Clone + foo::Clone`
 
-error: aborting due to 8 previous errors
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds.rs:118:33
+   |
+LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+   |                                 ^^^^^^^^^^^^^^^^^ help: try: `Any + Send`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index 01eb6c5..c16caa3 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -33,6 +33,11 @@
     Ok(())
 }
 
+fn dont_lint_on_type_alias() {
+    type A = i32;
+    _ = A::from(0i32);
+}
+
 fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
     let text = "foo\r\nbar\n\nbaz\n";
     let lines = text.lines();
@@ -106,6 +111,7 @@
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
 
+    dont_lint_on_type_alias();
     dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index 34b43a6..c75a2bc 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -33,6 +33,11 @@
     Ok(())
 }
 
+fn dont_lint_on_type_alias() {
+    type A = i32;
+    _ = A::from(0i32);
+}
+
 fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
     let text = "foo\r\nbar\n\nbaz\n";
     let lines = text.lines();
@@ -106,6 +111,7 @@
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
 
+    dont_lint_on_type_alias();
     dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index be067c6..4dca3aa 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -23,97 +23,97 @@
    |                      ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:45:22
+  --> $DIR/useless_conversion.rs:50:22
    |
 LL |     if Some("ok") == lines.into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:50:21
+  --> $DIR/useless_conversion.rs:55:21
    |
 LL |     let mut lines = text.lines().into_iter();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:56:22
+  --> $DIR/useless_conversion.rs:61:22
    |
 LL |     if Some("ok") == text.lines().into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> $DIR/useless_conversion.rs:62:13
+  --> $DIR/useless_conversion.rs:67:13
    |
 LL |     let _ = NUMBERS.into_iter().next();
    |             ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> $DIR/useless_conversion.rs:67:17
+  --> $DIR/useless_conversion.rs:72:17
    |
 LL |     let mut n = NUMBERS.into_iter();
    |                 ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:128:21
+  --> $DIR/useless_conversion.rs:134:21
    |
 LL |     let _: String = "foo".to_string().into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:129:21
+  --> $DIR/useless_conversion.rs:135:21
    |
 LL |     let _: String = From::from("foo".to_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:130:13
+  --> $DIR/useless_conversion.rs:136:13
    |
 LL |     let _ = String::from("foo".to_string());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:131:13
+  --> $DIR/useless_conversion.rs:137:13
    |
 LL |     let _ = String::from(format!("A: {:04}", 123));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:132:13
+  --> $DIR/useless_conversion.rs:138:13
    |
 LL |     let _ = "".lines().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
 
 error: useless conversion to the same type: `std::vec::IntoIter<i32>`
-  --> $DIR/useless_conversion.rs:133:13
+  --> $DIR/useless_conversion.rs:139:13
    |
 LL |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:134:21
+  --> $DIR/useless_conversion.rs:140:21
    |
 LL |     let _: String = format!("Hello {}", "world").into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
 
 error: useless conversion to the same type: `i32`
-  --> $DIR/useless_conversion.rs:139:13
+  --> $DIR/useless_conversion.rs:145:13
    |
 LL |     let _ = i32::from(a + b) * 3;
    |             ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> $DIR/useless_conversion.rs:145:23
+  --> $DIR/useless_conversion.rs:151:23
    |
 LL |     let _: Foo<'a'> = s2.into();
    |                       ^^^^^^^^^ help: consider removing `.into()`: `s2`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> $DIR/useless_conversion.rs:147:13
+  --> $DIR/useless_conversion.rs:153:13
    |
 LL |     let _ = Foo::<'a'>::from(s3);
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3`
 
 error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
-  --> $DIR/useless_conversion.rs:149:13
+  --> $DIR/useless_conversion.rs:155:13
    |
 LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
new file mode 100644
index 0000000..203c4e1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
@@ -0,0 +1,19 @@
+//@compile-flags: --test
+
+#![warn(clippy::wildcard_imports)]
+#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
+
+// Test for #10580, the lint should ignore it because of the crate's cfg test flag.
+
+fn foofoo() {}
+
+mod outer {
+    mod inner {
+        use super::super::*;
+        fn barbar() {
+            let _ = foofoo();
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 3f8f6a7..c40b71f 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -17,9 +17,9 @@
 
 [assign.owners]
 "/.github" = ["@flip1995"]
+"/book" = ["@flip1995"]
 "/util/gh-pages" = ["@xFrednet"]
 "*" = [
-    "@flip1995",
     "@Manishearth",
     "@llogiq",
     "@giraffate",
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 0d42504..e5297d4 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -20,6 +20,7 @@
 walkdir = "2"
 glob = "0.3.0"
 lazycell = "1.3.0"
+anyhow = "1"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 9059a14..ba68b5e 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -428,7 +428,6 @@
         ))
         .unwrap();
 
-        let mut current = None;
         let mut all_targets = HashSet::new();
         let mut all_archs = HashSet::new();
         let mut all_oses = HashSet::new();
@@ -449,14 +448,11 @@
             }
             all_pointer_widths.insert(format!("{}bit", cfg.pointer_width));
 
-            if target == config.target {
-                current = Some(cfg);
-            }
             all_targets.insert(target.into());
         }
 
         Self {
-            current: current.expect("current target not found"),
+            current: Self::get_current_target_config(config),
             all_targets,
             all_archs,
             all_oses,
@@ -467,6 +463,89 @@
             all_pointer_widths,
         }
     }
+
+    fn get_current_target_config(config: &Config) -> TargetCfg {
+        let mut arch = None;
+        let mut os = None;
+        let mut env = None;
+        let mut abi = None;
+        let mut families = Vec::new();
+        let mut pointer_width = None;
+        let mut endian = None;
+        let mut panic = None;
+
+        for config in
+            rustc_output(config, &["--print=cfg", "--target", &config.target]).trim().lines()
+        {
+            let (name, value) = config
+                .split_once("=\"")
+                .map(|(name, value)| {
+                    (
+                        name,
+                        Some(
+                            value
+                                .strip_suffix("\"")
+                                .expect("key-value pair should be properly quoted"),
+                        ),
+                    )
+                })
+                .unwrap_or_else(|| (config, None));
+
+            match name {
+                "target_arch" => {
+                    arch = Some(value.expect("target_arch should be a key-value pair").to_string());
+                }
+                "target_os" => {
+                    os = Some(value.expect("target_os sould be a key-value pair").to_string());
+                }
+                "target_env" => {
+                    env = Some(value.expect("target_env should be a key-value pair").to_string());
+                }
+                "target_abi" => {
+                    abi = Some(value.expect("target_abi should be a key-value pair").to_string());
+                }
+                "target_family" => {
+                    families
+                        .push(value.expect("target_family should be a key-value pair").to_string());
+                }
+                "target_pointer_width" => {
+                    pointer_width = Some(
+                        value
+                            .expect("target_pointer_width should be a key-value pair")
+                            .parse::<u32>()
+                            .expect("target_pointer_width should be a valid u32"),
+                    );
+                }
+                "target_endian" => {
+                    endian = Some(match value.expect("target_endian should be a key-value pair") {
+                        "big" => Endian::Big,
+                        "little" => Endian::Little,
+                        _ => panic!("target_endian should be either 'big' or 'little'"),
+                    });
+                }
+                "panic" => {
+                    panic = Some(match value.expect("panic should be a key-value pair") {
+                        "abort" => PanicStrategy::Abort,
+                        "unwind" => PanicStrategy::Unwind,
+                        _ => panic!("panic should be either 'abort' or 'unwind'"),
+                    });
+                }
+                _ => (),
+            }
+        }
+
+        TargetCfg {
+            arch: arch.expect("target configuration should specify target_arch"),
+            os: os.expect("target configuration should specify target_os"),
+            env: env.expect("target configuration should specify target_env"),
+            abi: abi.expect("target configuration should specify target_abi"),
+            families,
+            pointer_width: pointer_width
+                .expect("target configuration should specify target_pointer_width"),
+            endian: endian.expect("target configuration should specify target_endian"),
+            panic: panic.expect("target configuration should specify panic"),
+        }
+    }
 }
 
 #[derive(Clone, Debug, serde::Deserialize)]
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 4ede460..5bc4d16 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -32,6 +32,7 @@
 use std::str;
 use std::sync::Arc;
 
+use anyhow::Context;
 use glob::glob;
 use once_cell::sync::Lazy;
 use tracing::*;
@@ -131,7 +132,11 @@
     }
 
     let cx = TestCx { config: &config, props: &props, testpaths, revision };
-    create_dir_all(&cx.output_base_dir()).unwrap();
+    create_dir_all(&cx.output_base_dir())
+        .with_context(|| {
+            format!("failed to create output base directory {}", cx.output_base_dir().display())
+        })
+        .unwrap();
     if props.incremental {
         cx.init_incremental_test();
     }
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 4170c32..c8a3700 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -139,18 +139,18 @@
 type Cache = HashMap<String, FileEntry>;
 
 fn small_url_encode(s: &str) -> String {
-    s.replace("<", "%3C")
-        .replace(">", "%3E")
-        .replace(" ", "%20")
-        .replace("?", "%3F")
-        .replace("'", "%27")
-        .replace("&", "%26")
-        .replace(",", "%2C")
-        .replace(":", "%3A")
-        .replace(";", "%3B")
-        .replace("[", "%5B")
-        .replace("]", "%5D")
-        .replace("\"", "%22")
+    s.replace('<', "%3C")
+        .replace('>', "%3E")
+        .replace(' ', "%20")
+        .replace('?', "%3F")
+        .replace('\'', "%27")
+        .replace('&', "%26")
+        .replace(',', "%2C")
+        .replace(':', "%3A")
+        .replace(';', "%3B")
+        .replace('[', "%5B")
+        .replace(']', "%5D")
+        .replace('\"', "%22")
 }
 
 impl Checker {
@@ -267,7 +267,6 @@
                 FileEntry::OtherFile => return,
                 FileEntry::Redirect { target } => {
                     let t = target.clone();
-                    drop(target);
                     let (target, redir_entry) = self.load_file(&t, report);
                     match redir_entry {
                         FileEntry::Missing => {
@@ -391,7 +390,7 @@
         const ERROR_INVALID_NAME: i32 = 123;
 
         let pretty_path =
-            file.strip_prefix(&self.root).unwrap_or(&file).to_str().unwrap().to_string();
+            file.strip_prefix(&self.root).unwrap_or(file).to_str().unwrap().to_string();
 
         let entry =
             self.cache.entry(pretty_path.clone()).or_insert_with(|| match fs::metadata(file) {
@@ -470,10 +469,8 @@
         // NOTE: This cannot be added to `LINKCHECK_EXCEPTIONS` because the resolved path
         // calculated in `check` function is outside `build/<triple>/doc` dir.
         // So the `strip_prefix` method just returns the old absolute broken path.
-        if file.ends_with("std/primitive.slice.html") {
-            if link.ends_with("primitive.slice.html") {
-                return true;
-            }
+        if file.ends_with("std/primitive.slice.html") && link.ends_with("primitive.slice.html") {
+            return true;
         }
         false
     }
@@ -545,7 +542,7 @@
 fn parse_ids(ids: &mut HashSet<String>, file: &str, source: &str, report: &mut Report) {
     if ids.is_empty() {
         with_attrs_in_source(source, " id", |fragment, i, _| {
-            let frag = fragment.trim_start_matches("#").to_owned();
+            let frag = fragment.trim_start_matches('#').to_owned();
             let encoded = small_url_encode(&frag);
             if !ids.insert(frag) {
                 report.errors += 1;
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index e2a7d48..7bedb5d 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -184,6 +184,16 @@
 ]
 
 [[package]]
+name = "ctrlc"
+version = "3.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
+dependencies = [
+ "nix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
 name = "diff"
 version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -421,6 +431,7 @@
 version = "0.1.0"
 dependencies = [
  "colored",
+ "ctrlc",
  "env_logger",
  "getrandom",
  "lazy_static",
@@ -438,6 +449,18 @@
 ]
 
 [[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
+[[package]]
 name = "object"
 version = "0.30.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -714,6 +737,12 @@
 checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
 name = "syn"
 version = "2.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -820,9 +849,9 @@
 
 [[package]]
 name = "ui_test"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
+checksum = "191a442639ea102fa62671026047e51d574bfda44b7fdf32151d7314624c1cd2"
 dependencies = [
  "bstr",
  "cargo-platform",
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index f6f8183..683f99c 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -29,6 +29,7 @@
 # for more information.
 rustc-workspace-hack = "1.0.0"
 measureme = "10.0.0"
+ctrlc = "3.2.5"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
@@ -39,7 +40,7 @@
 
 [dev-dependencies]
 colored = "2"
-ui_test = "0.9"
+ui_test = "0.10"
 rustc_version = "0.4"
 # Features chosen to match those required by env_logger, to avoid rebuilds
 regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] }
diff --git a/src/tools/miri/cargo-miri/src/arg.rs b/src/tools/miri/cargo-miri/src/arg.rs
index e8bac46..d721606 100644
--- a/src/tools/miri/cargo-miri/src/arg.rs
+++ b/src/tools/miri/cargo-miri/src/arg.rs
@@ -40,7 +40,8 @@
         if arg == "--" {
             // Stop searching at `--`.
             self.args = None;
-            return None;
+            // But yield the `--` so that it does not get lost!
+            return Some(Err(Cow::Borrowed("--")));
         }
         // These branches cannot be merged if we want to avoid the allocation in the `Borrowed` branch.
         match &arg {
@@ -79,9 +80,8 @@
     ) -> impl Iterator<Item = Result<String, String>> + 'a {
         ArgSplitFlagValue::new(args.map(Cow::Owned), name).map(|x| {
             match x {
-                Ok(Cow::Owned(s)) => Ok(s),
-                Err(Cow::Owned(s)) => Err(s),
-                _ => panic!("iterator converted owned to borrowed"),
+                Ok(s) => Ok(s.into_owned()),
+                Err(s) => Err(s.into_owned()),
             }
         })
     }
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index 37f66d0..465e4a1 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -113,30 +113,17 @@
     };
     let metadata = get_cargo_metadata();
     let mut cmd = cargo();
-    cmd.arg(cargo_cmd);
-
-    // Forward all arguments before `--` other than `--target-dir` and its value to Cargo.
-    // (We want to *change* the target-dir value, so we must not forward it.)
-    let mut target_dir = None;
-    for arg in ArgSplitFlagValue::from_string_iter(&mut args, "--target-dir") {
-        match arg {
-            Ok(value) => {
-                if target_dir.is_some() {
-                    show_error!("`--target-dir` is provided more than once");
-                }
-                target_dir = Some(value.into());
-            }
-            Err(arg) => {
-                cmd.arg(arg);
-            }
-        }
+    cmd.arg(&cargo_cmd);
+    // In nextest we have to also forward the main `verb`.
+    if cargo_cmd == "nextest" {
+        cmd.arg(
+            args.next()
+                .unwrap_or_else(|| show_error!("`cargo miri nextest` expects a verb (e.g. `run`)")),
+        );
     }
-    // Detect the target directory if it's not specified via `--target-dir`.
-    // (`cargo metadata` does not support `--target-dir`, that's why we have to handle this ourselves.)
-    let target_dir = target_dir.get_or_insert_with(|| metadata.target_directory.clone());
-    // Set `--target-dir` to `miri` inside the original target directory.
-    target_dir.push("miri");
-    cmd.arg("--target-dir").arg(target_dir);
+    // We set the following flags *before* forwarding more arguments.
+    // This is needed to fix <https://github.com/rust-lang/miri/issues/2829>: cargo will stop
+    // interpreting things as flags when it sees the first positional argument.
 
     // Make sure the build target is explicitly set.
     // This is needed to make the `target.runner` settings do something,
@@ -154,8 +141,23 @@
     cmd.arg("--config")
         .arg(format!("target.'cfg(all())'.runner=[{cargo_miri_path_for_toml}, 'runner']"));
 
-    // Forward all further arguments after `--` to cargo.
-    cmd.arg("--").args(args);
+    // Set `--target-dir` to `miri` inside the original target directory.
+    let mut target_dir = match get_arg_flag_value("--target-dir") {
+        Some(dir) => PathBuf::from(dir),
+        None => metadata.target_directory.clone().into_std_path_buf(),
+    };
+    target_dir.push("miri");
+    cmd.arg("--target-dir").arg(target_dir);
+
+    // *After* we set all the flags that need setting, forward everything else. Make sure to skip
+    // `--target-dir` (which would otherwise be set twice).
+    for arg in
+        ArgSplitFlagValue::from_string_iter(&mut args, "--target-dir").filter_map(Result::err)
+    {
+        cmd.arg(arg);
+    }
+    // Forward all further arguments (not consumed by `ArgSplitFlagValue`) to cargo.
+    cmd.args(args);
 
     // Set `RUSTC_WRAPPER` to ourselves.  Cargo will prepend that binary to its usual invocation,
     // i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index 4be970b..48a46a7 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -306,7 +306,7 @@
     # Only in root project as `cargo-miri` has no tests.
     $CARGO test $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@"
     ;;
-run)
+run|run-dep)
     # Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
     # that we set the MIRI_SYSROOT up the right way.
     FOUND_TARGET_OPT=0
@@ -323,11 +323,17 @@
         # Make sure Miri actually uses this target.
         MIRIFLAGS="$MIRIFLAGS --target $MIRI_TEST_TARGET"
     fi
+
     # First build and get a sysroot.
     $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml
     find_sysroot
     # Then run the actual command.
-    exec $CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- $MIRIFLAGS "$@"
+    
+    if [ "$COMMAND" = "run-dep" ]; then
+        exec $CARGO test --test compiletest $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- --miri-run-dep-mode $MIRIFLAGS "$@"
+    else
+        exec $CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- $MIRIFLAGS "$@"
+    fi
     ;;
 fmt)
     find "$MIRIDIR" -not \( -name target -prune \) -name '*.rs' \
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 4268782..0bff100 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-0b795044c6f0854445f1f2bb6443e87848e150d1
+8b4b20836b832e91aa605a2faf5e2a55190202c8
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 28f9912..083dd48 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -28,8 +28,8 @@
     middle::exported_symbols::{
         ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
     },
-    query::LocalCrate,
-    ty::{query::ExternProviders, TyCtxt},
+    query::{ExternProviders, LocalCrate},
+    ty::TyCtxt,
 };
 use rustc_session::config::OptLevel;
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
index 064dbe0..a1e9491 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
@@ -83,7 +83,7 @@
         self.borrows.truncate(write_idx);
 
         #[cfg(not(feature = "stack-cache"))]
-        drop(first_removed); // This is only needed for the stack-cache
+        let _unused = first_removed; // This is only needed for the stack-cache
 
         #[cfg(feature = "stack-cache")]
         if let Some(first_removed) = first_removed {
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index e9bbae4..d85cac7 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -3,6 +3,7 @@
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
 use std::num::TryFromIntError;
+use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
 use std::task::Poll;
 use std::time::{Duration, SystemTime};
 
@@ -1012,8 +1013,24 @@
     /// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
     /// termination).
     fn run_threads(&mut self) -> InterpResult<'tcx, !> {
+        static SIGNALED: AtomicBool = AtomicBool::new(false);
+        ctrlc::set_handler(move || {
+            // Indicate that we have ben signaled to stop. If we were already signaled, exit
+            // immediately. In our interpreter loop we try to consult this value often, but if for
+            // whatever reason we don't get to that check or the cleanup we do upon finding that
+            // this bool has become true takes a long time, the exit here will promptly exit the
+            // process on the second Ctrl-C.
+            if SIGNALED.swap(true, Relaxed) {
+                std::process::exit(1);
+            }
+        })
+        .unwrap();
         let this = self.eval_context_mut();
         loop {
+            if SIGNALED.load(Relaxed) {
+                this.machine.handle_abnormal_termination();
+                std::process::exit(1);
+            }
             match this.machine.threads.schedule(&this.machine.clock)? {
                 SchedulingAction::ExecuteStep => {
                     if !this.step()? {
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index a93f3eb..e3f81a7 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -289,7 +289,7 @@
                     (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
                 ],
             InvalidProgram(
-                InvalidProgramInfo::AlreadyReported(rustc_errors::ErrorGuaranteed { .. })
+                InvalidProgramInfo::AlreadyReported(_)
             ) => {
                 // This got already reported. No point in reporting it again.
                 return None;
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index fc93808..893a4db 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -47,7 +47,6 @@
 extern crate rustc_middle;
 extern crate rustc_const_eval;
 extern crate rustc_data_structures;
-extern crate rustc_errors;
 extern crate rustc_hir;
 extern crate rustc_index;
 extern crate rustc_session;
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 32717a0..0ba7dad 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -651,6 +651,10 @@
 
     /// Sets up the "extern statics" for this machine.
     fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
+        // "__rust_no_alloc_shim_is_unstable"
+        let val = ImmTy::from_int(0, this.machine.layouts.u8);
+        Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
+
         match this.tcx.sess.target.os.as_ref() {
             "linux" => {
                 // "environ"
@@ -713,6 +717,15 @@
         let def_id = frame.instance.def_id();
         def_id.is_local() || self.local_crates.contains(&def_id.krate)
     }
+
+    /// Called when the interpreter is going to shut down abnormally, such as due to a Ctrl-C.
+    pub(crate) fn handle_abnormal_termination(&mut self) {
+        // All strings in the profile data are stored in a single string table which is not
+        // written to disk until the profiler is dropped. If the interpreter exits without dropping
+        // the profiler, it is not possible to interpret the profile data and all measureme tools
+        // will panic when given the file.
+        drop(self.profiler.take());
+    }
 }
 
 impl VisitTags for MiriMachine<'_, '_> {
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index 1e4ab2f..3239912 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -102,7 +102,7 @@
                 let ptr_layout = this.layout_of(ptr_ty)?;
 
                 for (i, ptr) in ptrs.into_iter().enumerate() {
-                    let offset = ptr_layout.size * i.try_into().unwrap();
+                    let offset = ptr_layout.size.checked_mul(i.try_into().unwrap(), this).unwrap();
 
                     let op_place = buf_place.offset(offset, ptr_layout, this)?;
 
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 44bca37..7436499 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -166,7 +166,7 @@
                     dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| {
                         // We add 1 to the number because that's what rustc also does everywhere it
                         // calls `CrateNum::new`...
-                        #[allow(clippy::integer_arithmetic)]
+                        #[allow(clippy::arithmetic_side_effects)]
                         (linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
                     }),
                 ) {
@@ -347,7 +347,6 @@
     /// Emulates calling the internal __rust_* allocator functions
     fn emulate_allocator(
         &mut self,
-        symbol: Symbol,
         default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>,
     ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
         let this = self.eval_context_mut();
@@ -359,11 +358,12 @@
 
         match allocator_kind {
             AllocatorKind::Global => {
-                let (body, instance) = this
-                    .lookup_exported_symbol(symbol)?
-                    .expect("symbol should be present if there is a global allocator");
-
-                Ok(EmulateByNameResult::MirBody(body, instance))
+                // When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
+                // of this attribute. As such we have to call an exported Rust function,
+                // and not execute any Miri shim. Somewhat unintuitively doing so is done
+                // by returning `NotSupported`, which triggers the `lookup_exported_symbol`
+                // fallback case in `emulate_foreign_item`.
+                return Ok(EmulateByNameResult::NotSupported);
             }
             AllocatorKind::Default => {
                 default(this)?;
@@ -558,11 +558,13 @@
 
             // Rust allocation
             "__rust_alloc" | "miri_alloc" => {
-                let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
-                let size = this.read_target_usize(size)?;
-                let align = this.read_target_usize(align)?;
-
                 let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
+                    // Only call `check_shim` when `#[global_allocator]` isn't used. When that
+                    // macro is used, we act like no shim exists, so that the exported function can run.
+                    let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+                    let size = this.read_target_usize(size)?;
+                    let align = this.read_target_usize(align)?;
+
                     Self::check_alloc_request(size, align)?;
 
                     let memory_kind = match link_name.as_str() {
@@ -581,8 +583,7 @@
                 };
 
                 match link_name.as_str() {
-                    "__rust_alloc" =>
-                        return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
+                    "__rust_alloc" => return this.emulate_allocator(default),
                     "miri_alloc" => {
                         default(this)?;
                         return Ok(EmulateByNameResult::NeedsJumping);
@@ -591,11 +592,13 @@
                 }
             }
             "__rust_alloc_zeroed" => {
-                let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
-                let size = this.read_target_usize(size)?;
-                let align = this.read_target_usize(align)?;
+                return this.emulate_allocator(|this| {
+                    // See the comment for `__rust_alloc` why `check_shim` is only called in the
+                    // default case.
+                    let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+                    let size = this.read_target_usize(size)?;
+                    let align = this.read_target_usize(align)?;
 
-                return this.emulate_allocator(Symbol::intern("__rg_alloc_zeroed"), |this| {
                     Self::check_alloc_request(size, align)?;
 
                     let ptr = this.allocate_ptr(
@@ -614,12 +617,15 @@
                 });
             }
             "__rust_dealloc" | "miri_dealloc" => {
-                let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
-                let ptr = this.read_pointer(ptr)?;
-                let old_size = this.read_target_usize(old_size)?;
-                let align = this.read_target_usize(align)?;
-
                 let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
+                    // See the comment for `__rust_alloc` why `check_shim` is only called in the
+                    // default case.
+                    let [ptr, old_size, align] =
+                        this.check_shim(abi, Abi::Rust, link_name, args)?;
+                    let ptr = this.read_pointer(ptr)?;
+                    let old_size = this.read_target_usize(old_size)?;
+                    let align = this.read_target_usize(align)?;
+
                     let memory_kind = match link_name.as_str() {
                         "__rust_dealloc" => MiriMemoryKind::Rust,
                         "miri_dealloc" => MiriMemoryKind::Miri,
@@ -635,8 +641,9 @@
                 };
 
                 match link_name.as_str() {
-                    "__rust_dealloc" =>
-                        return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
+                    "__rust_dealloc" => {
+                        return this.emulate_allocator(default);
+                    }
                     "miri_dealloc" => {
                         default(this)?;
                         return Ok(EmulateByNameResult::NeedsJumping);
@@ -645,15 +652,17 @@
                 }
             }
             "__rust_realloc" => {
-                let [ptr, old_size, align, new_size] =
-                    this.check_shim(abi, Abi::Rust, link_name, args)?;
-                let ptr = this.read_pointer(ptr)?;
-                let old_size = this.read_target_usize(old_size)?;
-                let align = this.read_target_usize(align)?;
-                let new_size = this.read_target_usize(new_size)?;
-                // No need to check old_size; we anyway check that they match the allocation.
+                return this.emulate_allocator(|this| {
+                    // See the comment for `__rust_alloc` why `check_shim` is only called in the
+                    // default case.
+                    let [ptr, old_size, align, new_size] =
+                        this.check_shim(abi, Abi::Rust, link_name, args)?;
+                    let ptr = this.read_pointer(ptr)?;
+                    let old_size = this.read_target_usize(old_size)?;
+                    let align = this.read_target_usize(align)?;
+                    let new_size = this.read_target_usize(new_size)?;
+                    // No need to check old_size; we anyway check that they match the allocation.
 
-                return this.emulate_allocator(Symbol::intern("__rg_realloc"), |this| {
                     Self::check_alloc_request(new_size, align)?;
 
                     let align = Align::from_bytes(align).unwrap();
@@ -707,7 +716,7 @@
                     .position(|&c| c == val)
                 {
                     let idx = u64::try_from(idx).unwrap();
-                    #[allow(clippy::integer_arithmetic)] // idx < num, so this never wraps
+                    #[allow(clippy::arithmetic_side_effects)] // idx < num, so this never wraps
                     let new_ptr = ptr.offset(Size::from_bytes(num - idx - 1), this)?;
                     this.write_pointer(new_ptr, dest)?;
                 } else {
@@ -916,10 +925,10 @@
                 let a = this.read_scalar(a)?.to_u64()?;
                 let b = this.read_scalar(b)?.to_u64()?;
 
-                #[allow(clippy::integer_arithmetic)]
+                #[allow(clippy::arithmetic_side_effects)]
                 // adding two u64 and a u8 cannot wrap in a u128
                 let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
-                #[allow(clippy::integer_arithmetic)] // it's a u128, we can shift by 64
+                #[allow(clippy::arithmetic_side_effects)] // it's a u128, we can shift by 64
                 let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());
 
                 let c_out_field = this.place_field(dest, 0)?;
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index d101f8d..1995db7 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -421,14 +421,18 @@
                 }
             }
             #[rustfmt::skip]
-            "cast" | "as" => {
+            "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
                 let (dest, dest_len) = this.place_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
+                let unsafe_cast = intrinsic_name == "cast";
                 let safe_cast = intrinsic_name == "as";
+                let ptr_cast = intrinsic_name == "cast_ptr";
+                let expose_cast = intrinsic_name == "expose_addr";
+                let from_exposed_cast = intrinsic_name == "from_exposed_addr";
 
                 for i in 0..dest_len {
                     let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
@@ -436,19 +440,31 @@
 
                     let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
                         // Int-to-(int|float): always safe
-                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) =>
+                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast =>
                             this.int_to_int_or_float(&op, dest.layout.ty)?,
                         // Float-to-float: always safe
-                        (ty::Float(_), ty::Float(_)) =>
+                        (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
                             this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in safe mode
                         (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
                             this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in unchecked mode
-                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
+                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),
-                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
+                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(),
+                        // Ptr-to-ptr cast
+                        (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => {
+                            this.ptr_to_ptr(&op, dest.layout.ty)?
+                        }
+                        // Ptr/Int casts
+                        (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => {
+                            this.pointer_expose_address_cast(&op, dest.layout.ty)?
+                        }
+                        (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => {
+                            this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?
+                        }
+                        // Error otherwise
                         _ =>
                             throw_unsup_format!(
                                 "Unsupported SIMD cast from element type {from_ty} to {to_ty}",
@@ -547,7 +563,11 @@
                 let (op, op_len) = this.operand_to_simd(op)?;
                 let bitmask_len = op_len.max(8);
 
-                assert!(dest.layout.ty.is_integral());
+                // Returns either an unsigned integer or array of `u8`.
+                assert!(
+                    dest.layout.ty.is_integral()
+                        || matches!(dest.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8)
+                );
                 assert!(bitmask_len <= 64);
                 assert_eq!(bitmask_len, dest.layout.size.bits());
                 let op_len = u32::try_from(op_len).unwrap();
@@ -561,7 +581,10 @@
                             .unwrap();
                     }
                 }
-                this.write_int(res, dest)?;
+                // We have to force the place type to be an int so that we can write `res` into it.
+                let mut dest = this.force_allocation(dest)?;
+                dest.layout = this.machine.layouts.uint(dest.layout.size).unwrap();
+                this.write_int(res, &dest.into())?;
             }
 
             name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"),
@@ -589,7 +612,7 @@
     assert!(idx < vec_len);
     match endianness {
         Endian::Little => idx,
-        #[allow(clippy::integer_arithmetic)] // idx < vec_len
+        #[allow(clippy::arithmetic_side_effects)] // idx < vec_len
         Endian::Big => vec_len - 1 - idx, // reverse order of bits
     }
 }
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 918efda..a423a07 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::integer_arithmetic)]
+#![warn(clippy::arithmetic_side_effects)]
 
 mod backtrace;
 #[cfg(target_os = "linux")]
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index 2f24c00..756dec1 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -108,7 +108,7 @@
         Ok(0)
     }
 
-    #[allow(non_snake_case, clippy::integer_arithmetic)]
+    #[allow(non_snake_case, clippy::arithmetic_side_effects)]
     fn GetSystemTimeAsFileTime(
         &mut self,
         LPFILETIME_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index 685feea..62bd087 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -56,7 +56,7 @@
 impl<'tcx> TlsData<'tcx> {
     /// Generate a new TLS key with the given destructor.
     /// `max_size` determines the integer size the key has to fit in.
-    #[allow(clippy::integer_arithmetic)]
+    #[allow(clippy::arithmetic_side_effects)]
     pub fn create_tls_key(
         &mut self,
         dtor: Option<ty::Instance<'tcx>>,
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index abec782..d1b09cd 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -458,7 +458,7 @@
 }
 
 impl DirHandler {
-    #[allow(clippy::integer_arithmetic)]
+    #[allow(clippy::arithmetic_side_effects)]
     fn insert_new(&mut self, read_dir: ReadDir) -> u64 {
         let id = self.next_id;
         self.next_id += 1;
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index ffe3ca6..6889c43 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -247,7 +247,7 @@
             // before doing the syscall.
             this.atomic_fence(AtomicFenceOrd::SeqCst)?;
             let mut n = 0;
-            #[allow(clippy::integer_arithmetic)]
+            #[allow(clippy::arithmetic_side_effects)]
             for _ in 0..val {
                 if let Some(thread) = this.futex_wake(addr_usize, bitset) {
                     this.unblock_thread(thread);
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index f72ba5c..b8bb7f6 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -219,7 +219,7 @@
                     .copied()
                     .scan(Size::ZERO, |a, x| {
                         let res = Some(*a);
-                        *a += x;
+                        *a = a.checked_add(x, this).unwrap();
                         res
                     })
                     .collect();
diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs
index 8bffa99..d9ae1b2 100644
--- a/src/tools/miri/src/shims/windows/handle.rs
+++ b/src/tools/miri/src/shims/windows/handle.rs
@@ -62,7 +62,7 @@
         let floor_log2 = variant_count.ilog2();
 
         // we need to add one for non powers of two to compensate for the difference
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         if variant_count.is_power_of_two() { floor_log2 } else { floor_log2 + 1 }
     }
 
@@ -87,7 +87,7 @@
 
         // packs the data into the lower `data_size` bits
         // and packs the discriminant right above the data
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         return discriminant << data_size | data;
     }
 
@@ -106,11 +106,11 @@
         let data_size = u32::BITS.checked_sub(disc_size).unwrap();
 
         // the lower `data_size` bits of this mask are 1
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         let data_mask = 2u32.pow(data_size) - 1;
 
         // the discriminant is stored right above the lower `data_size` bits
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         let discriminant = handle >> data_size;
 
         // the data is stored in the lower `data_size` bits
diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py
index 46b3afa..9df90c7 100755
--- a/src/tools/miri/test-cargo-miri/run-test.py
+++ b/src/tools/miri/test-cargo-miri/run-test.py
@@ -108,8 +108,9 @@
         env={'MIRITESTVAR': "wrongval"}, # changing the env var causes a rebuild (re-runs build.rs),
                                          # so keep it set
     )
+    # This also covers passing arguments without `--`: Cargo will forward unused positional arguments to the program.
     test("`cargo miri run` (with arguments and target)",
-        cargo_miri("run") + ["--bin", "cargo-miri-test", "--", "hello world", '"hello world"', r'he\\llo\"world'],
+        cargo_miri("run") + ["--bin", "cargo-miri-test", "hello world", '"hello world"', r'he\\llo\"world'],
         "run.args.stdout.ref", "run.args.stderr.ref",
     )
     test("`cargo miri r` (subcrate, no isolation)",
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index e6388c5..fa06c4b 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -1,5 +1,6 @@
 use colored::*;
 use regex::bytes::Regex;
+use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::{env, process::Command};
 use ui_test::status_emitter::StatusEmitter;
@@ -45,7 +46,7 @@
     so_file_path
 }
 
-fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
+fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> Config {
     // Miri is rustc-like, so we create a default builder for rustc and modify it
     let mut program = CommandBuilder::rustc();
     program.program = miri_path();
@@ -103,6 +104,26 @@
         ..Config::default()
     };
 
+    let use_std = env::var_os("MIRI_NO_STD").is_none();
+
+    if with_dependencies && use_std {
+        config.dependencies_crate_manifest_path =
+            Some(Path::new("test_dependencies").join("Cargo.toml"));
+        config.dependency_builder.args = vec![
+            "run".into(),
+            "--manifest-path".into(),
+            "cargo-miri/Cargo.toml".into(),
+            "--".into(),
+            "miri".into(),
+            "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
+        ];
+    }
+    config
+}
+
+fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
+    let mut config = test_config(target, path, mode, with_dependencies);
+
     // Handle command-line arguments.
     let mut after_dashdash = false;
     config.path_filter.extend(std::env::args().skip(1).filter(|arg| {
@@ -126,21 +147,6 @@
         }
     }));
 
-    let use_std = env::var_os("MIRI_NO_STD").is_none();
-
-    if with_dependencies && use_std {
-        config.dependencies_crate_manifest_path =
-            Some(Path::new("test_dependencies").join("Cargo.toml"));
-        config.dependency_builder.args = vec![
-            "run".into(),
-            "--manifest-path".into(),
-            "cargo-miri/Cargo.toml".into(),
-            "--".into(),
-            "miri".into(),
-            "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
-        ];
-    }
-
     eprintln!("   Compiler: {}", config.program.display());
     ui_test::run_tests_generic(
         config,
@@ -226,8 +232,18 @@
 
 fn main() -> Result<()> {
     ui_test::color_eyre::install()?;
+
     let target = get_target();
 
+    let mut args = std::env::args_os();
+
+    // Skip the program name and check whether this is a `./miri run-dep` invocation
+    if let Some(first) = args.nth(1) {
+        if first == "--miri-run-dep-mode" {
+            return run_dep_mode(target, args);
+        }
+    }
+
     // Add a test env var to do environment communication tests.
     env::set_var("MIRI_ENV_VAR_TEST", "0");
     // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
@@ -250,6 +266,21 @@
     Ok(())
 }
 
+fn run_dep_mode(target: String, mut args: impl Iterator<Item = OsString>) -> Result<()> {
+    let path = args.next().expect("./miri run-dep must be followed by a file name");
+    let mut config = test_config(&target, "", Mode::Yolo, /* with dependencies */ true);
+    config.program.args.remove(0); // remove the `--error-format=json` argument
+    config.program.args.push("--color".into());
+    config.program.args.push("always".into());
+    let mut cmd = ui_test::test_command(config, Path::new(&path))?;
+    // Separate the arguments to the `cargo miri` invocation from
+    // the arguments to the interpreted prog
+    cmd.arg("--");
+    cmd.args(args);
+    println!("{cmd:?}");
+    if cmd.spawn()?.wait()?.success() { Ok(()) } else { std::process::exit(1) }
+}
+
 /// This is a custom renderer for `ui_test` output that does not emit github actions
 /// `group`s, while still producing regular github actions messages on test failures.
 struct TextAndGha;
diff --git a/src/tools/miri/tests/fail/memleak.stderr b/src/tools/miri/tests/fail/memleak.stderr
index 6d9b664..12bb944 100644
--- a/src/tools/miri/tests/fail/memleak.stderr
+++ b/src/tools/miri/tests/fail/memleak.stderr
@@ -1,8 +1,8 @@
 error: memory leaked: ALLOC (Rust heap, size: 4, align: 4), allocated here:
   --> RUSTLIB/alloc/src/alloc.rs:LL:CC
    |
-LL |     unsafe { __rust_alloc(layout.size(), layout.align()) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         __rust_alloc(layout.size(), layout.align())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr
index 0e1146c..87c5f46 100644
--- a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr
+++ b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr
@@ -1,8 +1,8 @@
 error: memory leaked: ALLOC (Rust heap, size: 16, align: 4), allocated here:
   --> RUSTLIB/alloc/src/alloc.rs:LL:CC
    |
-LL |     unsafe { __rust_alloc(layout.size(), layout.align()) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         __rust_alloc(layout.size(), layout.align())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr
index 4979588..ec5f5f5 100644
--- a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr
+++ b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr
@@ -1,8 +1,8 @@
 error: memory leaked: ALLOC (Rust heap, size: 32, align: 8), allocated here:
   --> RUSTLIB/alloc/src/alloc.rs:LL:CC
    |
-LL |     unsafe { __rust_alloc(layout.size(), layout.align()) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         __rust_alloc(layout.size(), layout.align())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/never_say_never.rs b/src/tools/miri/tests/fail/never_say_never.rs
index f6d3dc7..fd082e3 100644
--- a/src/tools/miri/tests/fail/never_say_never.rs
+++ b/src/tools/miri/tests/fail/never_say_never.rs
@@ -6,10 +6,8 @@
 
 fn main() {
     let y = &5;
-    let x: ! = unsafe {
-        *(y as *const _ as *const !) //~ ERROR: entering unreachable code
-    };
-    f(x)
+    let x: ! = unsafe { *(y as *const _ as *const !) };
+    f(x) //~ ERROR: entering unreachable code
 }
 
 fn f(x: !) -> ! {
diff --git a/src/tools/miri/tests/fail/never_say_never.stderr b/src/tools/miri/tests/fail/never_say_never.stderr
index a2a63b8..9d3a8df 100644
--- a/src/tools/miri/tests/fail/never_say_never.stderr
+++ b/src/tools/miri/tests/fail/never_say_never.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: entering unreachable code
   --> $DIR/never_say_never.rs:LL:CC
    |
-LL |         *(y as *const _ as *const !)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code
+LL |     f(x)
+   |     ^^^^ entering unreachable code
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
index bf4204c..a5a1930 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
@@ -1,4 +1,4 @@
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {
     let target = &mut 42;
diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs
index 22ffa1b..b9199cf 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.rs
+++ b/src/tools/miri/tests/fail/terminate-terminator.rs
@@ -12,13 +12,13 @@
 
 #[inline(always)]
 fn has_cleanup() {
+    //~^ ERROR: panic in a function that cannot unwind
     let _f = Foo;
     panic!();
 }
 
 extern "C" fn panic_abort() {
     has_cleanup();
-    //~^ ERROR: panic in a function that cannot unwind
 }
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
index 8ce4bb7..d73e23a 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.stderr
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -6,15 +6,18 @@
   --> $DIR/terminate-terminator.rs:LL:CC
    |
 LL | / fn has_cleanup() {
+LL | |
 LL | |     let _f = Foo;
 LL | |     panic!();
 LL | | }
    | |_^ panic in a function that cannot unwind
-...
-LL |       has_cleanup();
-   |       ------------- in this inlined function call
    |
-   = note: inside `panic_abort` at $DIR/terminate-terminator.rs:LL:CC
+   = note: inside `has_cleanup` at $DIR/terminate-terminator.rs:LL:CC
+note: inside `panic_abort`
+  --> $DIR/terminate-terminator.rs:LL:CC
+   |
+LL |     has_cleanup();
+   |     ^^^^^^^^^^^^^
 note: inside `main`
   --> $DIR/terminate-terminator.rs:LL:CC
    |
diff --git a/src/tools/miri/tests/fail/uninit_buffer.rs b/src/tools/miri/tests/fail/uninit_buffer.rs
index 8a33005..d622b2f 100644
--- a/src/tools/miri/tests/fail/uninit_buffer.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer.rs
@@ -1,6 +1,6 @@
 //@error-in-other-file: memory is uninitialized at [0x4..0x10]
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::alloc::{alloc, dealloc, Layout};
 use std::slice::from_raw_parts;
diff --git a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
index e4d9404..ca82590 100644
--- a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
@@ -1,8 +1,7 @@
 //@error-in-other-file: memory is uninitialized at [0x4..0x8]
 //@normalize-stderr-test: "a[0-9]+" -> "ALLOC"
 #![feature(strict_provenance)]
-
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // Test printing allocations that contain single-byte provenance.
 
diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
new file mode 100644
index 0000000..303c998
--- /dev/null
+++ b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
@@ -0,0 +1,12 @@
+// Separate test without strict provenance
+//@compile-flags: -Zmiri-permissive-provenance
+#![feature(portable_simd, platform_intrinsics)]
+use std::ptr;
+use std::simd::*;
+
+fn main() {
+    // Pointer casts
+    let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast_ptr();
+    let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr();
+    let _ptrs = Simd::<*const i32, 4>::from_exposed_addr(addrs);
+}
diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs
index 173ac65..ee67a65 100644
--- a/src/tools/miri/tests/pass/portable-simd.rs
+++ b/src/tools/miri/tests/pass/portable-simd.rs
@@ -2,6 +2,10 @@
 #![feature(portable_simd, platform_intrinsics)]
 use std::simd::*;
 
+extern "platform-intrinsic" {
+    pub(crate) fn simd_bitmask<T, U>(x: T) -> U;
+}
+
 fn simd_ops_f32() {
     let a = f32x4::splat(10.0);
     let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
@@ -208,11 +212,40 @@
     assert_eq!(bitmask, 0b1010001101001001);
     assert_eq!(Mask::<i64, 16>::from_bitmask(bitmask), mask);
 
+    // Also directly call intrinsic, to test both kinds of return types.
+    unsafe {
+        let bitmask1: u16 = simd_bitmask(mask.to_int());
+        let bitmask2: [u8; 2] = simd_bitmask(mask.to_int());
+        if cfg!(target_endian = "little") {
+            assert_eq!(bitmask1, 0b1010001101001001);
+            assert_eq!(bitmask2, [0b01001001, 0b10100011]);
+        } else {
+            // All the bitstrings are reversed compared to above, but the array elements are in the
+            // same order.
+            assert_eq!(bitmask1, 0b1001001011000101);
+            assert_eq!(bitmask2, [0b10010010, 0b11000101]);
+        }
+    }
+
+    // Mask less than 8 bits long, which is a special case (padding with 0s).
     let values = [false, false, false, true];
     let mask = Mask::<i64, 4>::from_array(values);
     let bitmask = mask.to_bitmask();
     assert_eq!(bitmask, 0b1000);
     assert_eq!(Mask::<i64, 4>::from_bitmask(bitmask), mask);
+
+    // Also directly call intrinsic, to test both kinds of return types.
+    unsafe {
+        let bitmask1: u8 = simd_bitmask(mask.to_int());
+        let bitmask2: [u8; 1] = simd_bitmask(mask.to_int());
+        if cfg!(target_endian = "little") {
+            assert_eq!(bitmask1, 0b1000);
+            assert_eq!(bitmask2, [0b1000]);
+        } else {
+            assert_eq!(bitmask1, 0b0001);
+            assert_eq!(bitmask2, [0b0001]);
+        }
+    }
 }
 
 fn simd_cast() {
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index af245aa..3258a2b 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -31,7 +31,7 @@
 }
 
 fn host_to_target_path(path: String) -> PathBuf {
-    use std::ffi::{CStr, CString};
+    use std::ffi::{c_char, CStr, CString};
 
     let path = CString::new(path).unwrap();
     let mut out = Vec::with_capacity(1024);
diff --git a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
index 9f743f0..6e13a9e 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
@@ -1,7 +1,7 @@
 //@compile-flags: -Zmiri-retag-fields
 // Checks that the test does not run forever (which relies on a fast path).
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 fn main() {
     let array = [(); usize::MAX];
diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs
index 0aebfc4..5c9c18b 100644
--- a/src/tools/replace-version-placeholder/src/main.rs
+++ b/src/tools/replace-version-placeholder/src/main.rs
@@ -8,15 +8,13 @@
     let version_path = root_path.join("src").join("version");
     let version_str = t!(std::fs::read_to_string(&version_path), version_path);
     let version_str = version_str.trim();
-    walk::walk(
-        &root_path,
+    walk::walk_many(
+        &[&root_path.join("compiler"), &root_path.join("library")],
         |path, _is_dir| {
             walk::filter_dirs(path)
                 // We exempt these as they require the placeholder
                 // for their operation
                 || path.ends_with("compiler/rustc_attr/src/builtin.rs")
-                || path.ends_with("src/tools/tidy/src/features/version.rs")
-                || path.ends_with("src/tools/replace-version-placeholder")
         },
         &mut |entry, contents| {
             if !contents.contains(VERSION_PLACEHOLDER) {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index afa6bce..2e77811 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -117,6 +117,7 @@
     "autocfg",
     "bitflags",
     "block-buffer",
+    "byteorder", // via ruzstd in object in thorin-dwp
     "cc",
     "cfg-if",
     "chalk-derive",
@@ -145,6 +146,7 @@
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
     "fastrand",
+    "field-offset",
     "fixedbitset",
     "flate2",
     "fluent-bundle",
@@ -216,6 +218,7 @@
     "rustc-rayon",
     "rustc-rayon-core",
     "rustc_version",
+    "ruzstd", // via object in thorin-dwp
     "ryu",
     "scoped-tls",
     "scopeguard",
diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs
new file mode 100644
index 0000000..5f8eaeb
--- /dev/null
+++ b/src/tools/tidy/src/fluent_alphabetical.rs
@@ -0,0 +1,72 @@
+//! Checks that all Flunt files have messages in alphabetical order
+
+use crate::walk::{filter_dirs, walk};
+use std::{fs::OpenOptions, io::Write, path::Path};
+
+use regex::Regex;
+
+lazy_static::lazy_static! {
+    static ref MESSAGE: Regex = Regex::new(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#).unwrap();
+}
+
+fn filter_fluent(path: &Path) -> bool {
+    if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
+}
+
+fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) {
+    let mut matches = MESSAGE.captures_iter(fluent).peekable();
+    while let Some(m) = matches.next() {
+        if let Some(next) = matches.peek() {
+            let name = m.get(1).unwrap();
+            let next = next.get(1).unwrap();
+            if name.as_str() > next.as_str() {
+                tidy_error!(
+                    bad,
+                    "{filename}: message `{}` appears before `{}`, but is alphabetically later than it
+run tidy with `--bless` to sort the file correctly",
+                    name.as_str(),
+                    next.as_str()
+                );
+            }
+        } else {
+            break;
+        }
+    }
+}
+
+fn sort_messages(fluent: &str) -> String {
+    let mut chunks = vec![];
+    let mut cur = String::new();
+    for line in fluent.lines() {
+        if MESSAGE.is_match(line) {
+            chunks.push(std::mem::take(&mut cur));
+        }
+        cur += line;
+        cur.push('\n');
+    }
+    chunks.push(cur);
+    chunks.sort();
+    let mut out = chunks.join("");
+    out = out.trim().to_string();
+    out.push('\n');
+    out
+}
+
+pub fn check(path: &Path, bless: bool, bad: &mut bool) {
+    walk(
+        path,
+        |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
+        &mut |ent, contents| {
+            if bless {
+                let sorted = sort_messages(contents);
+                if sorted != contents {
+                    let mut f =
+                        OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap();
+                    f.write(sorted.as_bytes()).unwrap();
+                }
+            } else {
+                check_alphabetic(ent.path().to_str().unwrap(), contents, bad);
+            }
+        },
+    );
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 3500032..e467514 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -59,6 +59,7 @@
 pub mod error_codes;
 pub mod extdeps;
 pub mod features;
+pub mod fluent_alphabetical;
 pub mod mir_opt_tests;
 pub mod pal;
 pub mod primitive_docs;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index f59406c..1c4d96c 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -96,6 +96,7 @@
 
         // Checks that only make sense for the compiler.
         check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
+        check!(fluent_alphabetical, &compiler_path, bless);
 
         // Checks that only make sense for the std libs.
         check!(pal, &library_path);
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 5f388ee4..d0257d7 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -296,6 +296,12 @@
         if filename.contains("ignore-tidy") {
             return;
         }
+        // Shell completions are automatically generated
+        if let Some(p) = file.parent() {
+            if p.ends_with(Path::new("src/etc/completions")) {
+                return;
+            }
+        }
         // apfloat shouldn't be changed because of license problems
         if is_in(file, "compiler", "rustc_apfloat") {
             return;
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 9473eab..be3a5d3 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -4,13 +4,39 @@
 
 use ignore::Walk;
 use std::collections::HashMap;
+use std::ffi::OsStr;
 use std::fs;
 use std::path::{Path, PathBuf};
 
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 const ISSUES_ENTRY_LIMIT: usize = 1920;
-const ROOT_ENTRY_LIMIT: usize = 895;
+const ROOT_ENTRY_LIMIT: usize = 896;
+
+const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
+    "rs",     // test source files
+    "stderr", // expected stderr file, corresponds to a rs file
+    "stdout", // expected stdout file, corresponds to a rs file
+    "fixed",  // expected source file after applying fixes
+    "md",     // test directory descriptions
+    "ftl",    // translation tests
+];
+
+const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
+    "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint
+    "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs
+    "tests/ui/commandline-argfile-badutf8.args", // passing args via a file
+    "tests/ui/commandline-argfile.args", // passing args via a file
+    "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib
+    "tests/ui/include-macros/data.bin", // testing including data with the include macros
+    "tests/ui/include-macros/file.txt", // testing including data with the include macros
+    "tests/ui/macros/macro-expanded-include/file.txt", // testing including data with the include macros
+    "tests/ui/macros/not-utf8.bin", // testing including data with the include macros
+    "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include
+    "tests/ui/unused-crate-deps/test.mk", // why would you use make
+    "tests/ui/proc-macro/auxiliary/included-file.txt", // more include
+    "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer
+];
 
 fn check_entries(tests_path: &Path, bad: &mut bool) {
     let mut directories: HashMap<PathBuf, usize> = HashMap::new();
@@ -66,7 +92,14 @@
     let paths = [ui.as_path(), ui_fulldeps.as_path()];
     crate::walk::walk_no_read(&paths, |_, _| false, &mut |entry| {
         let file_path = entry.path();
-        if let Some(ext) = file_path.extension() {
+        if let Some(ext) = file_path.extension().and_then(OsStr::to_str) {
+            // files that are neither an expected extension or an exception should not exist
+            // they're probably typos or not meant to exist
+            if !(EXPECTED_TEST_FILE_EXTENSIONS.contains(&ext)
+                || EXTENSION_EXCEPTION_PATHS.iter().any(|path| file_path.ends_with(path)))
+            {
+                tidy_error!(bad, "file {} has unexpected extension {}", file_path.display(), ext);
+            }
             if ext == "stderr" || ext == "stdout" {
                 // Test output filenames have one of the formats:
                 // ```
diff --git a/tests/assembly/option-nonzero-eq.rs b/tests/assembly/option-nonzero-eq.rs
new file mode 100644
index 0000000..f5d88de
--- /dev/null
+++ b/tests/assembly/option-nonzero-eq.rs
@@ -0,0 +1,28 @@
+// revisions: WIN LIN
+// [WIN] only-windows
+// [LIN] only-linux
+// assembly-output: emit-asm
+// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
+// only-x86_64
+// ignore-sgx
+// ignore-debug
+
+use std::cmp::Ordering;
+
+// CHECK-lABEL: ordering_eq:
+#[no_mangle]
+pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
+    // Linux (System V): first two arguments are rdi then rsi
+    // Windows: first two arguments are rcx then rdx
+    // Both use rax for the return value.
+
+    // CHECK-NOT: mov
+    // CHECK-NOT: test
+    // CHECK-NOT: cmp
+
+    // LIN: cmp dil, sil
+    // WIN: cmp cl, dl
+    // CHECK-NEXT: sete al
+    // CHECK-NEXT: ret
+    l == r
+}
diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs
new file mode 100644
index 0000000..bea1aad
--- /dev/null
+++ b/tests/codegen/addr-of-mutate.rs
@@ -0,0 +1,34 @@
+// compile-flags: -C opt-level=3 -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+
+#![crate_type = "lib"]
+
+// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
+// See <https://github.com/rust-lang/rust/issues/111502>.
+
+// CHECK: i8 @foo(ptr noalias nocapture noundef dereferenceable(128) %x)
+#[no_mangle]
+pub fn foo(x: [u8; 128]) -> u8 {
+    let ptr = core::ptr::addr_of!(x).cast_mut();
+    unsafe {
+        (*ptr)[0] = 1;
+    }
+    x[0]
+}
+
+// CHECK: i1 @second(ptr noalias nocapture noundef dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+    let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
+    (*b_bool_ptr) = true;
+    a_ptr_and_b.1.1
+}
+
+// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
+// CHECK: i1 @third(ptr noalias nocapture noundef readonly dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+    let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
+    (*b_bool_ptr) = true;
+    a_ptr_and_b.1.1
+}
diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs
index c3ffaeb..f88d695 100644
--- a/tests/codegen/alloc-optimisation.rs
+++ b/tests/codegen/alloc-optimisation.rs
@@ -1,12 +1,13 @@
 //
 // no-system-llvm
 // compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 #[no_mangle]
 pub fn alloc_test(data: u32) {
     // CHECK-LABEL: @alloc_test
     // CHECK-NEXT: start:
+    // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
     // CHECK-NEXT: ret void
     let x = Box::new(data);
     drop(x);
diff --git a/tests/codegen/binary-search-index-no-bound-check.rs b/tests/codegen/binary-search-index-no-bound-check.rs
index c1766a4..595969a 100644
--- a/tests/codegen/binary-search-index-no-bound-check.rs
+++ b/tests/codegen/binary-search-index-no-bound-check.rs
@@ -9,7 +9,9 @@
 #[no_mangle]
 pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
     if let Ok(idx) = s.binary_search(&b'\\') {
         s[idx]
     } else {
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
index d82b737..e52392b 100644
--- a/tests/codegen/debug-vtable.rs
+++ b/tests/codegen/debug-vtable.rs
@@ -11,8 +11,6 @@
 
 // Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled.
 // This helps debuggers more reliably map from dyn pointer to concrete type.
-// CHECK: @vtable.0 = private constant <{
-// CHECK: @vtable.1 = private constant <{
 // CHECK: @vtable.2 = private constant <{
 // CHECK: @vtable.3 = private constant <{
 // CHECK: @vtable.4 = private constant <{
diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs
new file mode 100644
index 0000000..725e6fc
--- /dev/null
+++ b/tests/codegen/drop-in-place-noalias.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+// Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`.
+// Note that non-Unpin types should not get `noalias`, matching &mut behavior.
+
+#![crate_type="lib"]
+
+use std::marker::PhantomPinned;
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}({{.*\*|ptr}} noalias noundef align 4 dereferenceable(12) %{{.+}})
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}({{.*\*|ptr}} noundef nonnull align 4 %{{.+}})
+
+pub struct StructUnpin {
+    a: i32,
+    b: i32,
+    c: i32,
+}
+
+impl Drop for StructUnpin {
+    fn drop(&mut self) {}
+}
+
+pub struct StructNotUnpin {
+    a: i32,
+    b: i32,
+    c: i32,
+    p: PhantomPinned,
+}
+
+impl Drop for StructNotUnpin {
+    fn drop(&mut self) {}
+}
+
+pub unsafe fn main(x: StructUnpin, y: StructNotUnpin) {
+    drop(x);
+    drop(y);
+}
diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs
index df1080b..a09c795 100644
--- a/tests/codegen/fewer-names.rs
+++ b/tests/codegen/fewer-names.rs
@@ -13,8 +13,8 @@
 
     // NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
     // NO-NEXT:  start:
-    // NO-NEXT:    %z = add i32 %y, %x
-    // NO-NEXT:    ret i32 %z
+    // NO-NEXT:    %0 = add i32 %y, %x
+    // NO-NEXT:    ret i32 %0
     let z = x + y;
     z
 }
diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs
new file mode 100644
index 0000000..90b3c31
--- /dev/null
+++ b/tests/codegen/issues/issue-111603.rs
@@ -0,0 +1,28 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![feature(get_mut_unchecked, new_uninit)]
+
+use std::sync::Arc;
+
+// CHECK-LABEL: @new_uninit
+#[no_mangle]
+pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit();
+    unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]);
+    unsafe { arc.assume_init() }
+}
+
+// CHECK-LABEL: @new_uninit_slice
+#[no_mangle]
+pub fn new_uninit_slice(x: u64) -> Arc<[u64]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit_slice(1000);
+    for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } {
+        elem.write(x);
+    }
+    unsafe { arc.assume_init() }
+}
diff --git a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
index 8d07a67..2d77978 100644
--- a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
+++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
@@ -9,7 +9,10 @@
 #[no_mangle]
 pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         &s[..idx]
     } else {
@@ -21,7 +24,10 @@
 #[no_mangle]
 pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         &s[idx..]
     } else {
@@ -33,7 +39,10 @@
 #[no_mangle]
 pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         s[idx]
     } else {
@@ -44,7 +53,10 @@
 #[no_mangle]
 pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         &s[..idx]
     } else {
@@ -56,7 +68,10 @@
 #[no_mangle]
 pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         &s[idx..]
     } else {
@@ -68,7 +83,10 @@
 #[no_mangle]
 pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         s[idx]
     } else {
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index acf759e..c6b920c 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -13,8 +13,7 @@
 pub fn replace_big(dst: &mut Big, src: Big) -> Big {
     // Back in 1.68, this emitted six `memcpy`s.
     // `read_via_copy` in 1.69 got that down to three.
-    // `write_via_move` it was originally down to the essential two, however
-    // with nrvo disabled it is back at 3
+    // `write_via_move` and nvro get this down to the essential two.
     std::mem::replace(dst, src)
 }
 
@@ -26,11 +25,9 @@
 // For a large type, we expect exactly three `memcpy`s
 // CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %result, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %0, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
 // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %dest, {{i8\*|ptr}} align 8 %src, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %0, {{i8\*|ptr}} align 8 %result, i{{.*}} 56, i1 false)
-// CHECK-NOT: call void @llvm.memcpy
 
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/noalias-box-off.rs b/tests/codegen/noalias-box-off.rs
index afd17c7..c82c53b 100644
--- a/tests/codegen/noalias-box-off.rs
+++ b/tests/codegen/noalias-box-off.rs
@@ -4,5 +4,8 @@
 
 // CHECK-LABEL: @box_should_not_have_noalias_if_disabled(
 // CHECK-NOT: noalias
+// CHECK-SAME: %foo)
 #[no_mangle]
-pub fn box_should_not_have_noalias_if_disabled(_b: Box<u8>) {}
+pub fn box_should_not_have_noalias_if_disabled(foo: Box<u8>) {
+    drop(foo);
+}
diff --git a/tests/codegen/option-nonzero-eq.rs b/tests/codegen/option-nonzero-eq.rs
index 835decd..a394695f 100644
--- a/tests/codegen/option-nonzero-eq.rs
+++ b/tests/codegen/option-nonzero-eq.rs
@@ -7,6 +7,9 @@
 use core::num::{NonZeroU32, NonZeroI64};
 use core::ptr::NonNull;
 
+// See also tests/assembly/option-nonzero-eq.rs, for cases with `assume`s in the
+// LLVM and thus don't optimize down clearly here, but do in assembly.
+
 // CHECK-lABEL: @non_zero_eq
 #[no_mangle]
 pub fn non_zero_eq(l: Option<NonZeroU32>, r: Option<NonZeroU32>) -> bool {
@@ -33,12 +36,3 @@
     // CHECK-NEXT: ret i1
     l == r
 }
-
-// CHECK-lABEL: @ordering_eq
-#[no_mangle]
-pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
-    // CHECK: start:
-    // CHECK-NEXT: icmp eq i8
-    // CHECK-NEXT: ret i1
-    l == r
-}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
index 71e26e3..ebb26cd 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -44,7 +44,7 @@
 }
 
 // Trait implementation
-impl<T> Trait1<T> for Struct1<T> {
+impl<T, U> Trait1<T> for Struct1<U> {
     fn foo(&self) { }
 }
 
@@ -536,15 +536,15 @@
 // CHECK: ![[TYPE93]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"}
 // CHECK: ![[TYPE94]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"}
 // CHECK: ![[TYPE95]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_S0_E"}
-// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
+// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_S3_E"}
 // CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"}
 // CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"}
 // CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"}
@@ -566,9 +566,9 @@
 // CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32EE"}
 // CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_E"}
 // CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_S0_E"}
-// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_EE"}
-// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_E"}
-// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_S3_E"}
+// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32EE"}
+// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_E"}
+// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_S4_E"}
 // CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_EE"}
 // CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_E"}
 // CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_S0_E"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
index ab5dcec..0f79adab 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
@@ -1,44 +1,120 @@
 // Verifies that type metadata identifiers for trait objects are emitted correctly.
 //
 // needs-sanitizer-cfi
-// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi
 
 #![crate_type="lib"]
 
-trait Trait1 {
+pub trait Trait1 {
     fn foo(&self);
 }
 
-struct Type1;
+#[derive(Clone, Copy)]
+pub struct Type1;
 
 impl Trait1 for Type1 {
     fn foo(&self) {
     }
 }
 
-pub fn foo() {
-    let a = Type1;
-    a.foo();
-    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo
+pub trait Trait2<T> {
+    fn bar(&self);
 }
 
-pub fn bar() {
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub trait Trait4<'a, T> {
+    type Output: 'a;
+    fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+    type Output = &'a i32;
+    fn qux(&self, _: &U) -> Self::Output {
+        &0
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
+    a.foo();
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]")
+}
+
+pub fn bar1() {
     let a = Type1;
     let b = &a as &dyn Trait1;
     b.foo();
-    // CHECK-LABEL: define{{.*}}bar{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]")
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
 }
 
-pub fn baz() {
-    let a = Type1;
-    let b = &a as &dyn Trait1;
-    a.foo();
-    b.foo();
-    // CHECK-LABEL: define{{.*}}baz{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]")
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+    let b = Type4;
+    a.qux(&b);
+    // CHECK-LABEL: define{{.*}}4foo4{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
+}
+
+pub fn bar4<'a>() {
+    let a = Type4;
+    foo4(&a);
+    let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+    b.qux(&a);
+    // CHECK-LABEL: define{{.*}}4bar4{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
 }
 
 // CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE4]]"}
diff --git a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
index 81e0d93..004a67e 100644
--- a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
@@ -30,40 +30,115 @@
 #[lang="drop_in_place"]
 fn drop_in_place_fn<T>() { }
 
-trait Trait1 {
+pub trait Trait1 {
     fn foo(&self);
 }
 
-struct Type1;
+pub struct Type1;
 
 impl Trait1 for Type1 {
     fn foo(&self) {
     }
 }
 
-pub fn foo() {
-    let a = Type1;
-    a.foo();
-    // CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo
+pub trait Trait2<T> {
+    fn bar(&self);
 }
 
-pub fn bar() {
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub trait Trait4<'a, T> {
+    type Output: 'a;
+    fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+    type Output = &'a i32;
+    fn qux(&self, _: &U) -> Self::Output {
+        &0
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
+    a.foo();
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+}
+
+pub fn bar1() {
     let a = Type1;
     let b = &a as &dyn Trait1;
     b.foo();
-    // CHECK-LABEL: define{{.*}}bar{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
 }
 
-pub fn baz() {
-    let a = Type1;
-    let b = &a as &dyn Trait1;
-    a.foo();
-    b.foo();
-    // CHECK-LABEL: define{{.*}}baz{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo
-    // CHECK:       call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+    let b = Type4;
+    a.qux(&b);
+    // CHECK-LABEL: define{{.*}}4foo4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
+}
+
+pub fn bar4<'a>() {
+    let a = Type4;
+    foo4(&a);
+    let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+    b.qux(&a);
+    // CHECK-LABEL: define{{.*}}4bar4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
 }
 
 // CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}
diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs
new file mode 100644
index 0000000..51334c1
--- /dev/null
+++ b/tests/codegen/tied-features-strength.rs
@@ -0,0 +1,29 @@
+// ignore-tidy-linelength
+// revisions: ENABLE_SVE DISABLE_SVE DISABLE_NEON ENABLE_NEON
+// compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+
+// The "+v8a" feature is matched as optional as it isn't added when we
+// are targeting older LLVM versions. Once the min supported version
+// is LLVM-14 we can remove the optional regex matching for this feature.
+
+// [ENABLE_SVE] compile-flags: -C target-feature=+sve
+// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_SVE] compile-flags: -C target-feature=-sve
+// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_NEON] compile-flags: -C target-feature=-neon
+// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" }
+
+// [ENABLE_NEON] compile-flags: -C target-feature=+neon
+// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" }
+
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub fn test() {}
diff --git a/tests/codegen/var-names.rs b/tests/codegen/var-names.rs
index d4715ef..53841df 100644
--- a/tests/codegen/var-names.rs
+++ b/tests/codegen/var-names.rs
@@ -9,7 +9,7 @@
     // CHECK: %c = add i32 %a, %b
     let d = c;
     let e = d * a;
-    // CHECK-NEXT: %e = mul i32 %c, %a
+    // CHECK-NEXT: %0 = mul i32 %c, %a
     e
-    // CHECK-NEXT: ret i32 %e
+    // CHECK-NEXT: ret i32 %0
 }
diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs
index 9143fad..6f477a7 100644
--- a/tests/codegen/vec-optimizes-away.rs
+++ b/tests/codegen/vec-optimizes-away.rs
@@ -1,12 +1,13 @@
 // ignore-debug: the debug assertions get in the way
 // no-system-llvm
 // compile-flags: -O
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 #[no_mangle]
 pub fn sum_me() -> i32 {
     // CHECK-LABEL: @sum_me
     // CHECK-NEXT: {{^.*:$}}
+    // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1
     // CHECK-NEXT: ret i32 6
     vec![1, 2, 3].iter().sum::<i32>()
 }
diff --git a/tests/debuginfo/reference-debuginfo.rs b/tests/debuginfo/reference-debuginfo.rs
new file mode 100644
index 0000000..85ade17
--- /dev/null
+++ b/tests/debuginfo/reference-debuginfo.rs
@@ -0,0 +1,173 @@
+// Copy of `borrowed-basic.rs` which enables the `ReferencePropagation` MIR pass.
+// That pass replaces debuginfo for `a => _x` where `_x = &b` to be `a => &b`,
+// and leaves codegen to create a ladder of allocations so as `*a == b`.
+//
+// compile-flags:-g -Zmir-enable-passes=+ReferencePropagation,-ConstDebugInfo
+// min-lldb-version: 310
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command:run
+// gdb-command:print *bool_ref
+// gdb-check:$1 = true
+
+// gdb-command:print *int_ref
+// gdb-check:$2 = -1
+
+// gdb-command:print/d *char_ref
+// gdb-check:$3 = 97
+
+// gdb-command:print *i8_ref
+// gdbg-check:$4 = 68 'D'
+// gdbr-check:$4 = 68
+
+// gdb-command:print *i16_ref
+// gdb-check:$5 = -16
+
+// gdb-command:print *i32_ref
+// gdb-check:$6 = -32
+
+// gdb-command:print *i64_ref
+// gdb-check:$7 = -64
+
+// gdb-command:print *uint_ref
+// gdb-check:$8 = 1
+
+// gdb-command:print *u8_ref
+// gdbg-check:$9 = 100 'd'
+// gdbr-check:$9 = 100
+
+// gdb-command:print *u16_ref
+// gdb-check:$10 = 16
+
+// gdb-command:print *u32_ref
+// gdb-check:$11 = 32
+
+// gdb-command:print *u64_ref
+// gdb-check:$12 = 64
+
+// gdb-command:print *f32_ref
+// gdb-check:$13 = 2.5
+
+// gdb-command:print *f64_ref
+// gdb-check:$14 = 3.5
+
+// gdb-command:print *f64_double_ref
+// gdb-check:$15 = 3.5
+
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+// lldb-command:print *bool_ref
+// lldbg-check:[...]$0 = true
+// lldbr-check:(bool) *bool_ref = true
+
+// lldb-command:print *int_ref
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) *int_ref = -1
+
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print *char_ref
+// lldbr-check:(char) *char_ref = 'a'
+
+// lldb-command:print *i8_ref
+// lldbg-check:[...]$2 = 'D'
+// lldbr-check:(i8) *i8_ref = 68
+
+// lldb-command:print *i16_ref
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) *i16_ref = -16
+
+// lldb-command:print *i32_ref
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) *i32_ref = -32
+
+// lldb-command:print *i64_ref
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) *i64_ref = -64
+
+// lldb-command:print *uint_ref
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) *uint_ref = 1
+
+// lldb-command:print *u8_ref
+// lldbg-check:[...]$7 = 'd'
+// lldbr-check:(u8) *u8_ref = 100
+
+// lldb-command:print *u16_ref
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) *u16_ref = 16
+
+// lldb-command:print *u32_ref
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) *u32_ref = 32
+
+// lldb-command:print *u64_ref
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) *u64_ref = 64
+
+// lldb-command:print *f32_ref
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) *f32_ref = 2.5
+
+// lldb-command:print *f64_ref
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) *f64_ref = 3.5
+
+// lldb-command:print *f64_double_ref
+// lldbg-check:[...]$13 = 3.5
+// lldbr-check:(f64) **f64_double_ref = 3.5
+
+#![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+
+fn main() {
+    let bool_val: bool = true;
+    let bool_ref: &bool = &bool_val;
+
+    let int_val: isize = -1;
+    let int_ref: &isize = &int_val;
+
+    let char_val: char = 'a';
+    let char_ref: &char = &char_val;
+
+    let i8_val: i8 = 68;
+    let i8_ref: &i8 = &i8_val;
+
+    let i16_val: i16 = -16;
+    let i16_ref: &i16 = &i16_val;
+
+    let i32_val: i32 = -32;
+    let i32_ref: &i32 = &i32_val;
+
+    let i64_val: i64 = -64;
+    let i64_ref: &i64 = &i64_val;
+
+    let uint_val: usize = 1;
+    let uint_ref: &usize = &uint_val;
+
+    let u8_val: u8 = 100;
+    let u8_ref: &u8 = &u8_val;
+
+    let u16_val: u16 = 16;
+    let u16_ref: &u16 = &u16_val;
+
+    let u32_val: u32 = 32;
+    let u32_ref: &u32 = &u32_val;
+
+    let u64_val: u64 = 64;
+    let u64_ref: &u64 = &u64_val;
+
+    let f32_val: f32 = 2.5;
+    let f32_ref: &f32 = &f32_val;
+
+    let f64_val: f64 = 3.5;
+    let f64_ref: &f64 = &f64_val;
+    let f64_double_ref: &f64 = &f64_ref;
+
+    zzz(); // #break
+}
+
+fn zzz() {()}
diff --git a/tests/incremental/const-generic-type-cycle.rs b/tests/incremental/const-generic-type-cycle.rs
new file mode 100644
index 0000000..ca7b12e
--- /dev/null
+++ b/tests/incremental/const-generic-type-cycle.rs
@@ -0,0 +1,17 @@
+// Verify that we do not ICE when we try to overwrite an anon-const's type because of a trait
+// cycle.
+//
+// compile-flags: -Zincremental-ignore-spans
+// revisions: cpass cfail
+// error-pattern: cycle detected when computing type of `Bar::N`
+
+#![feature(trait_alias)]
+#![crate_type="lib"]
+
+#[cfg(cpass)]
+trait Bar<const N: usize> {}
+
+#[cfg(cfail)]
+trait Bar<const N: dyn BB> {}
+
+trait BB = Bar<{ 2 + 1 }>;
diff --git a/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir b/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir
new file mode 100644
index 0000000..5233d04
--- /dev/null
+++ b/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir
@@ -0,0 +1,12 @@
+// MIR for `copy_for_deref` after built
+
+fn copy_for_deref(_1: (&i32, i32)) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:38: +0:41
+    let mut _2: &i32;                    // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = deref_copy (_1.0: &i32);    // scope 0 at $DIR/projections.rs:+4:13: +4:37
+        _0 = (*_2);                      // scope 0 at $DIR/projections.rs:+5:13: +5:24
+        return;                          // scope 0 at $DIR/projections.rs:+6:13: +6:21
+    }
+}
diff --git a/tests/mir-opt/building/custom/projections.rs b/tests/mir-opt/building/custom/projections.rs
index 5e472e5..3c155de 100644
--- a/tests/mir-opt/building/custom/projections.rs
+++ b/tests/mir-opt/building/custom/projections.rs
@@ -21,13 +21,10 @@
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
 fn tuples(i: (u32, i32)) -> (u32, i32) {
     mir!(
-        // FIXME(JakobDegen): This is necessary because we can't give type hints for `RET`
-        let temp: (u32, i32);
+        type RET = (u32, i32);
         {
-            temp.0 = i.0;
-            temp.1 = i.1;
-
-            RET = temp;
+            RET.0 = i.0;
+            RET.1 = i.1;
             Return()
         }
     )
@@ -71,6 +68,19 @@
     })
 }
 
+// EMIT_MIR projections.copy_for_deref.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn copy_for_deref(x: (&i32, i32)) -> i32 {
+    mir!(
+        let temp: &i32;
+        {
+            temp = CopyForDeref(x.0);
+            RET = *temp;
+            Return()
+        }
+    )
+}
+
 fn main() {
     assert_eq!(unions(U { a: 5 }), 5);
     assert_eq!(tuples((5, 6)), (5, 6));
@@ -82,4 +92,7 @@
     assert_eq!(o, Some(10));
 
     assert_eq!(simple_index([0; 10], &[0; 10]), 0);
+
+    let one = 1;
+    assert_eq!(copy_for_deref((&one, one)), 1);
 }
diff --git a/tests/mir-opt/building/custom/projections.tuples.built.after.mir b/tests/mir-opt/building/custom/projections.tuples.built.after.mir
index 65487d3..dec5752 100644
--- a/tests/mir-opt/building/custom/projections.tuples.built.after.mir
+++ b/tests/mir-opt/building/custom/projections.tuples.built.after.mir
@@ -2,12 +2,10 @@
 
 fn tuples(_1: (u32, i32)) -> (u32, i32) {
     let mut _0: (u32, i32);              // return place in scope 0 at $DIR/projections.rs:+0:29: +0:39
-    let mut _2: (u32, i32);              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
 
     bb0: {
-        (_2.0: u32) = (_1.0: u32);       // scope 0 at $DIR/projections.rs:+5:13: +5:25
-        (_2.1: i32) = (_1.1: i32);       // scope 0 at $DIR/projections.rs:+6:13: +6:25
-        _0 = _2;                         // scope 0 at $DIR/projections.rs:+8:13: +8:23
-        return;                          // scope 0 at $DIR/projections.rs:+9:13: +9:21
+        (_0.0: u32) = (_1.0: u32);       // scope 0 at $DIR/projections.rs:+4:13: +4:24
+        (_0.1: i32) = (_1.1: i32);       // scope 0 at $DIR/projections.rs:+5:13: +5:24
+        return;                          // scope 0 at $DIR/projections.rs:+6:13: +6:21
     }
 }
diff --git a/tests/mir-opt/building/enum_cast.bar.built.after.mir b/tests/mir-opt/building/enum_cast.bar.built.after.mir
index 0746e0b..9f14c02 100644
--- a/tests/mir-opt/building/enum_cast.bar.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.bar.built.after.mir
@@ -5,17 +5,16 @@
     let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
     let _2: Bar;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
     let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
-    let mut _4: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
     let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _4 = Ge(const 1_isize, _3);      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_4);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _5 = Le(const 0_isize, _3);      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_5);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
         return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
diff --git a/tests/mir-opt/building/enum_cast.boo.built.after.mir b/tests/mir-opt/building/enum_cast.boo.built.after.mir
index 699c876..715dedc 100644
--- a/tests/mir-opt/building/enum_cast.boo.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.boo.built.after.mir
@@ -5,17 +5,16 @@
     let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
     let _2: Boo;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
     let mut _3: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
-    let mut _4: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
     let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _4 = Ge(const 1_u8, _3);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_4);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _5 = Le(const 0_u8, _3);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_5);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
         return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
index 1112177..6c177c6 100644
--- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
@@ -6,7 +6,7 @@
     let _2: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
     let _4: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
     let mut _5: isize;                   // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
-    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
+    let mut _6: u8;                      // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
     let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
     let _8: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
     scope 1 {
@@ -31,10 +31,9 @@
         StorageLive(_4);                 // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
         _4 = move _2;                    // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
         _5 = discriminant(_4);           // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        _6 = Ge(const 2_isize, _5);      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        assume(_6);                      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        _7 = Le(const 0_isize, _5);      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        assume(_7);                      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        _6 = _5 as u8 (IntToInt);        // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        _7 = Le(_6, const 2_u8);         // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        assume(move _7);                 // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
         _3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
         drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
     }
diff --git a/tests/mir-opt/building/enum_cast.far.built.after.mir b/tests/mir-opt/building/enum_cast.far.built.after.mir
new file mode 100644
index 0000000..ab8129c
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.far.built.after.mir
@@ -0,0 +1,22 @@
+// MIR for `far` after built
+
+fn far(_1: Far) -> isize {
+    debug far => _1;                     // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11
+    let mut _0: isize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
+    let _2: Far;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+    let mut _3: i16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+    let mut _4: u16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u16 (IntToInt);       // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u16);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _0 = move _3 as isize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.offsetty.built.after.mir b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir
new file mode 100644
index 0000000..7b2b583
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir
@@ -0,0 +1,26 @@
+// MIR for `offsetty` after built
+
+fn offsetty(_1: NotStartingAtZero) -> u32 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:13: +0:14
+    let mut _0: u32;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
+    let _2: NotStartingAtZero;           // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _5 = Ge(_4, const 4_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _6 = Le(_4, const 8_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _7 = BitAnd(move _5, move _6);   // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        assume(move _7);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _0 = move _3 as u32 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs
index 98fd5ac..431b5c7 100644
--- a/tests/mir-opt/building/enum_cast.rs
+++ b/tests/mir-opt/building/enum_cast.rs
@@ -1,6 +1,7 @@
 // EMIT_MIR enum_cast.foo.built.after.mir
 // EMIT_MIR enum_cast.bar.built.after.mir
 // EMIT_MIR enum_cast.boo.built.after.mir
+// EMIT_MIR enum_cast.far.built.after.mir
 
 enum Foo {
     A
@@ -15,6 +16,11 @@
     A, B
 }
 
+#[repr(i16)]
+enum Far {
+    A, B
+}
+
 fn foo(foo: Foo) -> usize {
     foo as usize
 }
@@ -27,6 +33,10 @@
     boo as usize
 }
 
+fn far(far: Far) -> isize {
+    far as isize
+}
+
 // EMIT_MIR enum_cast.droppy.built.after.mir
 enum Droppy {
     A, B, C
@@ -46,5 +56,37 @@
     let z = Droppy::B;
 }
 
+#[repr(i16)]
+enum SignedAroundZero {
+    A = -2,
+    B = 0,
+    C = 2,
+}
+
+#[repr(u16)]
+enum UnsignedAroundZero {
+    A = 65535,
+    B = 0,
+    C = 1,
+}
+
+// EMIT_MIR enum_cast.signy.built.after.mir
+fn signy(x: SignedAroundZero) -> i16 {
+    x as i16
+}
+
+// EMIT_MIR enum_cast.unsigny.built.after.mir
+fn unsigny(x: UnsignedAroundZero) -> u16 {
+    // FIXME: This doesn't get an around-the-end range today, sadly.
+    x as u16
+}
+
+enum NotStartingAtZero { A = 4, B = 6, C = 8 }
+
+// EMIT_MIR enum_cast.offsetty.built.after.mir
+fn offsetty(x: NotStartingAtZero) -> u32 {
+    x as u32
+}
+
 fn main() {
 }
diff --git a/tests/mir-opt/building/enum_cast.signy.built.after.mir b/tests/mir-opt/building/enum_cast.signy.built.after.mir
new file mode 100644
index 0000000..ef4fea6
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.signy.built.after.mir
@@ -0,0 +1,26 @@
+// MIR for `signy` after built
+
+fn signy(_1: SignedAroundZero) -> i16 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:10: +0:11
+    let mut _0: i16;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:34: +0:37
+    let _2: SignedAroundZero;            // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _3: i16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _4: u16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _4 = _3 as u16 (IntToInt);       // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _5 = Ge(_4, const 65534_u16);    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _6 = Le(_4, const 2_u16);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _7 = BitOr(move _5, move _6);    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        assume(move _7);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _0 = move _3 as i16 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.unsigny.built.after.mir b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir
new file mode 100644
index 0000000..7ca147b
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir
@@ -0,0 +1,17 @@
+// MIR for `unsigny` after built
+
+fn unsigny(_1: UnsignedAroundZero) -> u16 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:12: +0:13
+    let mut _0: u16;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
+    let _2: UnsignedAroundZero;          // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+    let mut _3: u16;                     // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
+        _0 = move _3 as u16 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+2:12: +2:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+3:2: +3:2
+    }
+}
diff --git a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
index c5907e7..15117ea 100644
--- a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
@@ -4,59 +4,29 @@
   fn adt_transmutes() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/combine_transmutes.rs:+0:32: +0:32
       let _1: u8;                          // in scope 0 at $DIR/combine_transmutes.rs:+1:9: +1:11
-      let mut _2: EnumNoRepr;              // in scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-      let mut _4: EnumNoRepr;              // in scope 0 at $DIR/combine_transmutes.rs:+2:28: +2:41
-      let mut _6: EnumReprIsize;           // in scope 0 at $DIR/combine_transmutes.rs:+3:31: +3:47
-      let mut _8: EnumReprIsize;           // in scope 0 at $DIR/combine_transmutes.rs:+4:31: +4:47
-      let mut _10: std::cmp::Ordering;     // in scope 0 at $DIR/combine_transmutes.rs:+5:28: +5:52
-      let mut _12: std::cmp::Ordering;     // in scope 0 at $DIR/combine_transmutes.rs:+6:28: +6:52
-      let mut _14: std::option::Option<std::num::NonZeroU8>; // in scope 0 at $DIR/combine_transmutes.rs:+7:28: +7:58
-      let mut _16: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+8:29: +8:54
-      let mut _18: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+9:29: +9:54
-      let mut _20: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+10:29: +10:47
-      let mut _22: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+11:29: +11:47
-      let mut _24: std::mem::MaybeUninit<std::string::String>; // in scope 0 at $DIR/combine_transmutes.rs:+12:46: +12:77
+      let mut _2: std::option::Option<std::num::NonZeroU8>; // in scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+      let mut _4: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+2:29: +2:54
+      let mut _6: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+3:29: +3:54
+      let mut _8: Union32;                 // in scope 0 at $DIR/combine_transmutes.rs:+4:29: +4:47
+      let mut _10: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+5:29: +5:47
+      let mut _12: std::mem::MaybeUninit<std::string::String>; // in scope 0 at $DIR/combine_transmutes.rs:+6:46: +6:77
       scope 1 {
           debug _a => _1;                  // in scope 1 at $DIR/combine_transmutes.rs:+1:9: +1:11
-          let _3: i8;                      // in scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
+          let _3: i16;                     // in scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
           scope 2 {
               debug _a => _3;              // in scope 2 at $DIR/combine_transmutes.rs:+2:9: +2:11
-              let _5: usize;               // in scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
+              let _5: u16;                 // in scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
               scope 3 {
                   debug _a => _5;          // in scope 3 at $DIR/combine_transmutes.rs:+3:9: +3:11
-                  let _7: isize;           // in scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
+                  let _7: u32;             // in scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
                   scope 4 {
                       debug _a => _7;      // in scope 4 at $DIR/combine_transmutes.rs:+4:9: +4:11
-                      let _9: u8;          // in scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
+                      let _9: i32;         // in scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
                       scope 5 {
                           debug _a => _9;  // in scope 5 at $DIR/combine_transmutes.rs:+5:9: +5:11
-                          let _11: i8;     // in scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
+                          let _11: std::mem::ManuallyDrop<std::string::String>; // in scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
                           scope 6 {
                               debug _a => _11; // in scope 6 at $DIR/combine_transmutes.rs:+6:9: +6:11
-                              let _13: u8; // in scope 6 at $DIR/combine_transmutes.rs:+7:9: +7:11
-                              scope 7 {
-                                  debug _a => _13; // in scope 7 at $DIR/combine_transmutes.rs:+7:9: +7:11
-                                  let _15: i16; // in scope 7 at $DIR/combine_transmutes.rs:+8:9: +8:11
-                                  scope 8 {
-                                      debug _a => _15; // in scope 8 at $DIR/combine_transmutes.rs:+8:9: +8:11
-                                      let _17: u16; // in scope 8 at $DIR/combine_transmutes.rs:+9:9: +9:11
-                                      scope 9 {
-                                          debug _a => _17; // in scope 9 at $DIR/combine_transmutes.rs:+9:9: +9:11
-                                          let _19: u32; // in scope 9 at $DIR/combine_transmutes.rs:+10:9: +10:11
-                                          scope 10 {
-                                              debug _a => _19; // in scope 10 at $DIR/combine_transmutes.rs:+10:9: +10:11
-                                              let _21: i32; // in scope 10 at $DIR/combine_transmutes.rs:+11:9: +11:11
-                                              scope 11 {
-                                                  debug _a => _21; // in scope 11 at $DIR/combine_transmutes.rs:+11:9: +11:11
-                                                  let _23: std::mem::ManuallyDrop<std::string::String>; // in scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
-                                                  scope 12 {
-                                                      debug _a => _23; // in scope 12 at $DIR/combine_transmutes.rs:+12:9: +12:11
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
-                              }
                           }
                       }
                   }
@@ -66,93 +36,55 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+1:9: +1:11
-          StorageLive(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-          _2 = EnumNoRepr::A;              // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-          _1 = move _2 as u8 (Transmute);  // scope 0 at $DIR/combine_transmutes.rs:+1:18: +1:42
-          StorageDead(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:41: +1:42
+          StorageLive(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+          _2 = Option::<NonZeroU8>::Some(const _); // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+                                           // mir::Constant
+                                           // + span: $DIR/combine_transmutes.rs:35:33: 35:57
+                                           // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, [], None) }
+          _1 = move _2 as u8 (Transmute);  // scope 0 at $DIR/combine_transmutes.rs:+1:18: +1:59
+          StorageDead(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:58: +1:59
           StorageLive(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
-          StorageLive(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:28: +2:41
-          _4 = EnumNoRepr::B;              // scope 1 at $DIR/combine_transmutes.rs:+2:28: +2:41
-          _3 = move _4 as i8 (Transmute);  // scope 1 at $DIR/combine_transmutes.rs:+2:18: +2:42
-          StorageDead(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:41: +2:42
+          StorageLive(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:29: +2:54
+          _4 = Wrapping::<i16>(const 0_i16); // scope 1 at $DIR/combine_transmutes.rs:+2:29: +2:54
+-         _3 = move _4 as i16 (Transmute); // scope 1 at $DIR/combine_transmutes.rs:+2:19: +2:55
++         _3 = move (_4.0: i16);           // scope 1 at $DIR/combine_transmutes.rs:+2:19: +2:55
+          StorageDead(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:54: +2:55
           StorageLive(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
-          StorageLive(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:31: +3:47
-          _6 = EnumReprIsize::A;           // scope 2 at $DIR/combine_transmutes.rs:+3:31: +3:47
-          _5 = move _6 as usize (Transmute); // scope 2 at $DIR/combine_transmutes.rs:+3:21: +3:48
-          StorageDead(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:47: +3:48
+          StorageLive(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:29: +3:54
+          _6 = Wrapping::<i16>(const 0_i16); // scope 2 at $DIR/combine_transmutes.rs:+3:29: +3:54
+          _5 = move _6 as u16 (Transmute); // scope 2 at $DIR/combine_transmutes.rs:+3:19: +3:55
+          StorageDead(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:54: +3:55
           StorageLive(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
-          StorageLive(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:31: +4:47
-          _8 = EnumReprIsize::B;           // scope 3 at $DIR/combine_transmutes.rs:+4:31: +4:47
--         _7 = move _8 as isize (Transmute); // scope 3 at $DIR/combine_transmutes.rs:+4:21: +4:48
-+         _7 = discriminant(_8);           // scope 3 at $DIR/combine_transmutes.rs:+4:21: +4:48
+          StorageLive(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:29: +4:47
+          _8 = Union32 { u32: const 0_i32 }; // scope 3 at $DIR/combine_transmutes.rs:+4:29: +4:47
+          _7 = move _8 as u32 (Transmute); // scope 3 at $DIR/combine_transmutes.rs:+4:19: +4:48
           StorageDead(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:47: +4:48
           StorageLive(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
-          StorageLive(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:28: +5:52
-          _10 = Less;                      // scope 4 at $DIR/combine_transmutes.rs:+5:28: +5:52
-          _9 = move _10 as u8 (Transmute); // scope 4 at $DIR/combine_transmutes.rs:+5:18: +5:53
-          StorageDead(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:52: +5:53
+          StorageLive(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:29: +5:47
+          _10 = Union32 { u32: const 0_u32 }; // scope 4 at $DIR/combine_transmutes.rs:+5:29: +5:47
+          _9 = move _10 as i32 (Transmute); // scope 4 at $DIR/combine_transmutes.rs:+5:19: +5:48
+          StorageDead(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:47: +5:48
           StorageLive(_11);                // scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
-          StorageLive(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:28: +6:52
-          _12 = Less;                      // scope 5 at $DIR/combine_transmutes.rs:+6:28: +6:52
--         _11 = move _12 as i8 (Transmute); // scope 5 at $DIR/combine_transmutes.rs:+6:18: +6:53
-+         _11 = discriminant(_12);         // scope 5 at $DIR/combine_transmutes.rs:+6:18: +6:53
-          StorageDead(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:52: +6:53
-          StorageLive(_13);                // scope 6 at $DIR/combine_transmutes.rs:+7:9: +7:11
-          StorageLive(_14);                // scope 6 at $DIR/combine_transmutes.rs:+7:28: +7:58
-          _14 = Option::<NonZeroU8>::Some(const _); // scope 6 at $DIR/combine_transmutes.rs:+7:28: +7:58
+          StorageLive(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:46: +6:77
+          _12 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 5 at $DIR/combine_transmutes.rs:+6:46: +6:77
                                            // mir::Constant
-                                           // + span: $DIR/combine_transmutes.rs:41:33: 41:57
-                                           // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, [], None) }
-          _13 = move _14 as u8 (Transmute); // scope 6 at $DIR/combine_transmutes.rs:+7:18: +7:59
-          StorageDead(_14);                // scope 6 at $DIR/combine_transmutes.rs:+7:58: +7:59
-          StorageLive(_15);                // scope 7 at $DIR/combine_transmutes.rs:+8:9: +8:11
-          StorageLive(_16);                // scope 7 at $DIR/combine_transmutes.rs:+8:29: +8:54
-          _16 = Wrapping::<i16>(const 0_i16); // scope 7 at $DIR/combine_transmutes.rs:+8:29: +8:54
--         _15 = move _16 as i16 (Transmute); // scope 7 at $DIR/combine_transmutes.rs:+8:19: +8:55
-+         _15 = move (_16.0: i16);         // scope 7 at $DIR/combine_transmutes.rs:+8:19: +8:55
-          StorageDead(_16);                // scope 7 at $DIR/combine_transmutes.rs:+8:54: +8:55
-          StorageLive(_17);                // scope 8 at $DIR/combine_transmutes.rs:+9:9: +9:11
-          StorageLive(_18);                // scope 8 at $DIR/combine_transmutes.rs:+9:29: +9:54
-          _18 = Wrapping::<i16>(const 0_i16); // scope 8 at $DIR/combine_transmutes.rs:+9:29: +9:54
-          _17 = move _18 as u16 (Transmute); // scope 8 at $DIR/combine_transmutes.rs:+9:19: +9:55
-          StorageDead(_18);                // scope 8 at $DIR/combine_transmutes.rs:+9:54: +9:55
-          StorageLive(_19);                // scope 9 at $DIR/combine_transmutes.rs:+10:9: +10:11
-          StorageLive(_20);                // scope 9 at $DIR/combine_transmutes.rs:+10:29: +10:47
-          _20 = Union32 { u32: const 0_i32 }; // scope 9 at $DIR/combine_transmutes.rs:+10:29: +10:47
-          _19 = move _20 as u32 (Transmute); // scope 9 at $DIR/combine_transmutes.rs:+10:19: +10:48
-          StorageDead(_20);                // scope 9 at $DIR/combine_transmutes.rs:+10:47: +10:48
-          StorageLive(_21);                // scope 10 at $DIR/combine_transmutes.rs:+11:9: +11:11
-          StorageLive(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:29: +11:47
-          _22 = Union32 { u32: const 0_u32 }; // scope 10 at $DIR/combine_transmutes.rs:+11:29: +11:47
-          _21 = move _22 as i32 (Transmute); // scope 10 at $DIR/combine_transmutes.rs:+11:19: +11:48
-          StorageDead(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:47: +11:48
-          StorageLive(_23);                // scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
-          StorageLive(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
-          _24 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
-                                           // mir::Constant
-                                           // + span: $DIR/combine_transmutes.rs:46:46: 46:75
-                                           // + user_ty: UserType(23)
+                                           // + span: $DIR/combine_transmutes.rs:40:46: 40:75
+                                           // + user_ty: UserType(11)
                                            // + literal: Const { ty: fn() -> MaybeUninit<String> {MaybeUninit::<String>::uninit}, val: Value(<ZST>) }
       }
   
       bb1: {
--         _23 = move _24 as std::mem::ManuallyDrop<std::string::String> (Transmute); // scope 11 at $DIR/combine_transmutes.rs:+12:36: +12:78
-+         _23 = move (_24.1: std::mem::ManuallyDrop<std::string::String>); // scope 11 at $DIR/combine_transmutes.rs:+12:36: +12:78
-          StorageDead(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:77: +12:78
-          _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:32: +13:2
-          StorageDead(_23);                // scope 11 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_21);                // scope 10 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_19);                // scope 9 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_17);                // scope 8 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_15);                // scope 7 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_13);                // scope 6 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_11);                // scope 5 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          return;                          // scope 0 at $DIR/combine_transmutes.rs:+13:2: +13:2
+-         _11 = move _12 as std::mem::ManuallyDrop<std::string::String> (Transmute); // scope 5 at $DIR/combine_transmutes.rs:+6:36: +6:78
++         _11 = move (_12.1: std::mem::ManuallyDrop<std::string::String>); // scope 5 at $DIR/combine_transmutes.rs:+6:36: +6:78
+          StorageDead(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:77: +6:78
+          _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:32: +7:2
+          StorageDead(_11);                // scope 5 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          return;                          // scope 0 at $DIR/combine_transmutes.rs:+7:2: +7:2
       }
   }
   
diff --git a/tests/mir-opt/combine_transmutes.rs b/tests/mir-opt/combine_transmutes.rs
index 7088488..403f935 100644
--- a/tests/mir-opt/combine_transmutes.rs
+++ b/tests/mir-opt/combine_transmutes.rs
@@ -32,12 +32,6 @@
 
 // EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify.diff
 pub unsafe fn adt_transmutes() {
-    let _a: u8 = transmute(EnumNoRepr::A);
-    let _a: i8 = transmute(EnumNoRepr::B);
-    let _a: usize = transmute(EnumReprIsize::A);
-    let _a: isize = transmute(EnumReprIsize::B);
-    let _a: u8 = transmute(std::cmp::Ordering::Less);
-    let _a: i8 = transmute(std::cmp::Ordering::Less);
     let _a: u8 = transmute(Some(std::num::NonZeroU8::MAX));
     let _a: i16 = transmute(std::num::Wrapping(0_i16));
     let _a: u16 = transmute(std::num::Wrapping(0_i16));
@@ -46,20 +40,4 @@
     let _a: ManuallyDrop<String> = transmute(MaybeUninit::<String>::uninit());
 }
 
-#[inline(always)]
-#[custom_mir(dialect = "runtime", phase = "initial")]
-const unsafe fn mir_transmute<T, U>(x: T) -> U {
-    mir!{
-        {
-            RET = CastTransmute(x);
-            Return()
-        }
-    }
-}
-
-pub enum EnumNoRepr { A, B, C }
-
-#[repr(isize)]
-pub enum EnumReprIsize { A, B, C }
-
 pub union Union32 { u32: u32, i32: i32 }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
index bc41b5d..5258d75 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_box() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _2 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: Box<Never>, val: Value(Scalar(0x00000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
index c4376e6..7e57e06 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_box() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _2 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: Box<Never>, val: Value(Scalar(0x0000000000000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
index 81b7b36..032681f 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
@@ -3,22 +3,19 @@
   
   fn unreachable_direct() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:39: +0:40
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:41: +3:2
-      let _2: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:15
+      let _1: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:41: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _3 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _2 = move _3 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _2 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _1 = move _2 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
           unreachable;                     // scope 2 at $DIR/transmute.rs:+1:29: +1:42
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
index 81b7b36..032681f 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
@@ -3,22 +3,19 @@
   
   fn unreachable_direct() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:39: +0:40
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:41: +3:2
-      let _2: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:15
+      let _1: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:41: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _3 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _2 = move _3 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _2 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _1 = move _2 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
           unreachable;                     // scope 2 at $DIR/transmute.rs:+1:29: +1:42
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
index 47f023c..ec8a62b 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
@@ -3,28 +3,24 @@
   
   fn unreachable_mut() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
--         _3 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _3 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+-         _2 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _2 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &mut Never, val: Value(Scalar(0x00000001)) }
-          _2 = &mut (*_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
-          StorageDead(_3);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
-          StorageLive(_4);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          _1 = &mut (*_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          StorageDead(_2);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
index 62300d2..288da6e 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
@@ -3,28 +3,24 @@
   
   fn unreachable_mut() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
--         _3 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _3 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+-         _2 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _2 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &mut Never, val: Value(Scalar(0x0000000000000001)) }
-          _2 = &mut (*_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
-          StorageDead(_3);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
-          StorageLive(_4);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          _1 = &mut (*_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          StorageDead(_2);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
index 8578f89..dcca0fc 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_ref() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
-+         _2 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
++         _1 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &Never, val: Value(Scalar(0x00000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
index 8b11cea..3a0b967 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_ref() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
-+         _2 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
++         _1 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &Never, val: Value(Scalar(0x0000000000000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
index 69acebf..1c7b649 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
@@ -6,15 +6,17 @@
       let mut _0: i32;                     // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:27: +0:30
       let _2: i32;                         // in scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
       scope 1 {
-          debug y => _2;                   // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
+-         debug y => _2;                   // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
++         debug y => _0;                   // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
-          _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
+-         StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
+-         _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
++         _0 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
           _1 = const 123_i32;              // scope 1 at $DIR/copy_propagation_arg.rs:+2:5: +2:12
-          _0 = _2;                         // scope 1 at $DIR/copy_propagation_arg.rs:+3:5: +3:6
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+4:1: +4:2
+-         _0 = _2;                         // scope 1 at $DIR/copy_propagation_arg.rs:+3:5: +3:6
+-         StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:+4:2: +4:2
       }
   }
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
index 94f24b50..a5129e0 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
@@ -16,8 +16,7 @@
 +         let mut _4: usize;               // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         let mut _5: usize;               // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         let mut _6: *mut u8;             // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         let mut _7: std::boxed::Box<std::vec::Vec<u32>>; // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         let mut _8: *const std::vec::Vec<u32>; // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         let mut _7: *const std::vec::Vec<u32>; // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         scope 4 {
 +         }
 +     }
@@ -66,12 +65,9 @@
       bb3: {
 -         StorageDead(_1);                 // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2
 -         return;                          // scope 0 at $DIR/inline_into_box_place.rs:+2:2: +2:2
-+         StorageLive(_7);                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         _7 = ShallowInitBox(move _6, std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         _8 = (((_7.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         (*_8) = move _2;                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         _1 = move _7;                    // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         StorageDead(_7);                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         _1 = ShallowInitBox(move _6, std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         _7 = (((_1.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         (*_7) = move _2;                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         StorageDead(_2);                 // scope 0 at $DIR/inline_into_box_place.rs:+1:48: +1:49
 +         _0 = const ();                   // scope 0 at $DIR/inline_into_box_place.rs:+0:11: +2:2
 +         drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index 8c4ab25..21570a8 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -8,9 +8,8 @@
     let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
     scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15
         debug self => _4;                // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _5: &mut T;              // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _6: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _7: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _5: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _6: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
     }
 
     bb0: {
@@ -18,12 +17,9 @@
         StorageLive(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageLive(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         _4 = &mut (*_1);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
-        StorageLive(_5);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:7: +1:15
-        _6 = deref_copy (*_4);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _7 = (((_6.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _5 = &mut (*_7);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _3 = _5;                         // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        StorageDead(_5);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:7: +1:15
+        _5 = deref_copy (*_4);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _3 = &mut (*_6);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
         _2 = &mut (*_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageDead(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
         _0 = &mut (*_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
index b18a41b..4f93422 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
@@ -7,21 +7,17 @@
     let mut _3: &std::boxed::Box<T>;     // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
     scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:7: 18:15
         debug self => _3;                // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let _4: &T;                      // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _5: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _6: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _4: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _5: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
     }
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageLive(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         _3 = &(*_1);                     // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
-        StorageLive(_4);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _5 = deref_copy (*_3);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _4 = &(*_6);                     // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _2 = _4;                         // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _4 = deref_copy (*_3);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _5 = (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _2 = &(*_5);                     // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
         _0 = &(*_2);                     // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageDead(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
         StorageDead(_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
index 473e02f..d76cd0e 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
@@ -12,7 +12,51 @@
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         let mut _5: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
++             scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _8: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _9: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 scope 4 {
++                     scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _12: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                         }
++                     }
++                     scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _14: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         scope 8 {
++                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                         }
++                     }
++                     scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _15: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 10 {
++                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                         scope 11 {
++                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                                 scope 14 {
++                                     scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                                     }
++                                 }
++                             }
++                         }
++                         scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                     }
++                 }
++             }
 +         }
 +     }
   
@@ -22,30 +66,87 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
+-                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _5 = core::num::<impl u16>::unchecked_shl::conv(move (_6.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
--                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> u16 {core::num::<impl u16>::unchecked_shl::conv}, val: Value(<ZST>) }
++         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _11 = const 65535_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // mir::Constant
-+                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
-+     }
-+ 
-+     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
++     }
++ 
++     bb2: {
++         _9 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb3: {
++         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _12 = _7 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = Result::<u16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb4: {
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb5: {
++         _8 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb6: {
++         unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb7: {
++         _14 = move ((_9 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _8 = Option::<u16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_8 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
       }
   }
   
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index 9b7b11e..3c175ed 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -9,7 +9,51 @@
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         let mut _3: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
+            scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _7: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                scope 4 {
+                    scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _10: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                        }
+                    }
+                    scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _12: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        scope 8 {
+                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                        }
+                    }
+                    scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _13: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 10 {
+                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                        scope 11 {
+                            scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                scope 14 {
+                                    scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    }
+                                }
+                            }
+                        }
+                        scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -17,22 +61,78 @@
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = core::num::<impl u16>::unchecked_shl::conv(move (_4.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> u16 {core::num::<impl u16>::unchecked_shl::conv}, val: Value(<ZST>) }
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _9 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
     bb2: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+        _7 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb3: {
+        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _10 = _5 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = Result::<u16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb4: {
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb5: {
+        _6 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb6: {
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb7: {
+        _12 = move ((_7 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _6 = Option::<u16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
     }
 }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
index 9638ddd..f3d3e60 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
@@ -12,7 +12,51 @@
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         let mut _5: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
++             scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _8: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _9: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 scope 4 {
++                     scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _12: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                         }
++                     }
++                     scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _14: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         scope 8 {
++                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                         }
++                     }
++                     scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _15: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 10 {
++                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                         scope 11 {
++                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                                 scope 14 {
++                                     scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                                     }
++                                 }
++                             }
++                         }
++                         scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                     }
++                 }
++             }
 +         }
 +     }
   
@@ -22,30 +66,87 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
+-                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _5 = core::num::<impl i16>::unchecked_shr::conv(move (_6.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
--                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> i16 {core::num::<impl i16>::unchecked_shr::conv}, val: Value(<ZST>) }
++         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _11 = const 32767_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // mir::Constant
-+                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
-+     }
-+ 
-+     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
++     }
++ 
++     bb2: {
++         _9 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb3: {
++         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _12 = _7 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = Result::<i16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb4: {
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb5: {
++         _8 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb6: {
++         unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb7: {
++         _14 = move ((_9 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _8 = Option::<i16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_8 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
       }
   }
   
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index afe6d08..724b3c5 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -9,7 +9,51 @@
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         let mut _3: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
+            scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _7: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                scope 4 {
+                    scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _10: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                        }
+                    }
+                    scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _12: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        scope 8 {
+                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                        }
+                    }
+                    scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _13: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 10 {
+                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                        scope 11 {
+                            scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                scope 14 {
+                                    scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    }
+                                }
+                            }
+                        }
+                        scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -17,22 +61,78 @@
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = core::num::<impl i16>::unchecked_shr::conv(move (_4.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> i16 {core::num::<impl i16>::unchecked_shr::conv}, val: Value(<ZST>) }
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _9 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
     bb2: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+        _7 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb3: {
+        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _10 = _5 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = Result::<i16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb4: {
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb5: {
+        _6 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb6: {
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb7: {
+        _12 = move ((_7 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _6 = Option::<i16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
     }
 }
diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
new file mode 100644
index 0000000..745f2bb
--- /dev/null
+++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
@@ -0,0 +1,50 @@
+- // MIR for `caller` before Inline
++ // MIR for `caller` after Inline
+  
+  fn caller(_1: Box<[i32]>) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/unsized_argument.rs:+0:11: +0:12
+      let mut _0: ();                      // return place in scope 0 at $DIR/unsized_argument.rs:+0:26: +0:26
+      let _2: ();                          // in scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+      let mut _3: std::boxed::Box<[i32]>;  // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+      let mut _4: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _5: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _6: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _7: *const [i32];            // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+          StorageLive(_3);                 // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+          _3 = move _1;                    // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+          _7 = (((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>).0: *const [i32]); // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+          _2 = callee(move (*_7)) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:5: 9:11
+                                           // + literal: Const { ty: fn([i32]) {callee}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_3);                 // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+          StorageDead(_2);                 // scope 0 at $DIR/unsized_argument.rs:+1:15: +1:16
+          _0 = const ();                   // scope 0 at $DIR/unsized_argument.rs:+0:26: +2:2
+          return;                          // scope 0 at $DIR/unsized_argument.rs:+2:2: +2:2
+      }
+  
+      bb2 (cleanup): {
+          resume;                          // scope 0 at $DIR/unsized_argument.rs:+0:1: +2:2
+      }
+  
+      bb3: {
+          _4 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> bb1; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:14: 9:15
+                                           // + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
+      }
+  
+      bb4 (cleanup): {
+          _6 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> [return: bb2, unwind terminate]; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:14: 9:15
+                                           // + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
+      }
+  }
+  
diff --git a/tests/mir-opt/inline/unsized_argument.rs b/tests/mir-opt/inline/unsized_argument.rs
new file mode 100644
index 0000000..b2c5140
--- /dev/null
+++ b/tests/mir-opt/inline/unsized_argument.rs
@@ -0,0 +1,15 @@
+// needs-unwind
+#![feature(unsized_fn_params)]
+
+#[inline(always)]
+fn callee(y: [i32]) {}
+
+// EMIT_MIR unsized_argument.caller.Inline.diff
+fn caller(x: Box<[i32]>) {
+    callee(*x);
+}
+
+fn main() {
+    let b = Box::new([1]);
+    caller(b);
+}
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff
index 778ecc4..8a8cd89 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff
@@ -9,9 +9,8 @@
 +         debug self => _2;                // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         let mut _3: &std::option::Option<T>; // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         let mut _4: isize;               // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-+         let _5: T;                       // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         scope 2 {
-+             debug val => _5;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
++             debug val => _0;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
 +         }
 +         scope 3 {
 +             scope 5 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -47,10 +46,7 @@
 -     bb2 (cleanup): {
 -         resume;                          // scope 0 at $DIR/unwrap_unchecked.rs:+0:1: +2:2
 +     bb2: {
-+         StorageLive(_5);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-+         _5 = move ((_2 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-+         _0 = move _5;                    // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_5);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
++         _0 = move ((_2 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         StorageDead(_3);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
 +         StorageDead(_2);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:26: +1:27
 +         return;                          // scope 0 at $DIR/unwrap_unchecked.rs:+2:2: +2:2
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
index 5cdf4fa..c5e2469 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
@@ -7,9 +7,8 @@
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _2: &std::option::Option<T>; // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _3: isize;               // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        let _4: T;                       // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         scope 2 {
-            debug val => _4;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+            debug val => _0;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
         }
         scope 3 {
             scope 5 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -35,10 +34,7 @@
     }
 
     bb2: {
-        StorageLive(_4);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        _4 = move ((_1 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        _0 = move _4;                    // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
+        _0 = move ((_1 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         StorageDead(_2);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
         return;                          // scope 0 at $DIR/unwrap_unchecked.rs:+2:2: +2:2
     }
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 4086da5..25f4722 100644
--- a/tests/mir-opt/issue_72181_1.f.built.after.mir
+++ b/tests/mir-opt/issue_72181_1.f.built.after.mir
@@ -3,27 +3,13 @@
 fn f(_1: Void) -> ! {
     debug v => _1;                       // in scope 0 at $DIR/issue_72181_1.rs:+0:6: +0:7
     let mut _0: !;                       // return place in scope 0 at $DIR/issue_72181_1.rs:+0:18: +0:19
-    let mut _2: !;                       // in scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-    let mut _3: !;                       // in scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-        StorageLive(_3);                 // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12
         unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12
     }
 
     bb1: {
-        unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
-    }
-
-    bb2: {
-        StorageDead(_3);                 // scope 0 at $DIR/issue_72181_1.rs:+1:14: +1:15
-        unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-    }
-
-    bb3: {
-        StorageDead(_2);                 // scope 0 at $DIR/issue_72181_1.rs:+2:1: +2:2
         return;                          // scope 0 at $DIR/issue_72181_1.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
index abb89b9..73b9ea4 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
@@ -21,9 +21,9 @@
           let _13: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
           let _14: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
           scope 2 {
-              debug v1 => _12;             // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16
-              debug v2 => _13;             // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24
-              debug v3 => _14;             // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32
+              debug v1 => &(*_2)[0 of 3];  // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16
+              debug v2 => &(*_2)[1 of 3];  // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24
+              debug v3 => &(*_2)[2 of 3];  // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32
           }
       }
   
@@ -52,15 +52,6 @@
       }
   
       bb2: {
-          StorageLive(_12);                // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
-          _12 = &(*_2)[0 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
-          StorageLive(_13);                // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
-          _13 = &(*_2)[1 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
-          StorageLive(_14);                // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
-          _14 = &(*_2)[2 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
-          StorageDead(_14);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_13);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_12);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
           StorageDead(_5);                 // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2
           StorageDead(_2);                 // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2
           return;                          // scope 0 at $DIR/issue_76432.rs:+6:2: +6:2
diff --git a/tests/mir-opt/issue_99325.main.built.after.mir b/tests/mir-opt/issue_99325.main.built.after.mir
index f0c9ef4..0424ce3 100644
--- a/tests/mir-opt/issue_99325.main.built.after.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), substs: [] }) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)]) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated([], DefId(0:8 ~ issue_99325[22bb]::main::{constant#1})) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/issue_99325.rs:+0:15: +0:15
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
index 8735a75..aa5d961 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_box_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:70:25: 70:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> Box<Never> {transmute::<usize, Box<Never>>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
index a772132..5fafd45 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_mut_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:64:25: 64:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &mut Never {transmute::<usize, &mut Never>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as &mut Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         _1 = const 1_usize as &mut Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
index c4d53d4..08dead1 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_ref_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:58:21: 58:40
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &Never {transmute::<usize, &Never>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as &Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
++         _1 = const 1_usize as &Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
index c0cc698..28e4590 100644
--- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
@@ -3,16 +3,15 @@
   
   fn unreachable() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:25: +0:26
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:27: +2:2
-      let _2: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+      let _1: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+      let mut _2: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
       scope 1 {
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
--         _3 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+-         _2 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:31:14: 31:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 71bdfcc..c425f3c 100644
--- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -22,7 +22,7 @@
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11
-    let mut _1: [usize; Const(Value(Leaf(0x00000003)): usize)]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
+    let mut _1: [usize; Const { ty: usize, kind: Leaf(0x00000003) }]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
     let _3: usize;                       // in scope 0 at $DIR/region_subtyping_basic.rs:+2:16: +2:17
     let mut _4: usize;                   // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
     let mut _5: bool;                    // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 9fa8609..22ad24f 100644
--- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -22,7 +22,7 @@
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11
-    let mut _1: [usize; Const(Value(Leaf(0x0000000000000003)): usize)]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
+    let mut _1: [usize; Const { ty: usize, kind: Leaf(0x0000000000000003) }]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
     let _3: usize;                       // in scope 0 at $DIR/region_subtyping_basic.rs:+2:16: +2:17
     let mut _4: usize;                   // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
     let mut _5: bool;                    // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir
index 4fddd50..1d23871 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir
@@ -4,17 +4,13 @@
     debug r => _1;                       // in scope 0 at $DIR/mem_replace.rs:+0:23: +0:24
     debug v => _2;                       // in scope 0 at $DIR/mem_replace.rs:+0:36: +0:37
     let mut _0: u32;                     // return place in scope 0 at $DIR/mem_replace.rs:+0:47: +0:50
-    let _3: u32;                         // in scope 0 at $DIR/mem_replace.rs:+1:9: +1:13
     scope 1 {
-        debug temp => _3;                // in scope 1 at $DIR/mem_replace.rs:+1:9: +1:13
+        debug temp => _0;                // in scope 1 at $DIR/mem_replace.rs:+1:9: +1:13
     }
 
     bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/mem_replace.rs:+1:9: +1:13
-        _3 = (*_1);                      // scope 0 at $DIR/mem_replace.rs:+1:16: +1:18
+        _0 = (*_1);                      // scope 0 at $DIR/mem_replace.rs:+1:16: +1:18
         (*_1) = _2;                      // scope 1 at $DIR/mem_replace.rs:+2:5: +2:11
-        _0 = _3;                         // scope 1 at $DIR/mem_replace.rs:+3:5: +3:9
-        StorageDead(_3);                 // scope 0 at $DIR/mem_replace.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/mem_replace.rs:+4:2: +4:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
index 619db12..50e0538 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
@@ -7,29 +7,28 @@
     scope 1 (inlined std::mem::replace::<u32>) { // at $DIR/mem_replace.rs:16:5: 16:28
         debug dest => _1;                // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         debug src => _2;                 // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        let mut _4: *const u32;          // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        let mut _5: *mut u32;            // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        let mut _3: *const u32;          // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        let mut _4: *mut u32;            // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         scope 2 {
-            let _3: u32;                 // in scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
             scope 3 {
-                debug result => _3;      // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+                debug result => _0;      // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
                 scope 7 (inlined std::ptr::write::<u32>) { // at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-                    debug dst => _5;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                    debug dst => _4;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                     debug src => _2;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                    let mut _7: *mut u32; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                    let mut _6: *mut u32; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     scope 8 {
                         scope 9 (inlined std::ptr::write::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug dst => _7; // in scope 9 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug dst => _6; // in scope 9 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                         }
                     }
                 }
             }
             scope 4 (inlined std::ptr::read::<u32>) { // at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-                debug src => _4;         // in scope 4 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                let mut _6: *const u32;  // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                debug src => _3;         // in scope 4 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                let mut _5: *const u32;  // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                 scope 5 {
                     scope 6 (inlined std::ptr::read::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                        debug src => _6; // in scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                        debug src => _5; // in scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     }
                 }
             }
@@ -38,20 +37,17 @@
 
     bb0: {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _4 = &raw const (*_1);           // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _3 = (*_4);                      // scope 5 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _5 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        (*_5) = _2;                      // scope 8 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _0 = move _3;                    // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        _3 = &raw const (*_1);           // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        _0 = (*_3);                      // scope 5 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageLive(_4);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        _4 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        (*_4) = _2;                      // scope 8 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageDead(_4);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/mem_replace.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
index 7d4766e..7a10b92 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
@@ -7,63 +7,62 @@
     scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) { // at $DIR/slice_index.rs:26:11: 26:35
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         debug index => _2;               // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        let mut _3: &mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        let mut _3: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         let mut _4: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        let mut _5: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
                 debug self => _2;        // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                debug slice => _5;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let _6: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                debug slice => _4;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let _5: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _7: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _8: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _9: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _9: *mut u32;    // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _10: *mut u32;   // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _11: *mut u32;   // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _11: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _12: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _13: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _14: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                let mut _15: *mut [u32]; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                let mut _13: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                let mut _14: *mut [u32]; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                 scope 4 {
-                    debug this => _6;    // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                    debug this => _5;    // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     scope 5 {
-                        let _7: usize;   // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                        let _6: usize;   // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                         scope 6 {
-                            debug new_len => _7; // in scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                            debug new_len => _6; // in scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                             scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _5; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _4; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                             }
                             scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _11; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                debug count => _12; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _10; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug count => _11; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 13 {
                                 }
                             }
                             scope 14 (inlined slice_from_raw_parts_mut::<u32>) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug data => _10; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                debug len => _13; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                debug data => _9; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                debug len => _12; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                let mut _16: *mut (); // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                 scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                    debug self => _10; // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                    let mut _17: *mut (); // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                    debug self => _9; // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 }
                                 scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                    debug data_address => _17; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    debug metadata => _13; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _18: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _19: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _20: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug data_address => _16; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug metadata => _12; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _17: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _18: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _19: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 17 {
                                     }
                                 }
                             }
                         }
                         scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug this => _14; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug slice => _15; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug this => _13; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug slice => _14; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _15; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                let mut _16: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _14; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                let mut _15: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 9 (inlined std::ptr::metadata::<[u32]>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                    debug ptr => _16; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug ptr => _15; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 10 {
                                     }
                                 }
@@ -76,61 +75,60 @@
     }
 
     bb0: {
+        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _4 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _5 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _7 = (_2.1: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_8);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _8 = (_2.1: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_9);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _9 = (_2.0: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _7 = unchecked_sub::<usize>(move _8, move _9) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _8 = (_2.0: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _6 = unchecked_sub::<usize>(move _7, move _8) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize, usize) -> usize {unchecked_sub::<usize>}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_9);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_8);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _10 = _4 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _11 = _5 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _12 = (_2.0: usize);             // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _10 = Offset(_11, _12);          // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _11 = (_2.0: usize);             // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _9 = Offset(_10, _11);           // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_13);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _13 = _7;                        // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_17);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _17 = _10 as *mut () (PtrToPtr); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _12 = _6;                        // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_16);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _16 = _9 as *mut () (PtrToPtr);  // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageLive(_17);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageLive(_18);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageLive(_19);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageLive(_20);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _20 = _17 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _19 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _20, metadata: _13 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_20);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _18 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _19 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _19 = _16 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _18 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _19, metadata: _12 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageDead(_19);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _4 = (_18.1: *mut [u32]);        // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_18);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_17);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_13);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _17 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _18 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_18);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _3 = (_17.1: *mut [u32]);        // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_17);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_16);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageDead(_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _3 = &mut (*_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _0 = _3;                         // scope 0 at $DIR/slice_index.rs:+1:5: +1:35
+        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _0 = &mut (*_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/slice_index.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir
index d3b59e2..dcf79a4 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir
@@ -4,25 +4,23 @@
     debug slice => _1;                   // in scope 0 at $DIR/slice_index.rs:+0:26: +0:31
     debug index => _2;                   // in scope 0 at $DIR/slice_index.rs:+0:41: +0:46
     let mut _0: &[u32];                  // return place in scope 0 at $DIR/slice_index.rs:+0:65: +0:71
-    let _3: &[u32];                      // in scope 0 at $DIR/slice_index.rs:+1:6: +1:18
     scope 1 (inlined #[track_caller] core::slice::index::<impl Index<std::ops::Range<usize>> for [u32]>::index) { // at $DIR/slice_index.rs:21:6: 21:18
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         debug index => _2;               // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        let _4: &[u32];                  // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        let _3: &[u32];                  // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
     }
 
     bb0: {
-        StorageLive(_4);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _4 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, _1) -> bb1; // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_3);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _3 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, _1) -> bb1; // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // + literal: Const { ty: for<'a> fn(std::ops::Range<usize>, &'a [u32]) -> &'a <std::ops::Range<usize> as SliceIndex<[u32]>>::Output {<std::ops::Range<usize> as SliceIndex<[u32]>>::index}, val: Value(<ZST>) }
     }
 
     bb1: {
-        _3 = _4;                         // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _0 = _3;                         // scope 0 at $DIR/slice_index.rs:+1:5: +1:18
+        _0 = _3;                         // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         return;                          // scope 0 at $DIR/slice_index.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
new file mode 100644
index 0000000..07bd48f
--- /dev/null
+++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
@@ -0,0 +1,175 @@
+- // MIR for `debuginfo` before ReferencePropagation
++ // MIR for `debuginfo` after ReferencePropagation
+  
+  fn debuginfo() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:16: +0:16
+      let _1: &mut u8;                     // in scope 0 at $DIR/reference_prop.rs:+3:9: +3:19
+      let mut _2: u8;                      // in scope 0 at $DIR/reference_prop.rs:+3:27: +3:31
+      let _4: debuginfo::T;                // in scope 0 at $DIR/reference_prop.rs:+4:18: +4:22
+      let _6: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:5: +12:6
+      let mut _7: std::option::Option<i32>; // in scope 0 at $DIR/reference_prop.rs:+9:11: +9:18
+      let mut _8: isize;                   // in scope 0 at $DIR/reference_prop.rs:+10:9: +10:13
+      let _10: ();                         // in scope 0 at $DIR/reference_prop.rs:+16:5: +17:6
+      let mut _11: &[i32];                 // in scope 0 at $DIR/reference_prop.rs:+16:82: +16:94
+      let _12: &[i32];                     // in scope 0 at $DIR/reference_prop.rs:+16:83: +16:94
+      let mut _13: &[i32; 10];             // in scope 0 at $DIR/reference_prop.rs:+16:83: +16:90
+      let _14: [i32; 10];                  // in scope 0 at $DIR/reference_prop.rs:+16:83: +16:90
+      let mut _15: std::ops::RangeFull;    // in scope 0 at $DIR/reference_prop.rs:+16:91: +16:93
+      let mut _16: usize;                  // in scope 0 at $DIR/reference_prop.rs:+16:12: +16:79
+      let mut _17: usize;                  // in scope 0 at $DIR/reference_prop.rs:+16:12: +16:79
+      let mut _18: bool;                   // in scope 0 at $DIR/reference_prop.rs:+16:12: +16:79
+      let _23: &&mut u8;                   // in scope 0 at $DIR/reference_prop.rs:+19:28: +19:40
+      let _24: &mut u8;                    // in scope 0 at $DIR/reference_prop.rs:+19:29: +19:40
+      let mut _25: debuginfo::T;           // in scope 0 at $DIR/reference_prop.rs:+19:34: +19:38
+      scope 1 {
+-         debug ref_mut_u8 => _1;          // in scope 1 at $DIR/reference_prop.rs:+3:9: +3:19
++         debug ref_mut_u8 => &_2;         // in scope 1 at $DIR/reference_prop.rs:+3:9: +3:19
+          let _3: &u8;                     // in scope 1 at $DIR/reference_prop.rs:+4:9: +4:14
+          let mut _28: &debuginfo::T;      // in scope 1 at $DIR/reference_prop.rs:+4:17: +4:24
+          scope 2 {
+-             debug field => _3;           // in scope 2 at $DIR/reference_prop.rs:+4:9: +4:14
++             debug field => &((*_28).0: u8); // in scope 2 at $DIR/reference_prop.rs:+4:9: +4:14
+              let _5: &u8;                 // in scope 2 at $DIR/reference_prop.rs:+7:9: +7:17
+              scope 3 {
+-                 debug reborrow => _5;    // in scope 3 at $DIR/reference_prop.rs:+7:9: +7:17
++                 debug reborrow => &_2;   // in scope 3 at $DIR/reference_prop.rs:+7:9: +7:17
+                  let _9: &i32;            // in scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+                  let _22: &&&mut u8;      // in scope 3 at $DIR/reference_prop.rs:+19:9: +19:24
+                  let mut _27: &std::option::Option<i32>; // in scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+                  scope 4 {
+-                     debug variant_field => _9; // in scope 4 at $DIR/reference_prop.rs:+11:14: +11:31
++                     debug variant_field => &(((*_27) as Some).0: i32); // in scope 4 at $DIR/reference_prop.rs:+11:14: +11:31
+                  }
+                  scope 5 {
+-                     debug constant_index => _19; // in scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
++                     debug constant_index => &(*_11)[1 of 3]; // in scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+                      debug subslice => _20; // in scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+                      debug constant_index_from_end => _21; // in scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+                      let _19: &i32;       // in scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+                      let _20: &[i32];     // in scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+                      let _21: &i32;       // in scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+                      let mut _26: &[i32; 10]; // in scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+                  }
+                  scope 6 {
+-                     debug multiple_borrow => _22; // in scope 6 at $DIR/reference_prop.rs:+19:9: +19:24
++                     debug multiple_borrow => &&&(_25.0: u8); // in scope 6 at $DIR/reference_prop.rs:+19:9: +19:24
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+3:9: +3:19
+          StorageLive(_2);                 // scope 0 at $DIR/reference_prop.rs:+3:27: +3:31
+          _2 = const 5_u8;                 // scope 0 at $DIR/reference_prop.rs:+3:27: +3:31
+-         _1 = &mut _2;                    // scope 0 at $DIR/reference_prop.rs:+3:22: +3:31
+-         StorageLive(_3);                 // scope 1 at $DIR/reference_prop.rs:+4:9: +4:14
+          _28 = const _;                   // scope 1 at $DIR/reference_prop.rs:+4:17: +4:24
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:535:17: 535:24
+                                           // + literal: Const { ty: &T, val: Unevaluated(debuginfo, [], Some(promoted[2])) }
+-         _3 = &((*_28).0: u8);            // scope 1 at $DIR/reference_prop.rs:+4:17: +4:24
+-         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:9: +7:17
+-         _5 = &(*_1);                     // scope 2 at $DIR/reference_prop.rs:+7:20: +7:32
+-         StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+9:5: +12:6
+          StorageLive(_7);                 // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+          _7 = Option::<i32>::Some(const 0_i32); // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+          _8 = discriminant(_7);           // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+          switchInt(move _8) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 3 at $DIR/reference_prop.rs:+9:5: +9:18
+      }
+  
+      bb1: {
+-         StorageLive(_9);                 // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+          _27 = const _;                   // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:542:14: 542:31
+                                           // + literal: Const { ty: &Option<i32>, val: Unevaluated(debuginfo, [], Some(promoted[1])) }
+-         _9 = &(((*_27) as Some).0: i32); // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+-         _6 = const ();                   // scope 4 at $DIR/reference_prop.rs:+11:36: +11:38
+-         StorageDead(_9);                 // scope 3 at $DIR/reference_prop.rs:+11:37: +11:38
+          goto -> bb4;                     // scope 3 at $DIR/reference_prop.rs:+11:37: +11:38
+      }
+  
+      bb2: {
+          unreachable;                     // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+      }
+  
+      bb3: {
+-         _6 = const ();                   // scope 3 at $DIR/reference_prop.rs:+10:17: +10:19
+          goto -> bb4;                     // scope 3 at $DIR/reference_prop.rs:+10:17: +10:19
+      }
+  
+      bb4: {
+          StorageDead(_7);                 // scope 3 at $DIR/reference_prop.rs:+12:5: +12:6
+-         StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+12:5: +12:6
+-         StorageLive(_10);                // scope 3 at $DIR/reference_prop.rs:+16:5: +17:6
+          StorageLive(_11);                // scope 5 at $DIR/reference_prop.rs:+16:82: +16:94
+          StorageLive(_12);                // scope 5 at $DIR/reference_prop.rs:+16:83: +16:94
+          StorageLive(_13);                // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+          _26 = const _;                   // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:547:83: 547:90
+                                           // + literal: Const { ty: &[i32; 10], val: Unevaluated(debuginfo, [], Some(promoted[0])) }
+          _13 = &(*_26);                   // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+          StorageLive(_15);                // scope 5 at $DIR/reference_prop.rs:+16:91: +16:93
+          _15 = RangeFull;                 // scope 5 at $DIR/reference_prop.rs:+16:91: +16:93
+          _12 = <[i32; 10] as Index<RangeFull>>::index(move _13, move _15) -> bb5; // scope 5 at $DIR/reference_prop.rs:+16:83: +16:94
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:547:83: 547:94
+                                           // + literal: Const { ty: for<'a> fn(&'a [i32; 10], RangeFull) -> &'a <[i32; 10] as Index<RangeFull>>::Output {<[i32; 10] as Index<RangeFull>>::index}, val: Value(<ZST>) }
+      }
+  
+      bb5: {
+          StorageDead(_15);                // scope 5 at $DIR/reference_prop.rs:+16:93: +16:94
+          StorageDead(_13);                // scope 5 at $DIR/reference_prop.rs:+16:93: +16:94
+          _11 = &(*_12);                   // scope 5 at $DIR/reference_prop.rs:+16:82: +16:94
+          _16 = Len((*_11));               // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+          _17 = const 3_usize;             // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+          _18 = Ge(move _16, move _17);    // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+          switchInt(move _18) -> [0: bb7, otherwise: bb6]; // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+      }
+  
+      bb6: {
+-         StorageLive(_19);                // scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+-         _19 = &(*_11)[1 of 3];           // scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+          StorageLive(_20);                // scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+          _20 = &(*_11)[2:-1];             // scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+          StorageLive(_21);                // scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+          _21 = &(*_11)[-1 of 3];          // scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+-         _10 = const ();                  // scope 5 at $DIR/reference_prop.rs:+16:95: +17:6
+          StorageDead(_21);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+          StorageDead(_20);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+-         StorageDead(_19);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+          goto -> bb8;                     // scope 3 at $DIR/reference_prop.rs:+16:5: +17:6
+      }
+  
+      bb7: {
+-         _10 = const ();                  // scope 3 at $DIR/reference_prop.rs:+17:6: +17:6
+          goto -> bb8;                     // scope 3 at $DIR/reference_prop.rs:+16:5: +17:6
+      }
+  
+      bb8: {
+          StorageDead(_12);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+          StorageDead(_11);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+-         StorageDead(_10);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+-         StorageLive(_22);                // scope 3 at $DIR/reference_prop.rs:+19:9: +19:24
+-         StorageLive(_23);                // scope 3 at $DIR/reference_prop.rs:+19:28: +19:40
+-         StorageLive(_24);                // scope 3 at $DIR/reference_prop.rs:+19:29: +19:40
+          StorageLive(_25);                // scope 3 at $DIR/reference_prop.rs:+19:34: +19:38
+          _25 = T(const 6_u8);             // scope 3 at $DIR/reference_prop.rs:+19:34: +19:38
+-         _24 = &mut (_25.0: u8);          // scope 3 at $DIR/reference_prop.rs:+19:29: +19:40
+-         _23 = &_24;                      // scope 3 at $DIR/reference_prop.rs:+19:28: +19:40
+-         _22 = &_23;                      // scope 3 at $DIR/reference_prop.rs:+19:27: +19:40
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+0:16: +20:2
+          StorageDead(_25);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_24);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_23);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_22);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_3);                 // scope 1 at $DIR/reference_prop.rs:+20:1: +20:2
+          StorageDead(_2);                 // scope 0 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+20:1: +20:2
+          return;                          // scope 0 at $DIR/reference_prop.rs:+20:2: +20:2
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
index 8edc83c..e158f64 100644
--- a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
@@ -24,7 +24,7 @@
           _5 = (*_2);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_5) -> bb3;   // scope 0 at $DIR/reference_prop.rs:+16:13: +16:38
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:383:28: 383:34
+                                           // + span: $DIR/reference_prop.rs:455:28: 455:34
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
index 920755b..38ab16c 100644
--- a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
@@ -29,7 +29,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+21:13: +21:27
           _0 = opaque::<i32>(_6) -> bb2;   // scope 0 at $DIR/reference_prop.rs:+22:13: +22:38
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:417:28: 417:34
+                                           // + span: $DIR/reference_prop.rs:489:28: 489:34
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
@@ -37,7 +37,7 @@
           _7 = (*_4);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_7) -> bb3;   // scope 0 at $DIR/reference_prop.rs:+27:13: +27:38
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:422:28: 422:34
+                                           // + span: $DIR/reference_prop.rs:494:28: 494:34
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
@@ -45,7 +45,7 @@
           _8 = (*_5);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_8) -> bb4;   // scope 0 at $DIR/reference_prop.rs:+33:13: +33:43
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:428:33: 428:39
+                                           // + span: $DIR/reference_prop.rs:500:33: 500:39
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
index 07bfdf0..6e45178 100644
--- a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
@@ -16,7 +16,7 @@
           _3 = (*_2);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_3) -> bb1;   // scope 0 at $DIR/reference_prop.rs:+14:13: +14:43
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:357:33: 357:39
+                                           // + span: $DIR/reference_prop.rs:429:33: 429:39
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
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
index af8ee24..d99e110 100644
--- 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
@@ -13,13 +13,16 @@
           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
+-             debug xref => _2;            // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
++             debug xref => &_1;           // 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
+-                 debug xraw => _3;        // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
++                 debug xraw => &_1;       // 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
+-                     debug xshr => _6;    // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
++                     debug xshr => &_1;   // 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
@@ -35,19 +38,17 @@
           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
+-         _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
+-         _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
+-         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
@@ -64,8 +65,8 @@
           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(_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.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
index e41fc28..7b31ee6 100644
--- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
@@ -17,12 +17,12 @@
       let mut _17: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _18: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
       let _19: usize;                      // in scope 0 at $DIR/reference_prop.rs:+22:13: +22:14
-      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _24: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _24: &&usize;                // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _25: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
       let _26: usize;                      // in scope 0 at $DIR/reference_prop.rs:+31:13: +31:14
-      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _31: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _31: *mut &usize;            // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _32: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let _33: usize;                      // in scope 0 at $DIR/reference_prop.rs:+40:13: +40:14
       let _36: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
@@ -35,16 +35,25 @@
       let _48: &T;                         // in scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
       let _50: ();                         // in scope 0 at $DIR/reference_prop.rs:+63:9: +63:19
       let mut _51: ();                     // in scope 0 at $DIR/reference_prop.rs:+63:16: +63:18
-      let _52: &T;                         // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-      let mut _53: &T;                     // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
-      let _54: &T;                         // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
-      let _56: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
-      let mut _57: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _52: ();                         // in scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+      let _53: &T;                         // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
+      let mut _54: &T;                     // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
+      let _55: &T;                         // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
+      let mut _58: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _59: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let _60: usize;                      // in scope 0 at $DIR/reference_prop.rs:+76:13: +76:14
+      let _64: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _65: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _66: usize;                      // in scope 0 at $DIR/reference_prop.rs:+85:13: +85:14
+      let _70: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _71: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
       scope 1 {
           debug a => _4;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
           let _5: &usize;                  // in scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
           scope 2 {
-              debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-             debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
++             debug b => &_4;              // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               let _6: usize;               // in scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
               scope 3 {
                   debug c => _6;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -86,7 +95,7 @@
           let mut _27: &usize;             // in scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           scope 13 {
               debug b => _27;              // in scope 13 at $DIR/reference_prop.rs:+32:13: +32:18
-              let _28: &mut &usize;        // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
+              let _28: *mut &usize;        // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
               scope 14 {
                   debug d => _28;          // in scope 14 at $DIR/reference_prop.rs:+33:13: +33:14
                   let _29: usize;          // in scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -131,17 +140,52 @@
           }
       }
       scope 25 {
-          debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
+-         debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
++         debug a => _1;                   // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
           let _49: T;                      // in scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
           scope 26 {
               debug b => _49;              // in scope 26 at $DIR/reference_prop.rs:+62:13: +62:14
           }
       }
       scope 27 {
-          debug a => _52;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
-          let _55: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          debug a => _53;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
+          let _56: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
           scope 28 {
-              debug b => _55;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+              debug b => _56;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+          }
+      }
+      scope 29 {
+          debug a => _60;                  // in scope 29 at $DIR/reference_prop.rs:+76:13: +76:14
+          let _61: &usize;                 // in scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+          scope 30 {
+-             debug b => _61;              // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
++             debug b => &_60;             // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
+              let _62: &&usize;            // in scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+              scope 31 {
+-                 debug d => _62;          // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
++                 debug d => &&_60;        // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
+                  let _63: usize;          // in scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+                  scope 32 {
+                      debug c => _63;      // in scope 32 at $DIR/reference_prop.rs:+79:13: +79:14
+                  }
+              }
+          }
+      }
+      scope 33 {
+          debug a => _66;                  // in scope 33 at $DIR/reference_prop.rs:+85:13: +85:14
+          let mut _67: &usize;             // in scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+          scope 34 {
+-             debug b => _67;              // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
++             debug b => &_66;             // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
+              let _68: &mut &usize;        // in scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+              scope 35 {
+-                 debug d => _68;          // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
++                 debug d => &&_66;        // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
+                  let _69: usize;          // in scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+                  scope 36 {
+                      debug c => _69;      // in scope 36 at $DIR/reference_prop.rs:+88:13: +88:14
+                  }
+              }
           }
       }
   
@@ -149,8 +193,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 0 at $DIR/reference_prop.rs:+3:13: +3:14
           _4 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+3:17: +3:24
-          StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &_4;                        // scope 1 at $DIR/reference_prop.rs:+4:17: +4:19
+-         StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &_4;                        // scope 1 at $DIR/reference_prop.rs:+4:17: +4:19
           StorageLive(_6);                 // scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -168,7 +212,7 @@
           StorageDead(_7);                 // scope 3 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -215,18 +259,18 @@
           _21 = &_20;                      // scope 9 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_22);                // scope 10 at $DIR/reference_prop.rs:+25:13: +25:14
           _22 = (*_20);                    // scope 10 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _24 = ();                        // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = opaque::<()>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _24 = _21;                       // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = opaque::<&&usize>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
                                            // + span: $DIR/reference_prop.rs:36:9: 36:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + literal: Const { ty: fn(&&usize) {opaque::<&&usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _18 = const ();                  // scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_22);                // scope 10 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_21);                // scope 9 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -239,21 +283,21 @@
           StorageLive(_27);                // scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           _27 = &_26;                      // scope 12 at $DIR/reference_prop.rs:+32:21: +32:23
           StorageLive(_28);                // scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
-          _28 = &mut _27;                  // scope 13 at $DIR/reference_prop.rs:+33:17: +33:23
+          _28 = &raw mut _27;              // scope 13 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_29);                // scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
           _29 = (*_27);                    // scope 14 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _31 = ();                        // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = opaque::<()>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _31 = _28;                       // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = opaque::<*mut &usize>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
                                            // + span: $DIR/reference_prop.rs:45:9: 45:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + literal: Const { ty: fn(*mut &usize) {opaque::<*mut &usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _25 = const ();                  // scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_29);                // scope 14 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_28);                // scope 13 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -321,8 +365,8 @@
           StorageDead(_39);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_38);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_47);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
-          _48 = &(*_1);                    // scope 0 at $DIR/reference_prop.rs:+61:17: +61:25
+-         StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _48 = &(*_1);                    // scope 0 at $DIR/reference_prop.rs:+61:17: +61:25
           StorageLive(_49);                // scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _49 = (*_48);                    // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _49 = (*_1);                     // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -340,36 +384,92 @@
           StorageDead(_50);                // scope 26 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _47 = const ();                  // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_49);                // scope 25 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_47);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-          _52 = &(*_2);                    // scope 0 at $DIR/reference_prop.rs:+68:17: +68:27
-          StorageLive(_53);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
--         StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
--         _54 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
--         _53 = &(*_54);                   // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
-+         _53 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
-          _2 = move _53;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:28
-          StorageDead(_53);                // scope 27 at $DIR/reference_prop.rs:+69:27: +69:28
--         StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:28: +69:29
-          StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
-          _55 = (*_52);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
-          StorageLive(_56);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
-          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _57 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _56 = opaque::<()>(move _57) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+-         StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageLive(_53);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
+          _53 = &(*_2);                    // scope 0 at $DIR/reference_prop.rs:+68:17: +68:27
+          StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+-         StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+-         _55 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+-         _54 = &(*_55);                   // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
++         _54 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+          _2 = move _54;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:28
+          StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:27: +69:28
+-         StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+69:28: +69:29
+          StorageLive(_56);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          _56 = (*_53);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
+          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+          StorageLive(_58);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _58 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _57 = opaque::<()>(move _58) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
                                            // + span: $DIR/reference_prop.rs:81:9: 81:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb8: {
-          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
-          StorageDead(_56);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
-          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
-          StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+73:2: +73:2
+          StorageDead(_58);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
+          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
+-         _52 = const ();                  // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageDead(_56);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
+          StorageDead(_53);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageLive(_59);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_60);                // scope 0 at $DIR/reference_prop.rs:+76:13: +76:14
+          _60 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+76:17: +76:24
+-         StorageLive(_61);                // scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _61 = &_60;                      // scope 29 at $DIR/reference_prop.rs:+77:17: +77:19
+-         StorageLive(_62);                // scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _62 = &_61;                      // scope 30 at $DIR/reference_prop.rs:+78:17: +78:19
+          StorageLive(_63);                // scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _63 = (*_61);                    // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
++         _63 = _60;                       // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_64);                // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_65);                // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _65 = ();                        // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _64 = opaque::<()>(move _65) -> bb9; // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:90:9: 90:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb9: {
+          StorageDead(_65);                // scope 32 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_64);                // scope 32 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _59 = const ();                  // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_63);                // scope 31 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_62);                // scope 30 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_61);                // scope 29 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_60);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageLive(_66);                // scope 0 at $DIR/reference_prop.rs:+85:13: +85:14
+          _66 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+85:17: +85:24
+-         StorageLive(_67);                // scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+-         _67 = &_66;                      // scope 33 at $DIR/reference_prop.rs:+86:21: +86:23
+-         StorageLive(_68);                // scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _68 = &mut _67;                  // scope 34 at $DIR/reference_prop.rs:+87:17: +87:23
+          StorageLive(_69);                // scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _69 = (*_67);                    // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
++         _69 = _66;                       // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_70);                // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_71);                // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _71 = ();                        // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _70 = opaque::<()>(move _71) -> bb10; // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:99:9: 99:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_71);                // scope 36 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_70);                // scope 36 at $DIR/reference_prop.rs:+89:19: +89:20
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_69);                // scope 35 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_68);                // scope 34 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_67);                // scope 33 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_66);                // scope 0 at $DIR/reference_prop.rs:+90:5: +90:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+91:2: +91:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
index 7127279..ddeb04e 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
@@ -13,11 +13,11 @@
       let _15: ();                         // in scope 0 at $DIR/reference_prop.rs:+17:9: +17:19
       let mut _16: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _17: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
-      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _23: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _23: &*const usize;          // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _24: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
-      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _30: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _30: *mut *const usize;      // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _31: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let _35: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
       let mut _36: *const usize;           // in scope 0 at $DIR/reference_prop.rs:+43:16: +43:17
@@ -31,15 +31,22 @@
       let mut _53: *const T;               // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:38
       let _55: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
       let mut _56: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
-      let _61: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
-      let mut _62: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let _62: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _63: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _64: ();                         // in scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+      let _69: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _70: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
+      let _75: ();                         // in scope 0 at $DIR/reference_prop.rs:+98:9: +98:19
+      let mut _76: ();                     // in scope 0 at $DIR/reference_prop.rs:+98:16: +98:18
       scope 1 {
           let _4: usize;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
           scope 2 {
               debug a => _4;               // in scope 2 at $DIR/reference_prop.rs:+3:13: +3:14
               let _5: *const usize;        // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               scope 3 {
-                  debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
+-                 debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
++                 debug b => &_4;          // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
                   let _6: usize;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
                   scope 4 {
                       debug c => _6;       // in scope 4 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -90,7 +97,7 @@
               let mut _26: *const usize;   // in scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
               scope 17 {
                   debug b => _26;          // in scope 17 at $DIR/reference_prop.rs:+32:13: +32:18
-                  let _27: &mut *const usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
+                  let _27: *mut *const usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
                   scope 18 {
                       debug d => _27;      // in scope 18 at $DIR/reference_prop.rs:+33:13: +33:14
                       let _28: usize;      // in scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -144,7 +151,8 @@
       scope 31 {
           let _47: *const T;               // in scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
           scope 32 {
-              debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
+-             debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
++             debug a => _1;               // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
               let _48: T;                  // in scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
               scope 33 {
                   debug b => _48;          // in scope 33 at $DIR/reference_prop.rs:+62:13: +62:14
@@ -162,18 +170,60 @@
           }
       }
       scope 37 {
-          let _57: usize;                  // in scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
+          let _58: usize;                  // in scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
           scope 38 {
-              debug a => _57;              // in scope 38 at $DIR/reference_prop.rs:+76:13: +76:14
-              let _58: *const usize;       // in scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+              debug a => _58;              // in scope 38 at $DIR/reference_prop.rs:+76:13: +76:14
+              let _59: *const usize;       // in scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
               scope 39 {
-                  debug b => _58;          // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
-                  let _59: *const usize;   // in scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+-                 debug b => _59;          // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
++                 debug b => &_58;         // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
+                  let _60: *const usize;   // in scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
                   scope 40 {
-                      debug c => _59;      // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
-                      let _60: usize;      // in scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+-                     debug c => _60;      // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
++                     debug c => &_58;     // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
+                      let _61: usize;      // in scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
                       scope 41 {
-                          debug e => _60;  // in scope 41 at $DIR/reference_prop.rs:+79:13: +79:14
+                          debug e => _61;  // in scope 41 at $DIR/reference_prop.rs:+79:13: +79:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 42 {
+          let _65: usize;                  // in scope 42 at $DIR/reference_prop.rs:+85:13: +85:14
+          scope 43 {
+              debug a => _65;              // in scope 43 at $DIR/reference_prop.rs:+85:13: +85:14
+              let _66: *const usize;       // in scope 43 at $DIR/reference_prop.rs:+86:13: +86:14
+              scope 44 {
+-                 debug b => _66;          // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:14
++                 debug b => &_65;         // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:14
+                  let _67: &*const usize;  // in scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+                  scope 45 {
+-                     debug d => _67;      // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
++                     debug d => &&_65;    // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
+                      let _68: usize;      // in scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+                      scope 46 {
+                          debug c => _68;  // in scope 46 at $DIR/reference_prop.rs:+88:13: +88:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 47 {
+          let _71: usize;                  // in scope 47 at $DIR/reference_prop.rs:+94:13: +94:14
+          scope 48 {
+              debug a => _71;              // in scope 48 at $DIR/reference_prop.rs:+94:13: +94:14
+              let mut _72: *const usize;   // in scope 48 at $DIR/reference_prop.rs:+95:13: +95:18
+              scope 49 {
+-                 debug b => _72;          // in scope 49 at $DIR/reference_prop.rs:+95:13: +95:18
++                 debug b => &_71;         // in scope 49 at $DIR/reference_prop.rs:+95:13: +95:18
+                  let _73: &mut *const usize; // in scope 49 at $DIR/reference_prop.rs:+96:13: +96:14
+                  scope 50 {
+-                     debug d => _73;      // in scope 50 at $DIR/reference_prop.rs:+96:13: +96:14
++                     debug d => &&_71;    // in scope 50 at $DIR/reference_prop.rs:+96:13: +96:14
+                      let _74: usize;      // in scope 50 at $DIR/reference_prop.rs:+97:13: +97:14
+                      scope 51 {
+                          debug c => _74;  // in scope 51 at $DIR/reference_prop.rs:+97:13: +97:14
                       }
                   }
               }
@@ -184,8 +234,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
           _4 = const 5_usize;              // scope 1 at $DIR/reference_prop.rs:+3:17: +3:24
-          StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &raw const _4;              // scope 2 at $DIR/reference_prop.rs:+4:17: +4:29
+-         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &raw const _4;              // scope 2 at $DIR/reference_prop.rs:+4:17: +4:29
           StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -194,7 +244,7 @@
           _8 = ();                         // scope 4 at $DIR/reference_prop.rs:+6:16: +6:18
           _7 = opaque::<()>(move _8) -> bb1; // scope 4 at $DIR/reference_prop.rs:+6:9: +6:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:166:9: 166:15
+                                           // + span: $DIR/reference_prop.rs:202:9: 202:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -203,7 +253,7 @@
           StorageDead(_7);                 // scope 4 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 1 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -224,7 +274,7 @@
           _16 = ();                        // scope 9 at $DIR/reference_prop.rs:+17:16: +17:18
           _15 = opaque::<()>(move _16) -> bb2; // scope 9 at $DIR/reference_prop.rs:+17:9: +17:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:177:9: 177:15
+                                           // + span: $DIR/reference_prop.rs:213:9: 213:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -246,18 +296,18 @@
           _20 = &_19;                      // scope 12 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_21);                // scope 13 at $DIR/reference_prop.rs:+25:13: +25:14
           _21 = (*_19);                    // scope 13 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = ();                        // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _22 = opaque::<()>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = _20;                       // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _22 = opaque::<&*const usize>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:186:9: 186:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:222:9: 222:15
+                                           // + literal: Const { ty: fn(&*const usize) {opaque::<&*const usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _17 = const ();                  // scope 10 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_21);                // scope 13 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_20);                // scope 12 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -270,21 +320,21 @@
           StorageLive(_26);                // scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
           _26 = &raw const _25;            // scope 16 at $DIR/reference_prop.rs:+32:21: +32:33
           StorageLive(_27);                // scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
-          _27 = &mut _26;                  // scope 17 at $DIR/reference_prop.rs:+33:17: +33:23
+          _27 = &raw mut _26;              // scope 17 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_28);                // scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
           _28 = (*_26);                    // scope 18 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = ();                        // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _29 = opaque::<()>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = _27;                       // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _29 = opaque::<*mut *const usize>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:195:9: 195:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:231:9: 231:15
+                                           // + literal: Const { ty: fn(*mut *const usize) {opaque::<*mut *const usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _24 = const ();                  // scope 15 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_28);                // scope 18 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_27);                // scope 17 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -304,7 +354,7 @@
           _36 = _33;                       // scope 23 at $DIR/reference_prop.rs:+43:16: +43:17
           _35 = opaque::<*const usize>(move _36) -> bb5; // scope 23 at $DIR/reference_prop.rs:+43:9: +43:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:203:9: 203:15
+                                           // + span: $DIR/reference_prop.rs:239:9: 239:15
                                            // + literal: Const { ty: fn(*const usize) {opaque::<*const usize>}, val: Value(<ZST>) }
       }
   
@@ -336,7 +386,7 @@
           _45 = _43;                       // scope 30 at $DIR/reference_prop.rs:+56:16: +56:18
           _44 = opaque::<*const usize>(move _45) -> bb6; // scope 30 at $DIR/reference_prop.rs:+56:9: +56:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:216:9: 216:15
+                                           // + span: $DIR/reference_prop.rs:252:9: 252:15
                                            // + literal: Const { ty: fn(*const usize) {opaque::<*const usize>}, val: Value(<ZST>) }
       }
   
@@ -352,8 +402,8 @@
           StorageDead(_38);                // scope 24 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_37);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_46);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
-          _47 = &raw const (*_1);          // scope 31 at $DIR/reference_prop.rs:+61:17: +61:35
+-         StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _47 = &raw const (*_1);          // scope 31 at $DIR/reference_prop.rs:+61:17: +61:35
           StorageLive(_48);                // scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _48 = (*_47);                    // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _48 = (*_1);                     // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -362,7 +412,7 @@
           _50 = ();                        // scope 33 at $DIR/reference_prop.rs:+63:16: +63:18
           _49 = opaque::<()>(move _50) -> bb7; // scope 33 at $DIR/reference_prop.rs:+63:9: +63:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:223:9: 223:15
+                                           // + span: $DIR/reference_prop.rs:259:9: 259:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -371,7 +421,7 @@
           StorageDead(_49);                // scope 33 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _46 = const ();                  // scope 31 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_48);                // scope 32 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_46);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageLive(_51);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
           StorageLive(_52);                // scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
@@ -387,7 +437,7 @@
           _56 = ();                        // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
           _55 = opaque::<()>(move _56) -> bb8; // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:231:9: 231:15
+                                           // + span: $DIR/reference_prop.rs:267:9: 267:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -398,34 +448,89 @@
           StorageDead(_54);                // scope 35 at $DIR/reference_prop.rs:+72:5: +72:6
           StorageDead(_52);                // scope 34 at $DIR/reference_prop.rs:+72:5: +72:6
 -         StorageDead(_51);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageLive(_57);                // scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
-          _57 = const 13_usize;            // scope 37 at $DIR/reference_prop.rs:+76:17: +76:25
-          StorageLive(_58);                // scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
-          _58 = &raw const _57;            // scope 38 at $DIR/reference_prop.rs:+77:17: +77:29
-          StorageLive(_59);                // scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
--         _59 = &raw const (*_58);         // scope 39 at $DIR/reference_prop.rs:+78:17: +78:30
-+         _59 = &raw const _57;            // scope 39 at $DIR/reference_prop.rs:+78:17: +78:30
-          StorageLive(_60);                // scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
--         _60 = (*_59);                    // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
-+         _60 = _57;                       // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
-          StorageLive(_61);                // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
-          StorageLive(_62);                // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
-          _62 = ();                        // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
-          _61 = opaque::<()>(move _62) -> bb9; // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+-         StorageLive(_57);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_58);                // scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
+          _58 = const 13_usize;            // scope 37 at $DIR/reference_prop.rs:+76:17: +76:25
+-         StorageLive(_59);                // scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _59 = &raw const _58;            // scope 38 at $DIR/reference_prop.rs:+77:17: +77:29
+-         StorageLive(_60);                // scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _60 = &raw const (*_59);         // scope 39 at $DIR/reference_prop.rs:+78:17: +78:30
+          StorageLive(_61);                // scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _61 = (*_60);                    // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
++         _61 = _58;                       // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_62);                // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_63);                // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _63 = ();                        // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _62 = opaque::<()>(move _63) -> bb9; // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:240:9: 240:15
+                                           // + span: $DIR/reference_prop.rs:276:9: 276:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb9: {
-          StorageDead(_62);                // scope 41 at $DIR/reference_prop.rs:+80:18: +80:19
-          StorageDead(_61);                // scope 41 at $DIR/reference_prop.rs:+80:19: +80:20
-          _0 = const ();                   // scope 37 at $DIR/reference_prop.rs:+75:5: +81:6
-          StorageDead(_60);                // scope 40 at $DIR/reference_prop.rs:+81:5: +81:6
-          StorageDead(_59);                // scope 39 at $DIR/reference_prop.rs:+81:5: +81:6
-          StorageDead(_58);                // scope 38 at $DIR/reference_prop.rs:+81:5: +81:6
-          StorageDead(_57);                // scope 37 at $DIR/reference_prop.rs:+81:5: +81:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+82:2: +82:2
+          StorageDead(_63);                // scope 41 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_62);                // scope 41 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _57 = const ();                  // scope 37 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_61);                // scope 40 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_60);                // scope 39 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 38 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_58);                // scope 37 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_57);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageLive(_64);                // scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageLive(_65);                // scope 42 at $DIR/reference_prop.rs:+85:13: +85:14
+          _65 = const 5_usize;             // scope 42 at $DIR/reference_prop.rs:+85:17: +85:24
+-         StorageLive(_66);                // scope 43 at $DIR/reference_prop.rs:+86:13: +86:14
+-         _66 = &raw const _65;            // scope 43 at $DIR/reference_prop.rs:+86:17: +86:29
+-         StorageLive(_67);                // scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _67 = &_66;                      // scope 44 at $DIR/reference_prop.rs:+87:17: +87:19
+          StorageLive(_68);                // scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _68 = (*_66);                    // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
++         _68 = _65;                       // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_69);                // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_70);                // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _70 = ();                        // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _69 = opaque::<()>(move _70) -> bb10; // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:285:9: 285:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_70);                // scope 46 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_69);                // scope 46 at $DIR/reference_prop.rs:+89:19: +89:20
+-         _64 = const ();                  // scope 42 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_68);                // scope 45 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_67);                // scope 44 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_66);                // scope 43 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_65);                // scope 42 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_64);                // scope 0 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageLive(_71);                // scope 47 at $DIR/reference_prop.rs:+94:13: +94:14
+          _71 = const 5_usize;             // scope 47 at $DIR/reference_prop.rs:+94:17: +94:24
+-         StorageLive(_72);                // scope 48 at $DIR/reference_prop.rs:+95:13: +95:18
+-         _72 = &raw const _71;            // scope 48 at $DIR/reference_prop.rs:+95:21: +95:33
+-         StorageLive(_73);                // scope 49 at $DIR/reference_prop.rs:+96:13: +96:14
+-         _73 = &mut _72;                  // scope 49 at $DIR/reference_prop.rs:+96:17: +96:23
+          StorageLive(_74);                // scope 50 at $DIR/reference_prop.rs:+97:13: +97:14
+-         _74 = (*_72);                    // scope 50 at $DIR/reference_prop.rs:+97:17: +97:19
++         _74 = _71;                       // scope 50 at $DIR/reference_prop.rs:+97:17: +97:19
+          StorageLive(_75);                // scope 51 at $DIR/reference_prop.rs:+98:9: +98:19
+          StorageLive(_76);                // scope 51 at $DIR/reference_prop.rs:+98:16: +98:18
+          _76 = ();                        // scope 51 at $DIR/reference_prop.rs:+98:16: +98:18
+          _75 = opaque::<()>(move _76) -> bb11; // scope 51 at $DIR/reference_prop.rs:+98:9: +98:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:294:9: 294:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb11: {
+          StorageDead(_76);                // scope 51 at $DIR/reference_prop.rs:+98:18: +98:19
+          StorageDead(_75);                // scope 51 at $DIR/reference_prop.rs:+98:19: +98:20
+          _0 = const ();                   // scope 47 at $DIR/reference_prop.rs:+93:5: +99:6
+          StorageDead(_74);                // scope 50 at $DIR/reference_prop.rs:+99:5: +99:6
+-         StorageDead(_73);                // scope 49 at $DIR/reference_prop.rs:+99:5: +99:6
+-         StorageDead(_72);                // scope 48 at $DIR/reference_prop.rs:+99:5: +99:6
+          StorageDead(_71);                // scope 47 at $DIR/reference_prop.rs:+99:5: +99:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+100:2: +100:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
index 44ddbbc..8d059de 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
@@ -17,12 +17,12 @@
       let mut _17: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _18: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
       let mut _19: usize;                  // in scope 0 at $DIR/reference_prop.rs:+22:13: +22:18
-      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _24: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _24: &&mut usize;            // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _25: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
       let mut _26: usize;                  // in scope 0 at $DIR/reference_prop.rs:+31:13: +31:18
-      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _31: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _31: *mut &mut usize;        // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _32: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let mut _33: usize;                  // in scope 0 at $DIR/reference_prop.rs:+40:13: +40:18
       let _36: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
@@ -35,16 +35,25 @@
       let _48: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
       let _50: ();                         // in scope 0 at $DIR/reference_prop.rs:+63:9: +63:19
       let mut _51: ();                     // in scope 0 at $DIR/reference_prop.rs:+63:16: +63:18
-      let _52: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-      let mut _53: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:32
+      let _52: ();                         // in scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+      let _53: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
       let mut _54: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:32
-      let _56: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
-      let mut _57: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let mut _55: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:32
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
+      let mut _58: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _59: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let mut _60: usize;                  // in scope 0 at $DIR/reference_prop.rs:+76:13: +76:18
+      let _64: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _65: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let mut _66: usize;                  // in scope 0 at $DIR/reference_prop.rs:+85:13: +85:18
+      let _70: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _71: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
       scope 1 {
           debug a => _4;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
           let _5: &mut usize;              // in scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
           scope 2 {
-              debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-             debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
++             debug b => &_4;              // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               let _6: usize;               // in scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
               scope 3 {
                   debug c => _6;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -86,7 +95,7 @@
           let mut _27: &mut usize;         // in scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           scope 13 {
               debug b => _27;              // in scope 13 at $DIR/reference_prop.rs:+32:13: +32:18
-              let _28: &mut &mut usize;    // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
+              let _28: *mut &mut usize;    // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
               scope 14 {
                   debug d => _28;          // in scope 14 at $DIR/reference_prop.rs:+33:13: +33:14
                   let _29: usize;          // in scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -131,17 +140,52 @@
           }
       }
       scope 25 {
-          debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
+-         debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
++         debug a => _1;                   // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
           let _49: T;                      // in scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
           scope 26 {
               debug b => _49;              // in scope 26 at $DIR/reference_prop.rs:+62:13: +62:14
           }
       }
       scope 27 {
-          debug a => _52;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
-          let _55: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          debug a => _53;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
+          let _56: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
           scope 28 {
-              debug b => _55;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+              debug b => _56;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+          }
+      }
+      scope 29 {
+          debug a => _60;                  // in scope 29 at $DIR/reference_prop.rs:+76:13: +76:18
+          let _61: &mut usize;             // in scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+          scope 30 {
+-             debug b => _61;              // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
++             debug b => &_60;             // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
+              let _62: &&mut usize;        // in scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+              scope 31 {
+-                 debug d => _62;          // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
++                 debug d => &&_60;        // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
+                  let _63: usize;          // in scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+                  scope 32 {
+                      debug c => _63;      // in scope 32 at $DIR/reference_prop.rs:+79:13: +79:14
+                  }
+              }
+          }
+      }
+      scope 33 {
+          debug a => _66;                  // in scope 33 at $DIR/reference_prop.rs:+85:13: +85:18
+          let mut _67: &mut usize;         // in scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+          scope 34 {
+-             debug b => _67;              // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
++             debug b => &_66;             // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
+              let _68: &mut &mut usize;    // in scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+              scope 35 {
+-                 debug d => _68;          // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
++                 debug d => &&_66;        // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
+                  let _69: usize;          // in scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+                  scope 36 {
+                      debug c => _69;      // in scope 36 at $DIR/reference_prop.rs:+88:13: +88:14
+                  }
+              }
           }
       }
   
@@ -149,8 +193,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 0 at $DIR/reference_prop.rs:+3:13: +3:18
           _4 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+3:21: +3:28
-          StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &mut _4;                    // scope 1 at $DIR/reference_prop.rs:+4:17: +4:23
+-         StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &mut _4;                    // scope 1 at $DIR/reference_prop.rs:+4:17: +4:23
           StorageLive(_6);                 // scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -159,7 +203,7 @@
           _8 = ();                         // scope 3 at $DIR/reference_prop.rs:+6:16: +6:18
           _7 = opaque::<()>(move _8) -> bb1; // scope 3 at $DIR/reference_prop.rs:+6:9: +6:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:91:9: 91:15
+                                           // + span: $DIR/reference_prop.rs:109:9: 109:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -168,7 +212,7 @@
           StorageDead(_7);                 // scope 3 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -193,7 +237,7 @@
           _17 = ();                        // scope 7 at $DIR/reference_prop.rs:+17:16: +17:18
           _16 = opaque::<()>(move _17) -> bb2; // scope 7 at $DIR/reference_prop.rs:+17:9: +17:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:102:9: 102:15
+                                           // + span: $DIR/reference_prop.rs:120:9: 120:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -215,18 +259,18 @@
           _21 = &_20;                      // scope 9 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_22);                // scope 10 at $DIR/reference_prop.rs:+25:13: +25:14
           _22 = (*_20);                    // scope 10 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _24 = ();                        // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = opaque::<()>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _24 = _21;                       // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = opaque::<&&mut usize>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:111:9: 111:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:129:9: 129:15
+                                           // + literal: Const { ty: fn(&&mut usize) {opaque::<&&mut usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _18 = const ();                  // scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_22);                // scope 10 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_21);                // scope 9 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -239,21 +283,21 @@
           StorageLive(_27);                // scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           _27 = &mut _26;                  // scope 12 at $DIR/reference_prop.rs:+32:21: +32:27
           StorageLive(_28);                // scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
-          _28 = &mut _27;                  // scope 13 at $DIR/reference_prop.rs:+33:17: +33:23
+          _28 = &raw mut _27;              // scope 13 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_29);                // scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
           _29 = (*_27);                    // scope 14 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _31 = ();                        // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = opaque::<()>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _31 = _28;                       // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = opaque::<*mut &mut usize>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:120:9: 120:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:138:9: 138:15
+                                           // + literal: Const { ty: fn(*mut &mut usize) {opaque::<*mut &mut usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _25 = const ();                  // scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_29);                // scope 14 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_28);                // scope 13 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -272,7 +316,7 @@
           _37 = move _34;                  // scope 18 at $DIR/reference_prop.rs:+43:16: +43:17
           _36 = opaque::<&mut usize>(move _37) -> bb5; // scope 18 at $DIR/reference_prop.rs:+43:9: +43:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:128:9: 128:15
+                                           // + span: $DIR/reference_prop.rs:146:9: 146:15
                                            // + literal: Const { ty: fn(&mut usize) {opaque::<&mut usize>}, val: Value(<ZST>) }
       }
   
@@ -302,7 +346,7 @@
           _46 = move _44;                  // scope 24 at $DIR/reference_prop.rs:+56:16: +56:18
           _45 = opaque::<&mut usize>(move _46) -> bb6; // scope 24 at $DIR/reference_prop.rs:+56:9: +56:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:141:9: 141:15
+                                           // + span: $DIR/reference_prop.rs:159:9: 159:15
                                            // + literal: Const { ty: fn(&mut usize) {opaque::<&mut usize>}, val: Value(<ZST>) }
       }
   
@@ -318,8 +362,8 @@
           StorageDead(_39);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_38);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_47);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
-          _48 = &mut (*_1);                // scope 0 at $DIR/reference_prop.rs:+61:17: +61:29
+-         StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _48 = &mut (*_1);                // scope 0 at $DIR/reference_prop.rs:+61:17: +61:29
           StorageLive(_49);                // scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _49 = (*_48);                    // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _49 = (*_1);                     // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -328,7 +372,7 @@
           _51 = ();                        // scope 26 at $DIR/reference_prop.rs:+63:16: +63:18
           _50 = opaque::<()>(move _51) -> bb7; // scope 26 at $DIR/reference_prop.rs:+63:9: +63:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:148:9: 148:15
+                                           // + span: $DIR/reference_prop.rs:166:9: 166:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -337,36 +381,92 @@
           StorageDead(_50);                // scope 26 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _47 = const ();                  // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_49);                // scope 25 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_47);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-          _52 = &mut (*_2);                // scope 0 at $DIR/reference_prop.rs:+68:17: +68:31
-          StorageLive(_53);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
--         StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
--         _54 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
--         _53 = &mut (*_54);               // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
-+         _53 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
-          _2 = move _53;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:32
-          StorageDead(_53);                // scope 27 at $DIR/reference_prop.rs:+69:31: +69:32
--         StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:32: +69:33
-          StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
-          _55 = (*_52);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
-          StorageLive(_56);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
-          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _57 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _56 = opaque::<()>(move _57) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+-         StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageLive(_53);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
+          _53 = &mut (*_2);                // scope 0 at $DIR/reference_prop.rs:+68:17: +68:31
+          StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+-         StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+-         _55 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+-         _54 = &mut (*_55);               // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
++         _54 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+          _2 = move _54;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:32
+          StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:31: +69:32
+-         StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+69:32: +69:33
+          StorageLive(_56);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          _56 = (*_53);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
+          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+          StorageLive(_58);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _58 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _57 = opaque::<()>(move _58) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:156:9: 156:15
+                                           // + span: $DIR/reference_prop.rs:174:9: 174:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb8: {
-          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
-          StorageDead(_56);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
-          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
-          StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+73:2: +73:2
+          StorageDead(_58);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
+          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
+-         _52 = const ();                  // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageDead(_56);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
+          StorageDead(_53);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageLive(_59);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_60);                // scope 0 at $DIR/reference_prop.rs:+76:13: +76:18
+          _60 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+76:21: +76:28
+-         StorageLive(_61);                // scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _61 = &mut _60;                  // scope 29 at $DIR/reference_prop.rs:+77:17: +77:23
+-         StorageLive(_62);                // scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _62 = &_61;                      // scope 30 at $DIR/reference_prop.rs:+78:17: +78:19
+          StorageLive(_63);                // scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _63 = (*_61);                    // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
++         _63 = _60;                       // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_64);                // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_65);                // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _65 = ();                        // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _64 = opaque::<()>(move _65) -> bb9; // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:183:9: 183:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb9: {
+          StorageDead(_65);                // scope 32 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_64);                // scope 32 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _59 = const ();                  // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_63);                // scope 31 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_62);                // scope 30 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_61);                // scope 29 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_60);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageLive(_66);                // scope 0 at $DIR/reference_prop.rs:+85:13: +85:18
+          _66 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+85:21: +85:28
+-         StorageLive(_67);                // scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+-         _67 = &mut _66;                  // scope 33 at $DIR/reference_prop.rs:+86:21: +86:27
+-         StorageLive(_68);                // scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _68 = &mut _67;                  // scope 34 at $DIR/reference_prop.rs:+87:17: +87:23
+          StorageLive(_69);                // scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _69 = (*_67);                    // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
++         _69 = _66;                       // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_70);                // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_71);                // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _71 = ();                        // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _70 = opaque::<()>(move _71) -> bb10; // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:192:9: 192:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_71);                // scope 36 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_70);                // scope 36 at $DIR/reference_prop.rs:+89:19: +89:20
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_69);                // scope 35 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_68);                // scope 34 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_67);                // scope 33 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_66);                // scope 0 at $DIR/reference_prop.rs:+90:5: +90:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+91:2: +91:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
index c55b5eb..c93aa52 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
@@ -13,11 +13,11 @@
       let _15: ();                         // in scope 0 at $DIR/reference_prop.rs:+17:9: +17:19
       let mut _16: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _17: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
-      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _23: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _23: &*mut usize;            // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _24: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
-      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _30: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _30: *mut *mut usize;        // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _31: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let _35: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
       let mut _36: *mut usize;             // in scope 0 at $DIR/reference_prop.rs:+43:16: +43:17
@@ -27,16 +27,23 @@
       let _46: ();                         // in scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
       let _49: ();                         // in scope 0 at $DIR/reference_prop.rs:+63:9: +63:19
       let mut _50: ();                     // in scope 0 at $DIR/reference_prop.rs:+63:16: +63:18
-      let mut _52: *mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:36
-      let _54: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
-      let mut _55: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _51: ();                         // in scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+      let mut _53: *mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:36
+      let _55: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
+      let mut _56: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let _62: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _63: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _68: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _69: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
       scope 1 {
           let mut _4: usize;               // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
           scope 2 {
               debug a => _4;               // in scope 2 at $DIR/reference_prop.rs:+3:13: +3:18
               let _5: *mut usize;          // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               scope 3 {
-                  debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
+-                 debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
++                 debug b => &_4;          // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
                   let _6: usize;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
                   scope 4 {
                       debug c => _6;       // in scope 4 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -87,7 +94,7 @@
               let mut _26: *mut usize;     // in scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
               scope 17 {
                   debug b => _26;          // in scope 17 at $DIR/reference_prop.rs:+32:13: +32:18
-                  let _27: &mut *mut usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
+                  let _27: *mut *mut usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
                   scope 18 {
                       debug d => _27;      // in scope 18 at $DIR/reference_prop.rs:+33:13: +33:14
                       let _28: usize;      // in scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -141,7 +148,8 @@
       scope 31 {
           let _47: *mut T;                 // in scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
           scope 32 {
-              debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
+-             debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
++             debug a => _1;               // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
               let _48: T;                  // in scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
               scope 33 {
                   debug b => _48;          // in scope 33 at $DIR/reference_prop.rs:+62:13: +62:14
@@ -149,12 +157,52 @@
           }
       }
       scope 34 {
-          let _51: *mut T;                 // in scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
+          let _52: *mut T;                 // in scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
           scope 35 {
-              debug a => _51;              // in scope 35 at $DIR/reference_prop.rs:+68:13: +68:14
-              let _53: T;                  // in scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
+              debug a => _52;              // in scope 35 at $DIR/reference_prop.rs:+68:13: +68:14
+              let _54: T;                  // in scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
               scope 36 {
-                  debug b => _53;          // in scope 36 at $DIR/reference_prop.rs:+70:13: +70:14
+                  debug b => _54;          // in scope 36 at $DIR/reference_prop.rs:+70:13: +70:14
+              }
+          }
+      }
+      scope 37 {
+          let mut _58: usize;              // in scope 37 at $DIR/reference_prop.rs:+76:13: +76:18
+          scope 38 {
+              debug a => _58;              // in scope 38 at $DIR/reference_prop.rs:+76:13: +76:18
+              let _59: *mut usize;         // in scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+              scope 39 {
+-                 debug b => _59;          // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
++                 debug b => &_58;         // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
+                  let _60: &*mut usize;    // in scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+                  scope 40 {
+-                     debug d => _60;      // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
++                     debug d => &&_58;    // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
+                      let _61: usize;      // in scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+                      scope 41 {
+                          debug c => _61;  // in scope 41 at $DIR/reference_prop.rs:+79:13: +79:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 42 {
+          let mut _64: usize;              // in scope 42 at $DIR/reference_prop.rs:+85:13: +85:18
+          scope 43 {
+              debug a => _64;              // in scope 43 at $DIR/reference_prop.rs:+85:13: +85:18
+              let mut _65: *mut usize;     // in scope 43 at $DIR/reference_prop.rs:+86:13: +86:18
+              scope 44 {
+-                 debug b => _65;          // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:18
++                 debug b => &_64;         // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:18
+                  let _66: &mut *mut usize; // in scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+                  scope 45 {
+-                     debug d => _66;      // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
++                     debug d => &&_64;    // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
+                      let _67: usize;      // in scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+                      scope 46 {
+                          debug c => _67;  // in scope 46 at $DIR/reference_prop.rs:+88:13: +88:14
+                      }
+                  }
               }
           }
       }
@@ -163,8 +211,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
           _4 = const 5_usize;              // scope 1 at $DIR/reference_prop.rs:+3:21: +3:28
-          StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &raw mut _4;                // scope 2 at $DIR/reference_prop.rs:+4:17: +4:27
+-         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &raw mut _4;                // scope 2 at $DIR/reference_prop.rs:+4:17: +4:27
           StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -173,7 +221,7 @@
           _8 = ();                         // scope 4 at $DIR/reference_prop.rs:+6:16: +6:18
           _7 = opaque::<()>(move _8) -> bb1; // scope 4 at $DIR/reference_prop.rs:+6:9: +6:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:250:9: 250:15
+                                           // + span: $DIR/reference_prop.rs:304:9: 304:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -182,7 +230,7 @@
           StorageDead(_7);                 // scope 4 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 1 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -203,7 +251,7 @@
           _16 = ();                        // scope 9 at $DIR/reference_prop.rs:+17:16: +17:18
           _15 = opaque::<()>(move _16) -> bb2; // scope 9 at $DIR/reference_prop.rs:+17:9: +17:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:261:9: 261:15
+                                           // + span: $DIR/reference_prop.rs:315:9: 315:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -225,18 +273,18 @@
           _20 = &_19;                      // scope 12 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_21);                // scope 13 at $DIR/reference_prop.rs:+25:13: +25:14
           _21 = (*_19);                    // scope 13 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = ();                        // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _22 = opaque::<()>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = _20;                       // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _22 = opaque::<&*mut usize>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:270:9: 270:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:324:9: 324:15
+                                           // + literal: Const { ty: fn(&*mut usize) {opaque::<&*mut usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _17 = const ();                  // scope 10 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_21);                // scope 13 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_20);                // scope 12 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -249,21 +297,21 @@
           StorageLive(_26);                // scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
           _26 = &raw mut _25;              // scope 16 at $DIR/reference_prop.rs:+32:21: +32:31
           StorageLive(_27);                // scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
-          _27 = &mut _26;                  // scope 17 at $DIR/reference_prop.rs:+33:17: +33:23
+          _27 = &raw mut _26;              // scope 17 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_28);                // scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
           _28 = (*_26);                    // scope 18 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = ();                        // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _29 = opaque::<()>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = _27;                       // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _29 = opaque::<*mut *mut usize>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:279:9: 279:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:333:9: 333:15
+                                           // + literal: Const { ty: fn(*mut *mut usize) {opaque::<*mut *mut usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _24 = const ();                  // scope 15 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_28);                // scope 18 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_27);                // scope 17 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -282,7 +330,7 @@
           _36 = _33;                       // scope 23 at $DIR/reference_prop.rs:+43:16: +43:17
           _35 = opaque::<*mut usize>(move _36) -> bb5; // scope 23 at $DIR/reference_prop.rs:+43:9: +43:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:287:9: 287:15
+                                           // + span: $DIR/reference_prop.rs:341:9: 341:15
                                            // + literal: Const { ty: fn(*mut usize) {opaque::<*mut usize>}, val: Value(<ZST>) }
       }
   
@@ -312,7 +360,7 @@
           _45 = _43;                       // scope 30 at $DIR/reference_prop.rs:+56:16: +56:18
           _44 = opaque::<*mut usize>(move _45) -> bb6; // scope 30 at $DIR/reference_prop.rs:+56:9: +56:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:300:9: 300:15
+                                           // + span: $DIR/reference_prop.rs:354:9: 354:15
                                            // + literal: Const { ty: fn(*mut usize) {opaque::<*mut usize>}, val: Value(<ZST>) }
       }
   
@@ -328,8 +376,8 @@
           StorageDead(_38);                // scope 24 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_37);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_46);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
-          _47 = &raw mut (*_1);            // scope 31 at $DIR/reference_prop.rs:+61:17: +61:33
+-         StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _47 = &raw mut (*_1);            // scope 31 at $DIR/reference_prop.rs:+61:17: +61:33
           StorageLive(_48);                // scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _48 = (*_47);                    // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _48 = (*_1);                     // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -338,7 +386,7 @@
           _50 = ();                        // scope 33 at $DIR/reference_prop.rs:+63:16: +63:18
           _49 = opaque::<()>(move _50) -> bb7; // scope 33 at $DIR/reference_prop.rs:+63:9: +63:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:307:9: 307:15
+                                           // + span: $DIR/reference_prop.rs:361:9: 361:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -347,32 +395,88 @@
           StorageDead(_49);                // scope 33 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _46 = const ();                  // scope 31 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_48);                // scope 32 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_46);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageLive(_51);                // scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
-          _51 = &raw mut (*_2);            // scope 34 at $DIR/reference_prop.rs:+68:17: +68:35
-          StorageLive(_52);                // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
-          _52 = &raw mut (*_1);            // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
-          _2 = move _52;                   // scope 35 at $DIR/reference_prop.rs:+69:9: +69:36
-          StorageDead(_52);                // scope 35 at $DIR/reference_prop.rs:+69:35: +69:36
-          StorageLive(_53);                // scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
-          _53 = (*_51);                    // scope 35 at $DIR/reference_prop.rs:+70:17: +70:19
-          StorageLive(_54);                // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
-          StorageLive(_55);                // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
-          _55 = ();                        // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
-          _54 = opaque::<()>(move _55) -> bb8; // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
+-         StorageLive(_51);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageLive(_52);                // scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
+          _52 = &raw mut (*_2);            // scope 34 at $DIR/reference_prop.rs:+68:17: +68:35
+          StorageLive(_53);                // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
+          _53 = &raw mut (*_1);            // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
+          _2 = move _53;                   // scope 35 at $DIR/reference_prop.rs:+69:9: +69:36
+          StorageDead(_53);                // scope 35 at $DIR/reference_prop.rs:+69:35: +69:36
+          StorageLive(_54);                // scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
+          _54 = (*_52);                    // scope 35 at $DIR/reference_prop.rs:+70:17: +70:19
+          StorageLive(_55);                // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
+          StorageLive(_56);                // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
+          _56 = ();                        // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
+          _55 = opaque::<()>(move _56) -> bb8; // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:315:9: 315:15
+                                           // + span: $DIR/reference_prop.rs:369:9: 369:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb8: {
-          StorageDead(_55);                // scope 36 at $DIR/reference_prop.rs:+71:18: +71:19
-          StorageDead(_54);                // scope 36 at $DIR/reference_prop.rs:+71:19: +71:20
-          _0 = const ();                   // scope 34 at $DIR/reference_prop.rs:+67:5: +72:6
-          StorageDead(_53);                // scope 35 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageDead(_51);                // scope 34 at $DIR/reference_prop.rs:+72:5: +72:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+73:2: +73:2
+          StorageDead(_56);                // scope 36 at $DIR/reference_prop.rs:+71:18: +71:19
+          StorageDead(_55);                // scope 36 at $DIR/reference_prop.rs:+71:19: +71:20
+-         _51 = const ();                  // scope 34 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageDead(_54);                // scope 35 at $DIR/reference_prop.rs:+72:5: +72:6
+          StorageDead(_52);                // scope 34 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageDead(_51);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageLive(_57);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_58);                // scope 37 at $DIR/reference_prop.rs:+76:13: +76:18
+          _58 = const 5_usize;             // scope 37 at $DIR/reference_prop.rs:+76:21: +76:28
+-         StorageLive(_59);                // scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _59 = &raw mut _58;              // scope 38 at $DIR/reference_prop.rs:+77:17: +77:27
+-         StorageLive(_60);                // scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _60 = &_59;                      // scope 39 at $DIR/reference_prop.rs:+78:17: +78:19
+          StorageLive(_61);                // scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _61 = (*_59);                    // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
++         _61 = _58;                       // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_62);                // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_63);                // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _63 = ();                        // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _62 = opaque::<()>(move _63) -> bb9; // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:378:9: 378:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb9: {
+          StorageDead(_63);                // scope 41 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_62);                // scope 41 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _57 = const ();                  // scope 37 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_61);                // scope 40 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_60);                // scope 39 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 38 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_58);                // scope 37 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_57);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageLive(_64);                // scope 42 at $DIR/reference_prop.rs:+85:13: +85:18
+          _64 = const 5_usize;             // scope 42 at $DIR/reference_prop.rs:+85:21: +85:28
+-         StorageLive(_65);                // scope 43 at $DIR/reference_prop.rs:+86:13: +86:18
+-         _65 = &raw mut _64;              // scope 43 at $DIR/reference_prop.rs:+86:21: +86:31
+-         StorageLive(_66);                // scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _66 = &mut _65;                  // scope 44 at $DIR/reference_prop.rs:+87:17: +87:23
+          StorageLive(_67);                // scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _67 = (*_65);                    // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
++         _67 = _64;                       // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_68);                // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_69);                // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _69 = ();                        // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _68 = opaque::<()>(move _69) -> bb10; // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:387:9: 387:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_69);                // scope 46 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_68);                // scope 46 at $DIR/reference_prop.rs:+89:19: +89:20
+          _0 = const ();                   // scope 42 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_67);                // scope 45 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_66);                // scope 44 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_65);                // scope 43 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_64);                // scope 42 at $DIR/reference_prop.rs:+90:5: +90:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+91:2: +91:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
index 93f8d1d..4083b45 100644
--- a/tests/mir-opt/reference_prop.rs
+++ b/tests/mir-opt/reference_prop.rs
@@ -33,16 +33,16 @@
         let b = &a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but do not propagate it
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     {
         let a = 5_usize;
         let mut b = &a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -80,6 +80,24 @@
         let b = *a; // This should not be optimized.
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let a = 5_usize;
+        let b = &a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let a = 5_usize;
+        let mut b = &a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a mut T) {
@@ -108,16 +126,16 @@
         let b = &mut a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     {
         let mut a = 5_usize;
         let mut b = &mut a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -155,6 +173,24 @@
         let b = *a; // This should not be optimized.
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let mut a = 5_usize;
+        let b = &mut a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let mut a = 5_usize;
+        let mut b = &mut a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *const T) {
@@ -183,16 +219,16 @@
         let b = &raw const a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     unsafe {
         let a = 5_usize;
         let mut b = &raw const a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -239,6 +275,24 @@
         let e = *c;
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let a = 5_usize;
+        let b = &raw const a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let a = 5_usize;
+        let mut b = &raw const a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 fn reference_propagation_mut_ptr<T: Copy>(single: *mut T, mut multiple: *mut T) {
@@ -267,16 +321,16 @@
         let b = &raw mut a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     unsafe {
         let mut a = 5_usize;
         let mut b = &raw mut a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -314,6 +368,24 @@
         let b = *a; // This should not be optimized.
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let mut a = 5_usize;
+        let b = &raw mut a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let mut a = 5_usize;
+        let mut b = &raw mut a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
@@ -456,6 +528,40 @@
     unsafe { opaque(*y) };
 }
 
+fn debuginfo() {
+    struct T(u8);
+
+    let ref_mut_u8 = &mut 5_u8;
+    let field = &T(0).0;
+
+    // Verify that we don't emit `&*` in debuginfo.
+    let reborrow = &*ref_mut_u8;
+
+    match Some(0) {
+        None => {}
+        Some(ref variant_field) => {}
+    }
+
+    // `constant_index_from_end` and `subslice` should not be promoted, as their value depends
+    // on the slice length.
+    if let [_, ref constant_index, subslice @ .., ref constant_index_from_end] = &[6; 10][..] {
+    }
+
+    let multiple_borrow = &&&mut T(6).0;
+}
+
+fn many_debuginfo() {
+    let a = 0;
+
+    // Verify that we do not ICE on deeply nested borrows.
+    let many_borrow =
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&a;
+}
+
 fn main() {
     let mut x = 5_usize;
     let mut y = 7_usize;
@@ -469,6 +575,8 @@
     maybe_dead(true);
     mut_raw_then_mut_shr();
     unique_with_copies();
+    debuginfo();
+    many_debuginfo();
 }
 
 // EMIT_MIR reference_prop.reference_propagation.ReferencePropagation.diff
@@ -481,3 +589,4 @@
 // 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
+// EMIT_MIR reference_prop.debuginfo.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
index 2cda240..b754aff 100644
--- a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff
@@ -10,7 +10,8 @@
       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
+-         debug y => _1;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:10
++         debug y => _3;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:10
           scope 5 {
           }
       }
@@ -25,7 +26,7 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+1:9: +1:10
+-         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
@@ -35,14 +36,14 @@
           _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
+                                           // + span: $DIR/reference_prop.rs:524:18: 524: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
+-         _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
@@ -51,7 +52,7 @@
 +         _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
+                                           // + span: $DIR/reference_prop.rs:528:14: 528:20
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
@@ -59,7 +60,7 @@
           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
+-         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/mir-opt/slice_filter.variant_a-\173closure\0430\175.DestinationPropagation.diff" "b/tests/mir-opt/slice_filter.variant_a-\173closure\0430\175.DestinationPropagation.diff"
index 7ad1ccf..afdcf57 100644
--- "a/tests/mir-opt/slice_filter.variant_a-\173closure\0430\175.DestinationPropagation.diff"
+++ "b/tests/mir-opt/slice_filter.variant_a-\173closure\0430\175.DestinationPropagation.diff"
@@ -3,136 +3,79 @@
   
   fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
       let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
-      let _3: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-      let _4: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-      let _5: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-      let _6: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
-      let mut _9: &&usize;                 // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
-      let mut _10: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let _11: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let mut _12: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
-      let mut _13: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
-      let mut _14: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let _15: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let mut _16: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
-      let mut _17: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
-      let mut _18: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
-      let mut _19: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let _20: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let mut _21: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
-      let mut _22: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
-      let mut _23: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let _24: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let mut _25: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _26: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _3: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
+      let mut _4: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
+      let mut _5: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
+      let mut _6: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
+      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
+      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
+      let mut _9: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _10: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _11: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _12: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
       scope 1 {
--         debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
--         debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
--         debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
--         debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
-+         debug a => _20;                  // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-+         debug b => _15;                  // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-+         debug c => _11;                  // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-+         debug d => _24;                  // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+          debug a => &((*_9).0: usize);    // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+          debug b => &((*_10).1: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+          debug c => &((*_11).2: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+          debug d => &((*_12).3: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
           scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
-              debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _29: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _30: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_9).0: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_11).2: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _31: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _32: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_9).0: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_11).2: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _13: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _14: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
-              debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _33: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _34: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_11).2: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_9).0: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _33;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _34;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _35: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _36: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_11).2: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_9).0: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _15: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _16: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
-              debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _37: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _38: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_12).3: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_10).1: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _37;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _38;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _39: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _40: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_12).3: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_10).1: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _17: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _18: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
-              debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _41: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _42: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_10).1: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_12).3: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _41;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _42;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _43: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _44: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_10).1: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_12).3: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _19: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _20: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
       }
   
       bb0: {
--         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
--         _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
--         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-+         _20 = &((*_25).0: usize);        // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
--         _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
--         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-+         _15 = &((*_26).1: usize);        // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
--         _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
--         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-+         _11 = &((*_27).2: usize);        // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
--         _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
--         StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-+         _24 = &((*_28).3: usize);        // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+          _9 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+          _10 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+          _11 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+          _12 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         StorageLive(_3);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
-          StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         _29 = deref_copy _3;             // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-+         _29 = deref_copy _20;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _30 = deref_copy _11;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_31);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _31 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_32);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _32 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _8 = Le(move _31, move _32);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_32);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_31);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+          StorageLive(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
+          StorageLive(_13);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _13 = ((*_9).0: usize);          // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_14);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _14 = ((*_11).2: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _4 = Le(move _13, move _14);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          switchInt(move _4) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
       }
   
       bb1: {
@@ -141,127 +84,80 @@
       }
   
       bb2: {
--         StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+-         StorageLive(_6);                 // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
-          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         _33 = deref_copy _5;             // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-+         _33 = deref_copy _11;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _34 = deref_copy _20;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_35);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _35 = (*_33);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_36);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _36 = (*_34);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _17 = Le(move _35, move _36);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_36);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_35);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
+          StorageLive(_15);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _15 = ((*_11).2: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _16 = ((*_9).0: usize);          // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _7 = Le(move _15, move _16);     // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_16);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_15);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          switchInt(move _7) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb3: {
--         StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_6);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_3);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
           return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
       }
   
       bb4: {
--         StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageDead(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
       }
   
       bb5: {
--         StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
+-         StorageLive(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
-          StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _37 = deref_copy _6;             // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         _37 = deref_copy _24;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _38 = deref_copy _15;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_39);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _39 = (*_37);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_40);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _40 = (*_38);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _12 = Le(move _39, move _40);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_40);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_39);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
--         StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageLive(_17);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _17 = ((*_12).3: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _18 = ((*_10).1: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _5 = Le(move _17, move _18);     // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_17);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _3 = move _5;                    // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+-         StorageDead(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-+         switchInt(move _12) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+          StorageDead(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
++         switchInt(move _5) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
       }
   
       bb6: {
--         _16 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+-         _6 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
 +         _0 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb7: {
--         StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
+-         StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
-          StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _41 = deref_copy _4;             // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         _41 = deref_copy _15;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _42 = deref_copy _24;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _43 = (*_41);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_44);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _44 = (*_42);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _21 = Le(move _43, move _44);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _0 = Le(move _43, move _44);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_44);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+          StorageLive(_19);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _19 = ((*_10).1: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_20);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _20 = ((*_12).3: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _8 = Le(move _19, move _20);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _0 = Le(move _19, move _20);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_20);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_19);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _6 = move _8;                    // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb8: {
--         StorageDead(_21);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_17);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _0 = move _16;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _0 = move _6;                    // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
           goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
       }
diff --git "a/tests/mir-opt/slice_filter.variant_a-\173closure\0430\175.ReferencePropagation.diff" "b/tests/mir-opt/slice_filter.variant_a-\173closure\0430\175.ReferencePropagation.diff"
index f6350b3..2534eee 100644
--- "a/tests/mir-opt/slice_filter.variant_a-\173closure\0430\175.ReferencePropagation.diff"
+++ "b/tests/mir-opt/slice_filter.variant_a-\173closure\0430\175.ReferencePropagation.diff"
@@ -38,54 +38,74 @@
       let mut _49: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
       let mut _50: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
       scope 1 {
-          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+-         debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+-         debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+-         debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+-         debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
++         debug a => &((*_25).0: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
++         debug b => &((*_26).1: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
++         debug c => &((*_27).2: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
++         debug d => &((*_28).3: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
           scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
-              debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_25).0: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_27).2: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _29: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _30: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_25).0: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_27).2: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _33: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _34: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
-              debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_27).2: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_25).0: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _35: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _36: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _35;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _36;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _35;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _36;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_27).2: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_25).0: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _39: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _40: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
-              debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_28).3: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_26).1: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _41: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _42: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _41;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _42;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _41;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _42;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_28).3: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_26).1: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _45: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _46: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
-              debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_26).1: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_28).3: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _47: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _48: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _47;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _48;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _47;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _48;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_26).1: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_28).3: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _51: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _52: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
@@ -93,40 +113,40 @@
       }
   
       bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+-         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
           _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+-         _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+-         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
           _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+-         _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+-         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
           _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+-         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
           StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
-          StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+-         _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+-         StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
 -         _29 = deref_copy (*_9);          // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _30 = deref_copy (*_10);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _29 = deref_copy _3;             // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _30 = deref_copy _11;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _33 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _33 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _33 = ((*_25).0: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _34 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _34 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _34 = ((*_27).2: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _8 = Le(move _33, move _34);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
           switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
       }
   
@@ -138,36 +158,36 @@
       bb2: {
           StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
-          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+-         _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+-         StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
 -         _35 = deref_copy (*_18);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _36 = deref_copy (*_19);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _35 = deref_copy _5;             // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _36 = deref_copy _20;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _39 = (*_35);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _39 = (*_35);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _39 = ((*_27).2: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _40 = (*_36);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _40 = (*_36);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _40 = ((*_25).0: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _17 = Le(move _39, move _40);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
           switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb3: {
           StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
           StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
           return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
       }
   
@@ -180,26 +200,26 @@
   
       bb5: {
           StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
-          StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+-         _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+-         StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
 -         _41 = deref_copy (*_13);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _42 = deref_copy (*_14);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _41 = deref_copy _6;             // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _42 = deref_copy _15;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _45 = (*_41);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _45 = (*_41);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _45 = ((*_28).3: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _46 = (*_42);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _46 = (*_42);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _46 = ((*_26).1: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _12 = Le(move _45, move _46);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
           StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
@@ -213,26 +233,26 @@
   
       bb7: {
           StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
-          StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+-         _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+-         StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 -         _47 = deref_copy (*_22);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _48 = deref_copy (*_23);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _47 = deref_copy _4;             // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _48 = deref_copy _24;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _51 = (*_47);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _51 = (*_47);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _51 = ((*_26).1: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _52 = (*_48);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _52 = (*_48);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _52 = ((*_28).3: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _21 = Le(move _51, move _52);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
           _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
diff --git a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
index 2af8649..4b2a16b 100644
--- a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
+++ b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
@@ -3,16 +3,13 @@
 fn process_void(_1: *const Void) -> () {
     debug input => _1;                   // in scope 0 at $DIR/uninhabited_enum.rs:+0:21: +0:26
     let mut _0: ();                      // return place in scope 0 at $DIR/uninhabited_enum.rs:+0:41: +0:41
-    let _2: &Void;                       // in scope 0 at $DIR/uninhabited_enum.rs:+1:8: +1:14
     scope 1 {
-        debug _input => _2;              // in scope 1 at $DIR/uninhabited_enum.rs:+1:8: +1:14
+        debug _input => _1;              // in scope 1 at $DIR/uninhabited_enum.rs:+1:8: +1:14
     }
     scope 2 {
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/uninhabited_enum.rs:+1:8: +1:14
-        StorageDead(_2);                 // scope 0 at $DIR/uninhabited_enum.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/uninhabited_enum.rs:+4:2: +4:2
     }
 }
diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
index 7bd7bb7..b59a65a 100644
--- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
@@ -18,14 +18,14 @@
 extern crate rustc_middle;
 extern crate rustc_session;
 
-use rustc_borrowck::consumers::BodyWithBorrowckFacts;
+use rustc_borrowck::consumers::{self, BodyWithBorrowckFacts, ConsumerOptions};
 use rustc_driver::Compilation;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_interface::interface::Compiler;
 use rustc_interface::{Config, Queries};
-use rustc_middle::ty::query::query_values::mir_borrowck;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::queries::mir_borrowck::ProvidedValue;
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use std::cell::RefCell;
@@ -102,7 +102,7 @@
             println!("Bodies retrieved for:");
             for (def_id, body) in bodies {
                 println!("{}", def_id);
-                assert!(body.input_facts.cfg_edge.len() > 0);
+                assert!(body.input_facts.unwrap().cfg_edge.len() > 0);
             }
         });
 
@@ -126,8 +126,9 @@
         RefCell::new(HashMap::new());
 }
 
-fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> {
-    let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id);
+fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'tcx> {
+    let opts = ConsumerOptions::PoloniusInputFacts;
+    let body_with_facts = consumers::get_body_with_borrowck_facts(tcx, def_id, opts);
     // SAFETY: The reader casts the 'static lifetime to 'tcx before using it.
     let body_with_facts: BodyWithBorrowckFacts<'static> =
         unsafe { std::mem::transmute(body_with_facts) };
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/Makefile b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile
new file mode 100644
index 0000000..7940dae
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile
@@ -0,0 +1,6 @@
+include ../tools.mk
+
+all:
+	$(RUSTC) --emit=metadata --crate-type lib stable.rs
+	$(RUSTC) --emit=metadata --extern stable=$(TMPDIR)/libstable.rmeta main.rs 2>&1 >/dev/null \
+		| $(CGREP) -e "stable since $$(cat $(S)/src/version)(-[a-zA-Z]+)?"
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/main.rs b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs
new file mode 100644
index 0000000..466aaa8
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs
@@ -0,0 +1,4 @@
+#![feature(foo)]
+extern crate stable;
+
+fn main() {}
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs
new file mode 100644
index 0000000..2fd09ad
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs
@@ -0,0 +1,5 @@
+#![feature(staged_api)]
+#![stable(since = "1.0.0", feature = "rust1")]
+
+#[stable(since = "CURRENT_RUSTC_VERSION", feature = "foo")]
+pub fn foo() {}
diff --git a/tests/run-make/debugger-visualizer-dep-info/Makefile b/tests/run-make/debugger-visualizer-dep-info/Makefile
new file mode 100644
index 0000000..0877998
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+# This test makes sure that files referenced via #[debugger_visualizer] are
+# included in `--emit dep-info` output.
+
+all:
+	$(RUSTC) --emit dep-info main.rs
+	$(CGREP) "foo.py" < $(TMPDIR)/main.d
+	$(CGREP) "my_visualizers/bar.natvis" < $(TMPDIR)/main.d
diff --git a/tests/run-make/debugger-visualizer-dep-info/foo.py b/tests/run-make/debugger-visualizer-dep-info/foo.py
new file mode 100644
index 0000000..1bb8bf6
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/foo.py
@@ -0,0 +1 @@
+# empty
diff --git a/tests/run-make/debugger-visualizer-dep-info/main.rs b/tests/run-make/debugger-visualizer-dep-info/main.rs
new file mode 100644
index 0000000..3aede22
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/main.rs
@@ -0,0 +1,12 @@
+#![debugger_visualizer(gdb_script_file = "foo.py")]
+
+fn main() {
+    const _UNUSED: u32 = {
+        mod inner {
+            #![debugger_visualizer(natvis_file = "my_visualizers/bar.natvis")]
+            pub const XYZ: u32 = 123;
+        }
+
+        inner::XYZ + 1
+    };
+}
diff --git a/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis
new file mode 100644
index 0000000..c341a40
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis
@@ -0,0 +1 @@
+<!-- empty -->
diff --git a/tests/run-make/incremental-debugger-visualizer/Makefile b/tests/run-make/incremental-debugger-visualizer/Makefile
new file mode 100644
index 0000000..8cfe415
--- /dev/null
+++ b/tests/run-make/incremental-debugger-visualizer/Makefile
@@ -0,0 +1,49 @@
+include ../tools.mk
+
+# This test makes sure that changes to files referenced via #[debugger_visualizer]
+# are picked up when compiling incrementally.
+
+# We have to copy the source to $(TMPDIR) because Github CI mounts the source
+# directory as readonly. We need to apply modifications to some of the source
+# file.
+SRC_DIR := $(TMPDIR)/src
+INCR_CACHE_DIR := $(TMPDIR)/incremental
+
+all:
+	rm -rf $(TMPDIR)/*
+	mkdir $(SRC_DIR)
+	cp ./foo.rs $(SRC_DIR)
+	echo "GDB script v1" > $(SRC_DIR)/foo.py
+	echo "Natvis v1" > $(SRC_DIR)/foo.natvis
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+	$(CGREP) "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta
+
+	# Change only the GDB script and check that the change has been picked up
+	echo "GDB script v2" > $(SRC_DIR)/foo.py
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+
+	$(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta
+
+	# Now change the Natvis version and check that the change has been picked up
+	echo "Natvis v2" > $(SRC_DIR)/foo.natvis
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+
+	$(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "Natvis v1" < $(TMPDIR)/libfoo.rmeta
diff --git a/tests/run-make/incremental-debugger-visualizer/foo.rs b/tests/run-make/incremental-debugger-visualizer/foo.rs
new file mode 100644
index 0000000..8daa36a
--- /dev/null
+++ b/tests/run-make/incremental-debugger-visualizer/foo.rs
@@ -0,0 +1,6 @@
+#![debugger_visualizer(natvis_file = "./foo.natvis")]
+#![debugger_visualizer(gdb_script_file = "./foo.py")]
+
+pub struct Foo {
+    pub x: u32,
+}
diff --git a/tests/run-make/issue-83045/Makefile b/tests/run-make/issue-83045/Makefile
index 7053da0..b76e184 100644
--- a/tests/run-make/issue-83045/Makefile
+++ b/tests/run-make/issue-83045/Makefile
@@ -29,5 +29,5 @@
 				  --crate-type=rlib \
 				  --edition=2018 \
 				  c.rs 2>&1 | tee $(TMPDIR)/output.txt || exit 0
-	$(CGREP) E0519 < $(TMPDIR)/output.txt
+	$(CGREP) E0463 < $(TMPDIR)/output.txt
 	$(CGREP) -v "internal compiler error" < $(TMPDIR)/output.txt
diff --git a/tests/run-make/no-alloc-shim/Makefile b/tests/run-make/no-alloc-shim/Makefile
new file mode 100644
index 0000000..568e3f9
--- /dev/null
+++ b/tests/run-make/no-alloc-shim/Makefile
@@ -0,0 +1,24 @@
+include ../tools.mk
+
+# ignore-cross-compile
+# ignore-msvc FIXME(bjorn3) can't figure out how to link with the MSVC toolchain
+
+TARGET_LIBDIR = $$($(RUSTC) --print target-libdir)
+
+all:
+	$(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort
+ifdef IS_MSVC
+	$(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib
+	$(call OUT_EXE,foo)
+else
+	$(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo)
+	$(call RUN_BINFILE,foo)
+endif
+
+	# Check that linking without __rust_no_alloc_shim_is_unstable defined fails
+	$(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort --cfg check_feature_gate
+ifdef IS_MSVC
+	$(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib || exit 0 && exit 1
+else
+	$(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) || exit 0 && exit 1
+endif
diff --git a/tests/run-make/no-alloc-shim/foo.rs b/tests/run-make/no-alloc-shim/foo.rs
new file mode 100644
index 0000000..a3daec3
--- /dev/null
+++ b/tests/run-make/no-alloc-shim/foo.rs
@@ -0,0 +1,44 @@
+#![feature(default_alloc_error_handler)]
+#![no_std]
+#![no_main]
+
+extern crate alloc;
+
+use alloc::alloc::{GlobalAlloc, Layout};
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[no_mangle]
+extern "C" fn rust_eh_personality() {
+    loop {}
+}
+
+#[global_allocator]
+static ALLOC: Alloc = Alloc;
+
+struct Alloc;
+
+unsafe impl GlobalAlloc for Alloc {
+    unsafe fn alloc(&self, _: Layout) -> *mut u8 {
+        core::ptr::null_mut()
+    }
+    unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
+        todo!()
+    }
+}
+
+#[cfg(not(check_feature_gate))]
+#[no_mangle]
+static __rust_no_alloc_shim_is_unstable: u8 = 0;
+
+#[no_mangle]
+extern "C" fn main(_argc: usize, _argv: *const *const i8) -> i32 {
+    unsafe {
+        assert_eq!(alloc::alloc::alloc(Layout::new::<()>()), core::ptr::null_mut());
+    }
+
+    0
+}
diff --git a/tests/run-make/print-native-static-libs/Makefile b/tests/run-make/print-native-static-libs/Makefile
new file mode 100644
index 0000000..98e72d7
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/Makefile
@@ -0,0 +1,15 @@
+include ../tools.mk
+
+# ignore-cross-compile
+# ignore-wasm
+
+all:
+	$(RUSTC) --crate-type rlib -lbar_cli bar.rs
+	$(RUSTC) foo.rs -lfoo_cli --crate-type staticlib --print native-static-libs 2>&1 \
+		| grep 'note: native-static-libs: ' \
+		| sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt
+
+	cat $(TMPDIR)/libs.txt | grep -F "glib-2.0" # in bar.rs
+	cat $(TMPDIR)/libs.txt | grep -F "systemd" # in foo.rs
+	cat $(TMPDIR)/libs.txt | grep -F "bar_cli"
+	cat $(TMPDIR)/libs.txt | grep -F "foo_cli"
diff --git a/tests/run-make/print-native-static-libs/bar.rs b/tests/run-make/print-native-static-libs/bar.rs
new file mode 100644
index 0000000..a563bbc
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/bar.rs
@@ -0,0 +1,13 @@
+#[no_mangle]
+pub extern "C" fn my_bar_add(left: i32, right: i32) -> i32 {
+    // Obviously makes no sense but...
+    unsafe {
+        g_free(std::ptr::null_mut());
+    }
+    left + right
+}
+
+#[link(name = "glib-2.0")]
+extern "C" {
+    fn g_free(p: *mut ());
+}
diff --git a/tests/run-make/print-native-static-libs/foo.rs b/tests/run-make/print-native-static-libs/foo.rs
new file mode 100644
index 0000000..6acaee2
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/foo.rs
@@ -0,0 +1,15 @@
+extern crate bar;
+
+#[no_mangle]
+pub extern "C" fn my_foo_add(left: i32, right: i32) -> i32 {
+    // Obviously makes no sense but...
+    unsafe {
+        init(std::ptr::null_mut());
+    }
+    bar::my_bar_add(left, right)
+}
+
+#[link(name = "systemd")]
+extern "C" {
+    fn init(p: *mut ());
+}
diff --git a/tests/run-make/short-ice/Makefile b/tests/run-make/short-ice/Makefile
new file mode 100644
index 0000000..4f33d59
--- /dev/null
+++ b/tests/run-make/short-ice/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+# ignore-windows
+
+export RUSTC := $(RUSTC_ORIGINAL)
+export TMPDIR := $(TMPDIR)
+
+all:
+	bash check.sh
diff --git a/tests/run-make/short-ice/check.sh b/tests/run-make/short-ice/check.sh
new file mode 100644
index 0000000..96cd8fe
--- /dev/null
+++ b/tests/run-make/short-ice/check.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
+RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
+
+short=$(cat $TMPDIR/rust-test-1.log | wc -l)
+full=$(cat $TMPDIR/rust-test-2.log | wc -l)
+rustc_query_count=$(cat $TMPDIR/rust-test-1.log | grep rustc_query_ | wc -l)
+rustc_query_count_full=$(cat $TMPDIR/rust-test-2.log | grep rustc_query_ | wc -l)
+
+begin_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_begin_short_backtrace | wc -l)
+end_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_end_short_backtrace | wc -l)
+
+cat $TMPDIR/rust-test-1.log
+echo "====================="
+cat $TMPDIR/rust-test-2.log
+echo "====================="
+
+echo "short backtrace: $short"
+echo "full  backtrace: $full"
+echo "begin_count: $begin_count"
+echo "end_count  : $end_count"
+echo "rustc_query_count: $rustc_query_count"
+echo "rustc_query_count_full: $rustc_query_count_full"
+
+## backtraces to vary a bit depending on platform and configuration options,
+## here we make sure that the short backtrace of rustc_query is shorter than the full,
+## and marks are in pairs.
+if [ $short -lt $full ] &&
+    [ $begin_count -eq $end_count ] &&
+    [ $(($rustc_query_count + 10)) -lt $rustc_query_count_full ] &&
+    [ $rustc_query_count_full -gt 10 ]; then
+    exit 0
+else
+    exit 1
+fi
diff --git a/tests/run-make/short-ice/src/lib.rs b/tests/run-make/short-ice/src/lib.rs
new file mode 100644
index 0000000..b23b7f8
--- /dev/null
+++ b/tests/run-make/short-ice/src/lib.rs
@@ -0,0 +1,7 @@
+fn func(s: &str) {
+    println!("{}", s);
+}
+
+fn main() {
+    func(1);
+}
diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml
index 0904aa9..e9b7729 100644
--- a/tests/rustdoc-gui/anchors.goml
+++ b/tests/rustdoc-gui/anchors.goml
@@ -75,35 +75,35 @@
     "check-colors",
     {
         "theme": "ayu",
-        "main_color": "rgb(197, 197, 197)",
-        "title_color": "rgb(255, 255, 255)",
-        "main_heading_color": "rgb(255, 255, 255)",
-        "main_heading_type_color": "rgb(255, 160, 165)",
-        "src_link_color": "rgb(57, 175, 215)",
-        "sidebar_link_color": "rgb(83, 177, 219)",
+        "main_color": "#c5c5c5",
+        "title_color": "#fff",
+        "main_heading_color": "#fff",
+        "main_heading_type_color": "#ffa0a5",
+        "src_link_color": "#39afd7",
+        "sidebar_link_color": "#53b1db",
     },
 )
 call-function: (
     "check-colors",
     {
         "theme": "dark",
-        "main_color": "rgb(221, 221, 221)",
-        "title_color": "rgb(221, 221, 221)",
-        "main_heading_color": "rgb(221, 221, 221)",
-        "main_heading_type_color": "rgb(45, 191, 184)",
-        "src_link_color": "rgb(210, 153, 29)",
-        "sidebar_link_color": "rgb(253, 191, 53)",
+        "main_color": "#ddd",
+        "title_color": "#ddd",
+        "main_heading_color": "#ddd",
+        "main_heading_type_color": "#2dbfb8",
+        "src_link_color": "#d2991d",
+        "sidebar_link_color": "#fdbf35",
     },
 )
 call-function: (
     "check-colors",
     {
         "theme": "light",
-        "main_color": "rgb(0, 0, 0)",
-        "title_color": "rgb(0, 0, 0)",
-        "main_heading_color": "rgb(0, 0, 0)",
-        "main_heading_type_color": "rgb(173, 55, 138)",
-        "src_link_color": "rgb(56, 115, 173)",
-        "sidebar_link_color": "rgb(53, 109, 164)",
+        "main_color": "black",
+        "title_color": "black",
+        "main_heading_color": "black",
+        "main_heading_type_color": "#ad378a",
+        "src_link_color": "#3873ad",
+        "sidebar_link_color": "#356da4",
     },
 )
diff --git a/tests/rustdoc-gui/codeblock-tooltip.goml b/tests/rustdoc-gui/codeblock-tooltip.goml
index 2ed0579..e1c81ed 100644
--- a/tests/rustdoc-gui/codeblock-tooltip.goml
+++ b/tests/rustdoc-gui/codeblock-tooltip.goml
@@ -109,19 +109,19 @@
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "background": "rgb(15, 20, 25)",
-    "color": "rgb(197, 197, 197)",
-    "border": "rgb(92, 103, 115)",
+    "background": "#0f1419",
+    "color": "#c5c5c5",
+    "border": "#5c6773",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "background": "rgb(53, 53, 53)",
-    "color": "rgb(221, 221, 221)",
-    "border": "rgb(224, 224, 224)",
+    "background": "#353535",
+    "color": "#ddd",
+    "border": "#e0e0e0",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "background": "rgb(255, 255, 255)",
-    "color": "rgb(0, 0, 0)",
-    "border": "rgb(224, 224, 224)",
+    "background": "white",
+    "color": "black",
+    "border": "#e0e0e0",
 })
diff --git a/tests/rustdoc-gui/highlight-colors.goml b/tests/rustdoc-gui/highlight-colors.goml
index 4f5e1c1..d162674 100644
--- a/tests/rustdoc-gui/highlight-colors.goml
+++ b/tests/rustdoc-gui/highlight-colors.goml
@@ -43,52 +43,52 @@
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "kw": "rgb(255, 119, 51)",
-    "kw2": "rgb(255, 119, 51)",
-    "prelude_ty": "rgb(105, 242, 223)",
-    "prelude_val": "rgb(255, 119, 51)",
-    "lifetime": "rgb(255, 119, 51)",
-    "number": "rgb(184, 204, 82)",
-    "string": "rgb(184, 204, 82)",
-    "bool_val": "rgb(255, 119, 51)",
-    "self": "rgb(54, 163, 217)",
-    "attr": "rgb(230, 225, 207)",
-    "macro": "rgb(163, 122, 204)",
-    "question_mark": "rgb(255, 144, 17)",
-    "comment": "rgb(120, 135, 151)",
-    "doc_comment": "rgb(161, 172, 136)",
+    "kw": "#ff7733",
+    "kw2": "#ff7733",
+    "prelude_ty": "#69f2df",
+    "prelude_val": "#ff7733",
+    "lifetime": "#ff7733",
+    "number": "#b8cc52",
+    "string": "#b8cc52",
+    "bool_val": "#ff7733",
+    "self": "#36a3d9",
+    "attr": "#e6e1cf",
+    "macro": "#a37acc",
+    "question_mark": "#ff9011",
+    "comment": "#788797",
+    "doc_comment": "#a1ac88",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "kw": "rgb(171, 138, 193)",
-    "kw2": "rgb(118, 154, 203)",
-    "prelude_ty": "rgb(118, 154, 203)",
-    "prelude_val": "rgb(238, 104, 104)",
-    "lifetime": "rgb(217, 127, 38)",
-    "number": "rgb(131, 163, 0)",
-    "string": "rgb(131, 163, 0)",
-    "bool_val": "rgb(238, 104, 104)",
-    "self": "rgb(238, 104, 104)",
-    "attr": "rgb(238, 104, 104)",
-    "macro": "rgb(62, 153, 159)",
-    "question_mark": "rgb(255, 144, 17)",
-    "comment": "rgb(141, 141, 139)",
-    "doc_comment": "rgb(140, 163, 117)",
+    "kw": "#ab8ac1",
+    "kw2": "#769acb",
+    "prelude_ty": "#769acb",
+    "prelude_val": "#ee6868",
+    "lifetime": "#d97f26",
+    "number": "#83a300",
+    "string": "#83a300",
+    "bool_val": "#ee6868",
+    "self": "#ee6868",
+    "attr": "#ee6868",
+    "macro": "#3e999f",
+    "question_mark": "#ff9011",
+    "comment": "#8d8d8b",
+    "doc_comment": "#8ca375",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "kw": "rgb(137, 89, 168)",
-    "kw2": "rgb(66, 113, 174)",
-    "prelude_ty": "rgb(66, 113, 174)",
-    "prelude_val": "rgb(200, 40, 41)",
-    "lifetime": "rgb(183, 101, 20)",
-    "number": "rgb(113, 140, 0)",
-    "string": "rgb(113, 140, 0)",
-    "bool_val": "rgb(200, 40, 41)",
-    "self": "rgb(200, 40, 41)",
-    "attr": "rgb(200, 40, 41)",
-    "macro": "rgb(62, 153, 159)",
-    "question_mark": "rgb(255, 144, 17)",
-    "comment": "rgb(142, 144, 140)",
-    "doc_comment": "rgb(77, 77, 76)",
+    "kw": "#8959a8",
+    "kw2": "#4271ae",
+    "prelude_ty": "#4271ae",
+    "prelude_val": "#c82829",
+    "lifetime": "#b76514",
+    "number": "#718c00",
+    "string": "#718c00",
+    "bool_val": "#c82829",
+    "self": "#c82829",
+    "attr": "#c82829",
+    "macro": "#3e999f",
+    "question_mark": "#ff9011",
+    "comment": "#8e908c",
+    "doc_comment": "#4d4d4c",
 })
diff --git a/tests/rustdoc-gui/jump-to-def-background.goml b/tests/rustdoc-gui/jump-to-def-background.goml
index 3a7d482..6adc36b 100644
--- a/tests/rustdoc-gui/jump-to-def-background.goml
+++ b/tests/rustdoc-gui/jump-to-def-background.goml
@@ -17,6 +17,6 @@
     },
 )
 
-call-function: ("check-background-color", ("ayu", "rgb(51, 51, 51)"))
-call-function: ("check-background-color", ("dark", "rgb(51, 51, 51)"))
-call-function: ("check-background-color", ("light", "rgb(238, 238, 238)"))
+call-function: ("check-background-color", ("ayu", "#333"))
+call-function: ("check-background-color", ("dark", "#333"))
+call-function: ("check-background-color", ("light", "#eee"))
diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml
index 8ddb06f..0052d18 100644
--- a/tests/rustdoc-gui/scrape-examples-color.goml
+++ b/tests/rustdoc-gui/scrape-examples-color.goml
@@ -33,30 +33,30 @@
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "highlight": "rgb(91, 59, 1)",
-    "highlight_focus": "rgb(124, 75, 15)",
-    "help_border": "rgb(170, 170, 170)",
-    "help_color": "rgb(238, 238, 238)",
-    "help_hover_border": "rgb(255, 255, 255)",
-    "help_hover_color": "rgb(255, 255, 255)",
+    "highlight": "#5b3b01",
+    "highlight_focus": "#7c4b0f",
+    "help_border": "#aaa",
+    "help_color": "#eee",
+    "help_hover_border": "#fff",
+    "help_hover_color": "#fff",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "highlight": "rgb(91, 59, 1)",
-    "highlight_focus": "rgb(124, 75, 15)",
-    "help_border": "rgb(170, 170, 170)",
-    "help_color": "rgb(238, 238, 238)",
-    "help_hover_border": "rgb(255, 255, 255)",
-    "help_hover_color": "rgb(255, 255, 255)",
+    "highlight": "#5b3b01",
+    "highlight_focus": "#7c4b0f",
+    "help_border": "#aaa",
+    "help_color": "#eee",
+    "help_hover_border": "#fff",
+    "help_hover_color": "#fff",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "highlight": "rgb(252, 255, 214)",
-    "highlight_focus": "rgb(246, 253, 176)",
-    "help_border": "rgb(85, 85, 85)",
-    "help_color": "rgb(51, 51, 51)",
-    "help_hover_border": "rgb(0, 0, 0)",
-    "help_hover_color": "rgb(0, 0, 0)",
+    "highlight": "#fcffd6",
+    "highlight_focus": "#f6fdb0",
+    "help_border": "#555",
+    "help_color": "#333",
+    "help_hover_border": "#000",
+    "help_hover_color": "#000",
 })
 
 // Now testing the top and bottom background in case there is only one scraped examples.
@@ -81,16 +81,16 @@
 
 call-function: ("check-background", {
     "theme": "ayu",
-    "background_color_start": "rgb(15, 20, 25)",
+    "background_color_start": "rgba(15, 20, 25, 1)",
     "background_color_end": "rgba(15, 20, 25, 0)",
 })
 call-function: ("check-background", {
     "theme": "dark",
-    "background_color_start": "rgb(53, 53, 53)",
+    "background_color_start": "rgba(53, 53, 53, 1)",
     "background_color_end": "rgba(53, 53, 53, 0)",
 })
 call-function: ("check-background", {
     "theme": "light",
-    "background_color_start": "rgb(255, 255, 255)",
+    "background_color_start": "rgba(255, 255, 255, 1)",
     "background_color_end": "rgba(255, 255, 255, 0)",
 })
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index da46a90..90f7160 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -47,89 +47,89 @@
 wait-for: "#search-tabs"
 assert-css: (
     "#search-tabs > button > .count",
-    {"color": "rgb(136, 136, 136)"},
+    {"color": "#888"},
     ALL,
 )
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
-    {"color": "rgb(197, 197, 197)"},
+    {"color": "#c5c5c5"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(0, 150, 207)"},
+    {"color": "#0096cf"},
 )
 
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
+    {"border-bottom-color": "#aaa3"}
 )
 
 // Checking the color of "keyword" text.
 assert-css: (
     "//*[@class='result-name']//*[text()='(keyword)']",
-    {"color": "rgb(120, 135, 151)"},
+    {"color": "#788797"},
 )
 
-store-value: (entry_color, "rgb(0, 150, 207)") // color of the search entry
-store-value: (hover_entry_color, "rgb(255, 255, 255)") // color of the hovered/focused search entry
-store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
-store-value: (hover_background_color, "rgb(60, 60, 60)") // hover background color
+store-value: (entry_color, "#0096cf") // color of the search entry
+store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry
+store-value: (background_color, "transparent") // background color
+store-value: (hover_background_color, "#3c3c3c") // hover background color
 
 call-function: (
     "check-result-color", (
         "keyword", // item kind
-        "rgb(57, 175, 215)", // color of item kind
-        "rgb(57, 175, 215)", // color of hovered/focused item kind
+        "#39afd7", // color of item kind
+        "#39afd7", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "struct", // item kind
-        "rgb(255, 160, 165)", // color of item kind
-        "rgb(255, 160, 165)", // color of hovered/focused item kind
+        "#ffa0a5", // color of item kind
+        "#ffa0a5", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "associatedtype", // item kind
-        "rgb(57, 175, 215)", // color of item kind
-        "rgb(57, 175, 215)", // color of hovered/focused item kind
+        "#39afd7", // color of item kind
+        "#39afd7", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "tymethod", // item kind
-        "rgb(253, 214, 135)", // color of item kind
-        "rgb(253, 214, 135)", // color of hovered/focused item kind
+        "#fdd687", // color of item kind
+        "#fdd687", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "method", // item kind
-        "rgb(253, 214, 135)", // color of item kind
-        "rgb(253, 214, 135)", // color of hovered/focused item kind
+        "#fdd687", // color of item kind
+        "#fdd687", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "structfield", // item kind
-        "rgb(0, 150, 207)", // color of item kind
-        "rgb(255, 255, 255)", // color of hovered/focused item kind
+        "#0096cf", // color of item kind
+        "#fff", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "macro", // item kind
-        "rgb(163, 122, 204)", // color of item kind
-        "rgb(163, 122, 204)", // color of hovered/focused item kind
+        "#a37acc", // color of item kind
+        "#a37acc", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "fn", // item kind
-        "rgb(253, 214, 135)", // color of item kind
-        "rgb(253, 214, 135)", // color of hovered/focused item kind
+        "#fdd687", // color of item kind
+        "#fdd687", // color of hovered/focused item kind
     ),
 )
 
@@ -138,7 +138,7 @@
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(0, 150, 207)", "background-color": "rgba(0, 0, 0, 0)"},
+    {"color": "#0096cf", "background-color": "transparent"},
     ALL,
 )
 
@@ -146,11 +146,11 @@
 move-cursor-to: "//*[@class='desc'][text()='Just a normal struct.']"
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(255, 255, 255)"},
+    {"color": "#fff"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(255, 255, 255)", "background-color": "rgb(60, 60, 60)"},
+    {"color": "#fff", "background-color": "rgb(60, 60, 60)"},
 )
 
 // Dark theme
@@ -164,89 +164,89 @@
 wait-for: "#search-tabs"
 assert-css: (
     "#search-tabs > button > .count",
-    {"color": "rgb(136, 136, 136)"},
+    {"color": "#888"},
     ALL,
 )
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
-    {"color": "rgb(221, 221, 221)"},
+    {"color": "#ddd"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(221, 221, 221)"},
+    {"color": "#ddd"},
 )
 
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
+    {"border-bottom-color": "#aaa3"}
 )
 
 // Checking the color for "keyword" text.
 assert-css: (
     "//*[@class='result-name']//*[text()='(keyword)']",
-    {"color": "rgb(221, 221, 221)"},
+    {"color": "#ddd"},
 )
 
-store-value: (entry_color, "rgb(221, 221, 221)") // color of the search entry
-store-value: (hover_entry_color, "rgb(221, 221, 221)") // color of the hovered/focused search entry
-store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
-store-value: (hover_background_color, "rgb(97, 97, 97)") // hover background color
+store-value: (entry_color, "#ddd") // color of the search entry
+store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry
+store-value: (background_color, "transparent") // background color
+store-value: (hover_background_color, "#616161") // hover background color
 
 call-function: (
     "check-result-color", (
         "keyword", // item kind
-        "rgb(210, 153, 29)", // color of item kind
-        "rgb(210, 153, 29)", // color of hovered/focused item kind
+        "#d2991d", // color of item kind
+        "#d2991d", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "struct", // item kind
-        "rgb(45, 191, 184)", // color of item kind
-        "rgb(45, 191, 184)", // color of hovered/focused item kind
+        "#2dbfb8", // color of item kind
+        "#2dbfb8", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "associatedtype", // item kind
-        "rgb(210, 153, 29)", // color of item kind
-        "rgb(210, 153, 29)", // color of hovered/focused item kind
+        "#d2991d", // color of item kind
+        "#d2991d", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "tymethod", // item kind
-        "rgb(43, 171, 99)", // color of item kind
-        "rgb(43, 171, 99)", // color of hovered/focused item kind
+        "#2bab63", // color of item kind
+        "#2bab63", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "method", // item kind
-        "rgb(43, 171, 99)", // color of item kind
-        "rgb(43, 171, 99)", // color of hovered/focused item kind
+        "#2bab63", // color of item kind
+        "#2bab63", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "structfield", // item kind
-        "rgb(221, 221, 221)", // color of item kind
-        "rgb(221, 221, 221)", // color of hovered/focused item kind
+        "#ddd", // color of item kind
+        "#ddd", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "macro", // item kind
-        "rgb(9, 189, 0)", // color of item kind
-        "rgb(9, 189, 0)", // color of hovered/focused item kind
+        "#09bd00", // color of item kind
+        "#09bd00", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "fn", // item kind
-        "rgb(43, 171, 99)", // color of item kind
-        "rgb(43, 171, 99)", // color of hovered/focused item kind
+        "#2bab63", // color of item kind
+        "#2bab63", // color of hovered/focused item kind
     ),
 )
 
@@ -255,7 +255,7 @@
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"},
+    {"color": "#ddd", "background-color": "transparent"},
 )
 
 // Light theme
@@ -266,89 +266,89 @@
 wait-for: "#search-tabs"
 assert-css: (
     "#search-tabs > button > .count",
-    {"color": "rgb(136, 136, 136)"},
+    {"color": "#888"},
     ALL,
 )
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
-    {"color": "rgb(0, 0, 0)"},
+    {"color": "#000"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(0, 0, 0)"},
+    {"color": "#000"},
 )
 
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
+    {"border-bottom-color": "#aaa3"}
 )
 
 // Checking the color for "keyword" text.
 assert-css: (
     "//*[@class='result-name']//*[text()='(keyword)']",
-    {"color": "rgb(0, 0, 0)"},
+    {"color": "#000"},
 )
 
-store-value: (entry_color, "rgb(0, 0, 0)") // color of the search entry
-store-value: (hover_entry_color, "rgb(0, 0, 0)") // color of the hovered/focused search entry
-store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
-store-value: (hover_background_color, "rgb(204, 204, 204)") // hover background color
+store-value: (entry_color, "#000") // color of the search entry
+store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry
+store-value: (background_color, "transparent") // background color
+store-value: (hover_background_color, "#ccc") // hover background color
 
 call-function: (
     "check-result-color", (
         "keyword", // item kind
-        "rgb(56, 115, 173)", // color of item kind
-        "rgb(56, 115, 173)", // color of hovered/focused item kind
+        "#3873ad", // color of item kind
+        "#3873ad", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "struct", // item kind
-        "rgb(173, 55, 138)", // color of item kind
-        "rgb(173, 55, 138)", // color of hovered/focused item kind
+        "#ad378a", // color of item kind
+        "#ad378a", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "associatedtype", // item kind
-        "rgb(56, 115, 173)", // color of item kind
-        "rgb(56, 115, 173)", // color of hovered/focused item kind
+        "#3873ad", // color of item kind
+        "#3873ad", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "tymethod", // item kind
-        "rgb(173, 124, 55)", // color of item kind
-        "rgb(173, 124, 55)", // color of hovered/focused item kind
+        "#ad7c37", // color of item kind
+        "#ad7c37", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "method", // item kind
-        "rgb(173, 124, 55)", // color of item kind
-        "rgb(173, 124, 55)", // color of hovered/focused item kind
+        "#ad7c37", // color of item kind
+        "#ad7c37", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "structfield", // item kind
-        "rgb(0, 0, 0)", // color of item kind
-        "rgb(0, 0, 0)", // color of hovered/focused item kind
+        "#000", // color of item kind
+        "#000", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "macro", // item kind
-        "rgb(6, 128, 0)", // color of item kind
-        "rgb(6, 128, 0)", // color of hovered/focused item kind
+        "#068000", // color of item kind
+        "#068000", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "fn", // item kind
-        "rgb(173, 124, 55)", // color of item kind
-        "rgb(173, 124, 55)", // color of hovered/focused item kind
+        "#ad7c37", // color of item kind
+        "#ad7c37", // color of hovered/focused item kind
     ),
 )
 
@@ -357,7 +357,7 @@
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"},
+    {"color": "#000", "background-color": "transparent"},
 )
 
 // Check the alias.
@@ -386,16 +386,16 @@
 
 call-function: ("check-alias", {
     "theme": "ayu",
-    "alias": "rgb(197, 197, 197)",
-    "grey": "rgb(153, 153, 153)",
+    "alias": "#c5c5c5",
+    "grey": "#999",
 })
 call-function: ("check-alias", {
     "theme": "dark",
-    "alias": "rgb(255, 255, 255)",
-    "grey": "rgb(204, 204, 204)",
+    "alias": "#fff",
+    "grey": "#ccc",
 })
 call-function: ("check-alias", {
     "theme": "light",
-    "alias": "rgb(0, 0, 0)",
-    "grey": "rgb(153, 153, 153)",
+    "alias": "#000",
+    "grey": "#999",
 })
diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml
index bf1fe7b..c37d969 100644
--- a/tests/rustdoc-gui/settings.goml
+++ b/tests/rustdoc-gui/settings.goml
@@ -301,7 +301,7 @@
 // Now we go to the settings page to check that the CSS is loaded as expected.
 go-to: "file://" + |DOC_PATH| + "/settings.html"
 wait-for: "#settings"
-assert-css: (".setting-line", {"position": "relative"})
+assert-css: (".setting-radio", {"cursor": "pointer"})
 
 assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS)
 compare-elements-position: (".sub form", "#settings", ("x"))
@@ -322,4 +322,4 @@
 set-window-size: (300, 1000)
 click: "#settings-menu"
 wait-for: "#settings"
-assert-css: (".setting-line", {"position": "relative"})
+assert-css: (".setting-radio", {"cursor": "pointer"})
diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml
index 5c79592..d5dd511 100644
--- a/tests/rustdoc-gui/source-code-page.goml
+++ b/tests/rustdoc-gui/source-code-page.goml
@@ -40,24 +40,24 @@
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "color": "rgb(92, 103, 115)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(112, 128, 144)",
+    "color": "#5c6773",
+    "background_color": "transparent",
+    "highlight_color": "#708090",
     "highlight_background_color": "rgba(255, 236, 164, 0.06)",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "color": "rgb(59, 145, 226)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(59, 145, 226)",
-    "highlight_background_color": "rgb(10, 4, 47)",
+    "color": "#3b91e2",
+    "background_color": "transparent",
+    "highlight_color": "#3b91e2",
+    "highlight_background_color": "#0a042f",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "color": "rgb(198, 126, 45)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(198, 126, 45)",
-    "highlight_background_color": "rgb(253, 255, 211)",
+    "color": "#c67e2d",
+    "background_color": "transparent",
+    "highlight_color": "#c67e2d",
+    "highlight_background_color": "#fdffd3",
 })
 
 // This is to ensure that the content is correctly align with the line numbers.
diff --git a/tests/rustdoc-gui/stab-badge.goml b/tests/rustdoc-gui/stab-badge.goml
index e234041..bb3d2aa 100644
--- a/tests/rustdoc-gui/stab-badge.goml
+++ b/tests/rustdoc-gui/stab-badge.goml
@@ -26,16 +26,16 @@
 
 call-function: ("check-badge", {
     "theme": "ayu",
-    "color": "rgb(197, 197, 197)",
-    "background": "rgb(49, 69, 89)",
+    "color": "#c5c5c5",
+    "background": "#314559",
 })
 call-function: ("check-badge", {
     "theme": "dark",
-    "color": "rgb(221, 221, 221)",
-    "background": "rgb(49, 69, 89)",
+    "color": "#ddd",
+    "background": "#314559",
 })
 call-function: ("check-badge", {
     "theme": "light",
-    "color": "rgb(0, 0, 0)",
-    "background": "rgb(255, 245, 214)",
+    "color": "black",
+    "background": "#fff5d6",
 })
diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs
index 6d7f6bb..05c2d42 100644
--- a/tests/rustdoc-json/assoc_items.rs
+++ b/tests/rustdoc-json/assoc_items.rs
@@ -3,35 +3,32 @@
 pub struct Simple;
 
 impl Simple {
-    // @is "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\"
+    // @has "$.index[*][?(@.name=='CONSTANT')].inner.assoc_const"
     pub const CONSTANT: usize = 0;
 }
 
 pub trait EasyToImpl {
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].kind" \"assoc_type\"
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.default" null
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.bounds" []
+    // @has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type"
+    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null
+    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" []
     /// ToDeclare trait
     type ToDeclare;
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].kind" \"assoc_const\"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.default" null
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.type.kind" '"primitive"'
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.type.inner" '"usize"'
+    // @has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const"
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"'
     /// AN_ATTRIBUTE trait
     const AN_ATTRIBUTE: usize;
 }
 
 impl EasyToImpl for Simple {
-    // @is "$.index[*][?(@.docs=='ToDeclare impl')].kind" '"assoc_type"'
-    // @is "$.index[*][?(@.docs=='ToDeclare impl')].inner.default.kind" \"primitive\"
-    // @is "$.index[*][?(@.docs=='ToDeclare impl')].inner.default.inner" \"usize\"
+    // @has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type"
+    // @is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\"
     /// ToDeclare impl
     type ToDeclare = usize;
 
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].kind" '"assoc_const"'
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.type.kind" \"primitive\"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.type.inner" \"usize\"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.default" \"12\"
+    // @has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const"
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\"
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\"
     /// AN_ATTRIBUTE impl
     const AN_ATTRIBUTE: usize = 12;
 }
diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs
index c5cc87c..a2a5c4a 100644
--- a/tests/rustdoc-json/blanket_impls.rs
+++ b/tests/rustdoc-json/blanket_impls.rs
@@ -2,7 +2,7 @@
 
 #![no_std]
 
-// @has "$.index[*][?(@.name=='Error')].kind" \"assoc_type\"
-// @has "$.index[*][?(@.name=='Error')].inner.default.kind" \"resolved_path\"
-// @has "$.index[*][?(@.name=='Error')].inner.default.inner.name" \"Infallible\"
+// @has "$.index[*][?(@.name=='Error')].inner.assoc_type"
+// @has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path"
+// @has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\"
 pub struct ForBlanketTryFromImpl;
diff --git a/tests/rustdoc-json/enums/discriminant/basic.rs b/tests/rustdoc-json/enums/discriminant/basic.rs
index 06906df..dbfc5c2 100644
--- a/tests/rustdoc-json/enums/discriminant/basic.rs
+++ b/tests/rustdoc-json/enums/discriminant/basic.rs
@@ -1,12 +1,12 @@
 #[repr(i8)]
 pub enum Ordering {
-    // @is "$.index[*][?(@.name=='Less')].inner.discriminant.expr" '"-1"'
-    // @is "$.index[*][?(@.name=='Less')].inner.discriminant.value" '"-1"'
+    // @is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.expr" '"-1"'
+    // @is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.value" '"-1"'
     Less = -1,
-    // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.expr" '"0"'
-    // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.expr" '"0"'
+    // @is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.value" '"0"'
     Equal = 0,
-    // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.expr" '"1"'
-    // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.value" '"1"'
+    // @is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.expr" '"1"'
+    // @is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.value" '"1"'
     Greater = 1,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/expr.rs b/tests/rustdoc-json/enums/discriminant/expr.rs
index e639965..ddcad58 100644
--- a/tests/rustdoc-json/enums/discriminant/expr.rs
+++ b/tests/rustdoc-json/enums/discriminant/expr.rs
@@ -1,30 +1,30 @@
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.expr" '"{ _ }"'
     Addition = 0 + 0,
-    // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.value" '"1"'
-    // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.expr" '"0b1"'
+    // @is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.value" '"1"'
+    // @is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.expr" '"0b1"'
     Bin = 0b1,
-    // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.value" '"2"'
-    // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.expr" '"0o2"'
+    // @is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.value" '"2"'
+    // @is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.expr" '"0o2"'
     Oct = 0o2,
-    // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.value" '"3"'
-    // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.expr" '"THREE"'
+    // @is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.value" '"3"'
+    // @is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.expr" '"THREE"'
     PubConst = THREE,
-    // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.value" '"4"'
-    // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.expr" '"0x4"'
+    // @is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.value" '"4"'
+    // @is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.expr" '"0x4"'
     Hex = 0x4,
-    // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.value" '"5"'
-    // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.value" '"5"'
+    // @is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.expr" '"{ _ }"'
     Cast = 5 as isize,
-    // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.value" '"6"'
-    // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.value" '"6"'
+    // @is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.expr" '"{ _ }"'
     PubCall = six(),
-    // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.value" '"7"'
-    // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.value" '"7"'
+    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.expr" '"{ _ }"'
     PrivCall = seven(),
-    // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.value" '"8"'
-    // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.expr" '"EIGHT"'
+    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.value" '"8"'
+    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.expr" '"EIGHT"'
     PrivConst = EIGHT,
 }
 
diff --git a/tests/rustdoc-json/enums/discriminant/limits.rs b/tests/rustdoc-json/enums/discriminant/limits.rs
index e56d559..47fb704 100644
--- a/tests/rustdoc-json/enums/discriminant/limits.rs
+++ b/tests/rustdoc-json/enums/discriminant/limits.rs
@@ -4,40 +4,40 @@
 
 #[repr(u64)]
 pub enum U64 {
-    // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.expr" '"u64::MIN"'
+    // @is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.expr" '"u64::MIN"'
     U64Min = u64::MIN,
-    // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.value" '"18446744073709551615"'
-    // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.expr" '"u64::MAX"'
+    // @is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.value" '"18446744073709551615"'
+    // @is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.expr" '"u64::MAX"'
     U64Max = u64::MAX,
 }
 
 #[repr(i64)]
 pub enum I64 {
-    // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.value" '"-9223372036854775808"'
-    // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.expr" '"i64::MIN"'
+    // @is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.value" '"-9223372036854775808"'
+    // @is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.expr" '"i64::MIN"'
     I64Min = i64::MIN,
-    // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.value" '"9223372036854775807"'
-    // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.expr" '"i64::MAX"'
+    // @is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.value" '"9223372036854775807"'
+    // @is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.expr" '"i64::MAX"'
     I64Max = i64::MAX,
 }
 
 #[repr(u128)]
 pub enum U128 {
-    // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.expr" '"u128::MIN"'
+    // @is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.expr" '"u128::MIN"'
     U128Min = u128::MIN,
-    // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.value" '"340282366920938463463374607431768211455"'
-    // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.expr" '"u128::MAX"'
+    // @is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.value" '"340282366920938463463374607431768211455"'
+    // @is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.expr" '"u128::MAX"'
     U128Max = u128::MAX,
 }
 
 #[repr(i128)]
 pub enum I128 {
-    // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.value" '"-170141183460469231731687303715884105728"'
-    // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.expr" '"i128::MIN"'
+    // @is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.value" '"-170141183460469231731687303715884105728"'
+    // @is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.expr" '"i128::MIN"'
     I128Min = i128::MIN,
-    // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.value" '"170141183460469231731687303715884105727"'
-    // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.expr" '"i128::MAX"'
+    // @is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.value" '"170141183460469231731687303715884105727"'
+    // @is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.expr" '"i128::MAX"'
     I128Max = i128::MAX,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
index 6889b30..9c3db81 100644
--- a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
+++ b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
@@ -1,15 +1,17 @@
+// ignore-tidy-linelength
+
 #[repr(u32)]
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.expr" '"0"'
+    // @is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.expr" '"0"'
     Basic = 0,
-    // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.value" '"10"'
-    // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.expr" '"10u32"'
+    // @is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.value" '"10"'
+    // @is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.expr" '"10u32"'
     Suffix = 10u32,
-    // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.value" '"100"'
-    // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.expr" '"1_0_0"'
+    // @is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.value" '"100"'
+    // @is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.expr" '"1_0_0"'
     Underscore = 1_0_0,
-    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.value" '"1000"'
-    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.expr" '"1_0_0_0u32"'
+    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.value" '"1000"'
+    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.expr" '"1_0_0_0u32"'
     SuffixUnderscore = 1_0_0_0u32,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
index 6a4f54d..38ba1ca 100644
--- a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
+++ b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
@@ -1,10 +1,12 @@
+// ignore-tidy-linelength
+
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Has')].inner.discriminant" '{"expr":"0", "value":"0"}'
+    // @is "$.index[*][?(@.name=='Has')].inner.variant.discriminant" '{"expr":"0", "value":"0"}'
     Has = 0,
-    // @is "$.index[*][?(@.name=='Doesnt')].inner.discriminant" null
+    // @is "$.index[*][?(@.name=='Doesnt')].inner.variant.discriminant" null
     Doesnt,
-    // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.discriminant" null
+    // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant.discriminant" null
     AlsoDoesnt,
-    // @is "$.index[*][?(@.name=='AlsoHas')].inner.discriminant" '{"expr":"44", "value":"44"}'
+    // @is "$.index[*][?(@.name=='AlsoHas')].inner.variant.discriminant" '{"expr":"44", "value":"44"}'
     AlsoHas = 44,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs
index e91a632..c4b087c 100644
--- a/tests/rustdoc-json/enums/discriminant/struct.rs
+++ b/tests/rustdoc-json/enums/discriminant/struct.rs
@@ -3,13 +3,13 @@
 #[repr(i32)]
 // @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(i32)]"]'
 pub enum Foo {
-    // @is    "$.index[*][?(@.name=='Struct')].inner.discriminant" null
-    // @count "$.index[*][?(@.name=='Struct')].inner.kind.struct.fields[*]" 0
+    // @is    "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null
+    // @count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0
     Struct {},
-    // @is    "$.index[*][?(@.name=='StructWithDiscr')].inner.discriminant" '{"expr": "42", "value": "42"}'
-    // @count "$.index[*][?(@.name=='StructWithDiscr')].inner.kind.struct.fields[*]" 1
+    // @is    "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.discriminant" '{"expr": "42", "value": "42"}'
+    // @count "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.kind.struct.fields[*]" 1
     StructWithDiscr { x: i32 } = 42,
-    // @is    "$.index[*][?(@.name=='StructWithHexDiscr')].inner.discriminant"  '{"expr": "0x42", "value": "66"}'
-    // @count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.kind.struct.fields[*]" 2
+    // @is    "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.discriminant"  '{"expr": "0x42", "value": "66"}'
+    // @count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.kind.struct.fields[*]" 2
     StructWithHexDiscr { x: i32, y: bool } = 0x42,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs
index b94d573..7da82ec 100644
--- a/tests/rustdoc-json/enums/discriminant/tuple.rs
+++ b/tests/rustdoc-json/enums/discriminant/tuple.rs
@@ -3,13 +3,13 @@
 #[repr(u32)]
 // @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(u32)]"]'
 pub enum Foo {
-    // @is    "$.index[*][?(@.name=='Tuple')].inner.discriminant" null
-    // @count "$.index[*][?(@.name=='Tuple')].inner.kind.tuple[*]" 0
+    // @is    "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null
+    // @count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0
     Tuple(),
-    // @is    "$.index[*][?(@.name=='TupleWithDiscr')].inner.discriminant" '{"expr": "1", "value": "1"}'
-    // @count "$.index[*][?(@.name=='TupleWithDiscr')].inner.kind.tuple[*]" 1
+    // @is    "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.discriminant" '{"expr": "1", "value": "1"}'
+    // @count "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.kind.tuple[*]" 1
     TupleWithDiscr(i32) = 1,
-    // @is    "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.discriminant" '{"expr": "0b10", "value": "2"}'
-    // @count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.discriminant" '{"expr": "0b10", "value": "2"}'
+    // @count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.kind.tuple[*]" 2
     TupleWithBinDiscr(i32, i32) = 0b10,
 }
diff --git a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
index 470b195..b001561 100644
--- a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
+++ b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
@@ -5,7 +5,7 @@
 extern crate color;
 use color::Color::Red;
 
-// @set red = "$.index[*][?(@.inner.is_crate == true)].links.Red"
+// @set red = "$.index[*][?(@.inner.module.is_crate)].links.Red"
 
 // @!has "$.index[*][?(@.name == 'Red')]"
 // @!has "$.index[*][?(@.name == 'Color')]"
diff --git a/tests/rustdoc-json/enums/field_hidden.rs b/tests/rustdoc-json/enums/field_hidden.rs
index 78a0543..5c0d0ff 100644
--- a/tests/rustdoc-json/enums/field_hidden.rs
+++ b/tests/rustdoc-json/enums/field_hidden.rs
@@ -5,8 +5,8 @@
 
 // @has "$.index[*][?(@.name=='ParseError')]"
 // @has "$.index[*][?(@.name=='UnexpectedEndTag')]"
-// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.kind.tuple" [null]
-// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.discriminant" null
+// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null]
+// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.discriminant" null
 
 pub enum ParseError {
     UnexpectedEndTag(#[doc(hidden)] u32),
diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs
index 1787a85..e283c07 100644
--- a/tests/rustdoc-json/enums/kind.rs
+++ b/tests/rustdoc-json/enums/kind.rs
@@ -5,28 +5,28 @@
 
 pub enum Foo {
     // @set Unit = "$.index[*][?(@.name=='Unit')].id"
-    // @is "$.index[*][?(@.name=='Unit')].inner.kind" '"plain"'
+    // @is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"'
     Unit,
     // @set Named = "$.index[*][?(@.name=='Named')].id"
-    // @is "$.index[*][?(@.name=='Named')].inner.kind.struct" '{"fields": [], "fields_stripped": false}'
+    // @is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}'
     Named {},
     // @set Tuple = "$.index[*][?(@.name=='Tuple')].id"
-    // @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" []
+    // @is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" []
     Tuple(),
     // @set NamedField = "$.index[*][?(@.name=='NamedField')].id"
-    // @set x = "$.index[*][?(@.name=='x' && @.kind=='struct_field')].id"
-    // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields[*]" $x
-    // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields_stripped" false
+    // @set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id"
+    // @is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x
+    // @is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false
     NamedField { x: i32 },
     // @set TupleField = "$.index[*][?(@.name=='TupleField')].id"
-    // @set tup_field = "$.index[*][?(@.name=='0' && @.kind=='struct_field')].id"
-    // @is "$.index[*][?(@.name=='TupleField')].inner.kind.tuple[*]" $tup_field
+    // @set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id"
+    // @is "$.index[*][?(@.name=='TupleField')].inner.variant.kind.tuple[*]" $tup_field
     TupleField(i32),
 }
 
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[0]" $Unit
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[1]" $Named
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[2]" $Tuple
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[3]" $NamedField
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[4]" $TupleField
-// @count "$.index[*][?(@.name=='Foo')].inner.variants[*]" 5
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[0]" $Unit
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[1]" $Named
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[2]" $Tuple
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[3]" $NamedField
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[4]" $TupleField
+// @count "$.index[*][?(@.name=='Foo')].inner.enum.variants[*]" 5
diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs
index de939cd..2676c4e 100644
--- a/tests/rustdoc-json/enums/struct_field_hidden.rs
+++ b/tests/rustdoc-json/enums/struct_field_hidden.rs
@@ -9,8 +9,8 @@
         // @set y = "$.index[*][?(@.name=='y')].id"
         y: i32,
     },
-    // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields_stripped" true
-    // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[0]" $b
-    // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[1]" $y
-    // @count "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[*]" 2
+    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true
+    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b
+    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y
+    // @count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2
 }
diff --git a/tests/rustdoc-json/enums/tuple_fields_hidden.rs b/tests/rustdoc-json/enums/tuple_fields_hidden.rs
index 70bfbb8..3aeb035 100644
--- a/tests/rustdoc-json/enums/tuple_fields_hidden.rs
+++ b/tests/rustdoc-json/enums/tuple_fields_hidden.rs
@@ -14,47 +14,47 @@
 // @set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id"
 
 pub enum EnumWithStrippedTupleVariants {
-    // @count "$.index[*][?(@.name=='None')].inner.kind.tuple[*]" 0
+    // @count "$.index[*][?(@.name=='None')].inner.variant.kind.tuple[*]" 0
     None(),
 
-    // @count "$.index[*][?(@.name=='One')].inner.kind.tuple[*]" 1
-    // @is    "$.index[*][?(@.name=='One')].inner.kind.tuple[0]" $1.1.0
+    // @count "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[*]" 1
+    // @is    "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[0]" $1.1.0
     One(/** 1.1.0*/ bool),
-    // @count "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[*]" 1
-    // @is    "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[0]" null
+    // @count "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[*]" 1
+    // @is    "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[0]" null
     OneHidden(#[doc(hidden)] bool),
 
-    // @count "$.index[*][?(@.name=='Two')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='Two')].inner.kind.tuple[0]" $2.1.0
-    // @is    "$.index[*][?(@.name=='Two')].inner.kind.tuple[1]" $2.1.1
+    // @count "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[0]" $2.1.0
+    // @is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[1]" $2.1.1
     Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool),
-    // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[1]" $2.2.1
+    // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[0]" null
+    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[1]" $2.2.1
     TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool),
-    // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[0]" $2.3.0
-    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[1]" null
+    // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[0]" $2.3.0
+    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[1]" null
     TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool),
-    // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[1]" null
+    // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[0]" null
+    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[1]" null
     TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool),
 
-    // @count "$.index[*][?(@.name=='Three1')].inner.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three1')].inner.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='Three1')].inner.kind.tuple[1]" $3.1.1
-    // @is    "$.index[*][?(@.name=='Three1')].inner.kind.tuple[2]" $3.1.2
+    // @count "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[*]" 3
+    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[0]" null
+    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[1]" $3.1.1
+    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[2]" $3.1.2
     Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool),
-    // @count "$.index[*][?(@.name=='Three2')].inner.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three2')].inner.kind.tuple[0]" $3.2.0
-    // @is    "$.index[*][?(@.name=='Three2')].inner.kind.tuple[1]" null
-    // @is    "$.index[*][?(@.name=='Three2')].inner.kind.tuple[2]" $3.2.2
+    // @count "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[*]" 3
+    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[0]" $3.2.0
+    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[1]" null
+    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[2]" $3.2.2
     Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool),
-    // @count "$.index[*][?(@.name=='Three3')].inner.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three3')].inner.kind.tuple[0]" $3.3.0
-    // @is    "$.index[*][?(@.name=='Three3')].inner.kind.tuple[1]" $3.3.1
-    // @is    "$.index[*][?(@.name=='Three3')].inner.kind.tuple[2]" null
+    // @count "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[*]" 3
+    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[0]" $3.3.0
+    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[1]" $3.3.1
+    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[2]" null
     Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool),
 }
 
@@ -70,14 +70,14 @@
 // @is "$.index[*][?(@.docs=='3.3.0')].name" '"0"'
 // @is "$.index[*][?(@.docs=='3.3.1')].name" '"1"'
 
-// @is "$.index[*][?(@.docs=='1.1.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.1.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.1.1')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.2.1')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.3.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.1.1')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.1.2')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.2.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.2.2')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.3.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.3.1')].inner" '{"kind": "primitive", "inner": "bool"}'
+// @is "$.index[*][?(@.docs=='1.1.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.1.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.1.1')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.2.1')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.3.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.1.1')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.1.2')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.2.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.2.2')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.3.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.3.1')].inner.struct_field" '{"primitive": "bool"}'
diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs
index 62b8b83..49990ec 100644
--- a/tests/rustdoc-json/enums/use_glob.rs
+++ b/tests/rustdoc-json/enums/use_glob.rs
@@ -10,9 +10,9 @@
     Blue,
 }
 
-// @set use_Color = "$.index[*][?(@.kind == 'import')].id"
-// @is "$.index[*][?(@.kind == 'import')].inner.id" $Color
-// @is "$.index[*][?(@.kind == 'import')].inner.glob" true
+// @set use_Color = "$.index[*][?(@.inner.import)].id"
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $Color
+// @is "$.index[*][?(@.inner.import)].inner.import.glob" true
 pub use Color::*;
 
-// @ismany "$.index[*][?(@.name == 'use_glob')].inner.items[*]" $Color $use_Color
+// @ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color
diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs
index 5f0d2b9..8190e1c 100644
--- a/tests/rustdoc-json/enums/use_variant.rs
+++ b/tests/rustdoc-json/enums/use_variant.rs
@@ -6,10 +6,10 @@
     // @set None = "$.index[*][?(@.name == 'None')].id"
     None,
 }
-// @is "$.index[*][?(@.name == 'AlwaysNone')].inner.variants[*]" $None
+// @is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None
 
-// @set use_None = "$.index[*][?(@.kind == 'import')].id"
-// @is "$.index[*][?(@.kind == 'import')].inner.id" $None
+// @set use_None = "$.index[*][?(@.inner.import)].id"
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $None
 pub use AlwaysNone::None;
 
-// @ismany "$.index[*][?(@.name == 'use_variant')].inner.items[*]" $AlwaysNone $use_None
+// @ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None
diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs
index 11bb6ce..a79e899 100644
--- a/tests/rustdoc-json/enums/use_variant_foreign.rs
+++ b/tests/rustdoc-json/enums/use_variant_foreign.rs
@@ -2,7 +2,7 @@
 
 extern crate color;
 
-// @is "$.index[*][?(@.inner.name == 'Red')].kind" '"import"'
+// @has "$.index[*].inner.import[?(@.name == 'Red')]"
 pub use color::Color::Red;
 
 // @!has "$.index[*][?(@.name == 'Red')]"
diff --git a/tests/rustdoc-json/enums/variant_struct.rs b/tests/rustdoc-json/enums/variant_struct.rs
index bc870c5..fe40f1a 100644
--- a/tests/rustdoc-json/enums/variant_struct.rs
+++ b/tests/rustdoc-json/enums/variant_struct.rs
@@ -1,10 +1,10 @@
 // @is "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\"
+// @has "$.index[*][?(@.name=='EnumStruct')].inner.enum"
 pub enum EnumStruct {
-    // @is "$.index[*][?(@.name=='x')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='x')].inner.struct_field"
     // @set x = "$.index[*][?(@.name=='x')].id"
-    // @is "$.index[*][?(@.name=='y')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='y')].inner.struct_field"
     // @set y = "$.index[*][?(@.name=='y')].id"
-    // @ismany "$.index[*][?(@.name=='VariantS')].inner.kind.struct.fields[*]" $x $y
+    // @ismany "$.index[*][?(@.name=='VariantS')].inner.variant.kind.struct.fields[*]" $x $y
     VariantS { x: u32, y: String },
 }
diff --git a/tests/rustdoc-json/enums/variant_tuple_struct.rs b/tests/rustdoc-json/enums/variant_tuple_struct.rs
index d1207bb..358fc10 100644
--- a/tests/rustdoc-json/enums/variant_tuple_struct.rs
+++ b/tests/rustdoc-json/enums/variant_tuple_struct.rs
@@ -1,10 +1,10 @@
 // @is "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\"
+// @has "$.index[*][?(@.name=='EnumTupleStruct')].inner.enum"
 pub enum EnumTupleStruct {
-    // @is "$.index[*][?(@.name=='0')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='0')].inner.struct_field"
     // @set f0 = "$.index[*][?(@.name=='0')].id"
-    // @is "$.index[*][?(@.name=='1')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='1')].inner.struct_field"
     // @set f1 = "$.index[*][?(@.name=='1')].id"
-    // @ismany "$.index[*][?(@.name=='VariantA')].inner.kind.tuple[*]" $f0 $f1
+    // @ismany "$.index[*][?(@.name=='VariantA')].inner.variant.kind.tuple[*]" $f0 $f1
     VariantA(u32, String),
 }
diff --git a/tests/rustdoc-json/fn_pointer/abi.rs b/tests/rustdoc-json/fn_pointer/abi.rs
index 6a30acc..77c0e82 100644
--- a/tests/rustdoc-json/fn_pointer/abi.rs
+++ b/tests/rustdoc-json/fn_pointer/abi.rs
@@ -2,23 +2,23 @@
 
 #![feature(abi_vectorcall)]
 
-// @is "$.index[*][?(@.name=='AbiRust')].inner.type.inner.header.abi" \"Rust\"
+// @is "$.index[*][?(@.name=='AbiRust')].inner.typedef.type.function_pointer.header.abi" \"Rust\"
 pub type AbiRust = fn();
 
-// @is "$.index[*][?(@.name=='AbiC')].inner.type.inner.header.abi" '{"C": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='AbiC')].inner.typedef.type.function_pointer.header.abi" '{"C": {"unwind": false}}'
 pub type AbiC = extern "C" fn();
 
-// @is "$.index[*][?(@.name=='AbiSystem')].inner.type.inner.header.abi" '{"System": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='AbiSystem')].inner.typedef.type.function_pointer.header.abi" '{"System": {"unwind": false}}'
 pub type AbiSystem = extern "system" fn();
 
-// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.type.inner.header.abi" '{"C": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.typedef.type.function_pointer.header.abi" '{"C": {"unwind": true}}'
 pub type AbiCUnwind = extern "C-unwind" fn();
 
-// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type.inner.header.abi" '{"System": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.typedef.type.function_pointer.header.abi" '{"System": {"unwind": true}}'
 pub type AbiSystemUnwind = extern "system-unwind" fn();
 
-// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.type.inner.header.abi.Other" '"\"vectorcall\""'
+// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.typedef.type.function_pointer.header.abi.Other" '"\"vectorcall\""'
 pub type AbiVecorcall = extern "vectorcall" fn();
 
-// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type.inner.header.abi.Other" '"\"vectorcall-unwind\""'
+// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.typedef.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""'
 pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn();
diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs
index a93b01a..48672f1 100644
--- a/tests/rustdoc-json/fn_pointer/generics.rs
+++ b/tests/rustdoc-json/fn_pointer/generics.rs
@@ -3,12 +3,11 @@
 #![feature(no_core)]
 #![no_core]
 
-// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][0]" '"val"'
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].inner.lifetime" \"\'c\"
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.output" '{ "kind": "primitive", "inner": "i32" }'
-// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].name" \"\'c\"
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[0][0]" '"val"'
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.output.primitive" \"i32\"
+// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[*]" 1
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[0].name" \"\'c\"
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
 pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32;
diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs
index bd65bb3..0ab776c 100644
--- a/tests/rustdoc-json/fn_pointer/qualifiers.rs
+++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs
@@ -1,9 +1,11 @@
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.unsafe" false
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.const" false
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.async" false
+// ignore-tidy-linelength
+
+// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.unsafe" false
+// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.const" false
+// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.async" false
 pub type FnPointer = fn();
 
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.unsafe" true
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.const" false
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.async" false
+// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.unsafe" true
+// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.const" false
+// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.async" false
 pub type UnsafePointer = unsafe fn();
diff --git a/tests/rustdoc-json/fns/abi.rs b/tests/rustdoc-json/fns/abi.rs
index 7a5dbee..d7b98b5 100644
--- a/tests/rustdoc-json/fns/abi.rs
+++ b/tests/rustdoc-json/fns/abi.rs
@@ -2,23 +2,23 @@
 
 #![feature(abi_vectorcall)]
 
-// @is "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
+// @is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
 pub fn abi_rust() {}
 
-// @is "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
 pub extern "C" fn abi_c() {}
 
-// @is "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
 pub extern "system" fn abi_system() {}
 
-// @is "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
 pub extern "C-unwind" fn abi_c_unwind() {}
 
-// @is "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
 pub extern "system-unwind" fn abi_system_unwind() {}
 
-// @is "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+// @is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
 pub extern "vectorcall" fn abi_vectorcall() {}
 
-// @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+// @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
 pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs
index b89781c..8192f2e 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -5,32 +5,30 @@
 
 use std::future::Future;
 
-// @is "$.index[*][?(@.name=='get_int')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int')].inner.header.async" false
+// @is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\"
+// @is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false
 pub fn get_int() -> i32 {
     42
 }
 
-// @is "$.index[*][?(@.name=='get_int_async')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int_async')].inner.header.async" true
+// @is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\"
+// @is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true
 pub async fn get_int_async() -> i32 {
     42
 }
 
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.kind" '"impl_trait"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.header.async" false
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive"  \"i32\"
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false
 pub fn get_int_future() -> impl Future<Output = i32> {
     async { 42 }
 }
 
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.kind" '"impl_trait"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.header.async" true
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\"
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true
 pub async fn get_int_future_async() -> impl Future<Output = i32> {
     async { 42 }
 }
diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs
index 33bebba..d6ea343 100644
--- a/tests/rustdoc-json/fns/extern_c_variadic.rs
+++ b/tests/rustdoc-json/fns/extern_c_variadic.rs
@@ -2,8 +2,8 @@
 #![no_core]
 
 extern "C" {
-    // @is "$.index[*][?(@.name == 'not_variadic')].inner.decl.c_variadic" false
+    // @is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false
     pub fn not_variadic(_: i32);
-    // @is "$.index[*][?(@.name == 'variadic')].inner.decl.c_variadic" true
+    // @is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true
     pub fn variadic(_: i32, ...);
 }
diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs
index eec295e..539d17f 100644
--- a/tests/rustdoc-json/fns/generic_args.rs
+++ b/tests/rustdoc-json/fns/generic_args.rs
@@ -9,59 +9,55 @@
 // @set generic_foo = "$.index[*][?(@.name=='GenericFoo')].id"
 pub trait GenericFoo<'a> {}
 
-// @is "$.index[*][?(@.name=='generics')].inner.generics.where_predicates" "[]"
-// @count "$.index[*][?(@.name=='generics')].inner.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"'
-// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null'
-// @count "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
-// @count "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"'
-// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].inner" '"F"'
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.where_predicates" "[]"
+// @count "$.index[*][?(@.name=='generics')].inner.function.generics.params[*]" 1
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].name" '"F"'
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null'
+// @count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
+// @count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"'
+// @is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"'
 pub fn generics<F: Foo>(f: F) {}
 
-// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]"
-// @count "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"'
-// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
-// @count "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"'
-// @count "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]"
+// @count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"'
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
+// @count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"'
+// @count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
 pub fn impl_trait(f: impl Foo) {}
 
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].name" '"F"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[*]" 3
-// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].kind" '"generic"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].inner" '"F"'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[*]" 3
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"'
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"'
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"'
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.generic_params" "[]"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.type.generic" \"G\"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind.lifetime.outlives" "[]"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.generic_params" "[]"
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.lifetime" \"\'b\"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.type.generic" \"H\"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].kind.lifetime.outlives" "[]"
 pub fn where_clase<F, G, H>(f: F, g: G, h: H)
 where
     F: Foo,
diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs
index a9bc2d5..27d8420 100644
--- a/tests/rustdoc-json/fns/generic_returns.rs
+++ b/tests/rustdoc-json/fns/generic_returns.rs
@@ -3,15 +3,14 @@
 #![feature(no_core)]
 #![no_core]
 
-// @count "$.index[*][?(@.name=='generic_returns')].inner.items[*]" 2
+// @count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2
 
 // @set foo = "$.index[*][?(@.name=='Foo')].id"
 pub trait Foo {}
 
-// @is "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" []
-// @is "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"'
-// @count "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1
-// @is "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" []
+// @count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1
+// @is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo
 pub fn get_foo() -> impl Foo {
     Fooer {}
 }
diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs
index 7b70ff1..5239a6f 100644
--- a/tests/rustdoc-json/fns/generics.rs
+++ b/tests/rustdoc-json/fns/generics.rs
@@ -6,21 +6,20 @@
 // @set wham_id = "$.index[*][?(@.name=='Wham')].id"
 pub trait Wham {}
 
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.where_predicates" []
-// @count "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"'
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]'
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" []
+// @count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"'
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]'
 pub fn one_generic_param_fn<T: Wham>(w: T) {}
 
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" []
-// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $wham_id
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" []
+// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"'
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
+// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"'
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
 pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs
index 32b7da0..55f2479 100644
--- a/tests/rustdoc-json/fns/pattern_arg.rs
+++ b/tests/rustdoc-json/fns/pattern_arg.rs
@@ -1,7 +1,7 @@
-// @is "$.index[*][?(@.name=='fst')].inner.decl.inputs[0][0]" '"(x, _)"'
+// @is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"'
 pub fn fst<X, Y>((x, _): (X, Y)) -> X {
     x
 }
 
-// @is "$.index[*][?(@.name=='drop_int')].inner.decl.inputs[0][0]" '"_"'
+// @is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"'
 pub fn drop_int(_: i32) {}
diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs
index 7ff5429..643865a 100644
--- a/tests/rustdoc-json/fns/qualifiers.rs
+++ b/tests/rustdoc-json/fns/qualifiers.rs
@@ -1,33 +1,33 @@
 // edition:2018
 
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.async" false
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.unsafe" false
+// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false
+// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false
 pub fn nothing_fn() {}
 
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.async"  false
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.unsafe" true
+// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async"  false
+// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true
 pub unsafe fn unsafe_fn() {}
 
-// @is "$.index[*][?(@.name=='const_fn')].inner.header.async"  false
-// @is "$.index[*][?(@.name=='const_fn')].inner.header.const"  true
-// @is "$.index[*][?(@.name=='const_fn')].inner.header.unsafe" false
+// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.async"  false
+// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.const"  true
+// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false
 pub const fn const_fn() {}
 
-// @is "$.index[*][?(@.name=='async_fn')].inner.header.async"  true
-// @is "$.index[*][?(@.name=='async_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='async_fn')].inner.header.unsafe" false
+// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.async"  true
+// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false
 pub async fn async_fn() {}
 
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.async"  true
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.unsafe" true
+// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async"  true
+// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true
 pub async unsafe fn async_unsafe_fn() {}
 
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.async"  false
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.const"  true
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.unsafe" true
+// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async"  false
+// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const"  true
+// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true
 pub const unsafe fn const_unsafe_fn() {}
 
 // It's impossible for a function to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs
index 2578bb4..e8a7dce 100644
--- a/tests/rustdoc-json/fns/return_type_alias.rs
+++ b/tests/rustdoc-json/fns/return_type_alias.rs
@@ -3,8 +3,7 @@
 /// @set foo = "$.index[*][?(@.name=='Foo')].id"
 pub type Foo = i32;
 
-// @is "$.index[*][?(@.name=='demo')].inner.decl.output.kind" '"resolved_path"'
-// @is "$.index[*][?(@.name=='demo')].inner.decl.output.inner.id" $foo
+// @is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo
 pub fn demo() -> Foo {
     42
 }
diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs
index e580978..99c57ff 100644
--- a/tests/rustdoc-json/generic-associated-types/gats.rs
+++ b/tests/rustdoc-json/generic-associated-types/gats.rs
@@ -9,34 +9,32 @@
 pub trait Display {}
 
 pub trait LendingIterator {
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*]" 1
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*].name" \"\'a\"
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*]" 1
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.type.inner" \"Self\"
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.bounds[*]" 1
+    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*]" 1
+    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*].name" \"\'a\"
+    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*]" 1
+    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.type.generic" \"Self\"
+    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
+    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.bounds[*]" 1
     type LendingItem<'a>: Display
     where
         Self: 'a;
 
-    // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.kind" \"qualified_path\"
-    // @count "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 1
-    // @count "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
-    // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.self_type.inner" \"Self\"
-    // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.name" \"LendingItem\"
+    // @count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1
+    // @count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    // @is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
+    // @is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\"
     fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>;
 }
 
 pub trait Iterator {
-    // @count "$.index[*][?(@.name=='Item')].inner.generics.params[*]" 0
-    // @count "$.index[*][?(@.name=='Item')].inner.generics.where_predicates[*]" 0
-    // @count "$.index[*][?(@.name=='Item')].inner.bounds[*]" 1
+    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.params[*]" 0
+    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.where_predicates[*]" 0
+    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1
     type Item: Display;
 
-    // @is "$.index[*][?(@.name=='next')].inner.decl.output.kind" \"qualified_path\"
-    // @count "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 0
-    // @count "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
-    // @is "$.index[*][?(@.name=='next')].inner.decl.output.inner.self_type.inner" \"Self\"
-    // @is "$.index[*][?(@.name=='next')].inner.decl.output.inner.name" \"Item\"
+    // @count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0
+    // @count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    // @is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
+    // @is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\"
     fn next<'a>(&'a self) -> Self::Item;
 }
diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs
index 00051b1..f37ce0a 100644
--- a/tests/rustdoc-json/glob_import.rs
+++ b/tests/rustdoc-json/glob_import.rs
@@ -5,7 +5,7 @@
 #![no_core]
 
 // @has "$.index[*][?(@.name=='glob')]"
-// @has "$.index[*][?(@.kind=='import')].inner.name" \"*\"
+// @has "$.index[*][?(@.inner.import)].inner.import.name" \"*\"
 
 
 mod m1 {
diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs
index 50d8524..ace37e5 100644
--- a/tests/rustdoc-json/impls/auto.rs
+++ b/tests/rustdoc-json/impls/auto.rs
@@ -12,7 +12,8 @@
 }
 
 // Testing spans, so all tests below code
-// @is "$.index[*][?(@.kind=='impl' && @.inner.synthetic==true)].span" null
 // @is "$.index[*][?(@.docs=='has span')].span.begin" "[10, 0]"
 // @is "$.index[*][?(@.docs=='has span')].span.end" "[12, 1]"
+// FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91
+// is "$.index[*][?(@.inner.impl.synthetic==true)].span" null
 pub struct Foo;
diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs
index 290c2d5..20e1cec 100644
--- a/tests/rustdoc-json/impls/foreign_for_local.rs
+++ b/tests/rustdoc-json/impls/foreign_for_local.rs
@@ -3,7 +3,7 @@
 
 /// ForeignTrait id hack
 pub use foreign_trait::ForeignTrait as _;
-// @set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.id"
+// @set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id"
 
 pub struct LocalStruct;
 // @set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id"
@@ -12,7 +12,7 @@
 impl foreign_trait::ForeignTrait for LocalStruct {}
 
 // @set impl = "$.index[*][?(@.docs=='foreign for local')].id"
-// @is "$.index[*][?(@.docs=='foreign for local')].inner.for.inner.id" $LocalStruct
-// @is "$.index[*][?(@.docs=='foreign for local')].inner.trait.id" $ForeignTrait
+// @is "$.index[*][?(@.docs=='foreign for local')].inner.impl.for.resolved_path.id" $LocalStruct
+// @is "$.index[*][?(@.docs=='foreign for local')].inner.impl.trait.id" $ForeignTrait
 
-// @has "$.index[*][?(@.name=='LocalStruct')].inner.impls[*]" $impl
+// @has "$.index[*][?(@.name=='LocalStruct')].inner.struct.impls[*]" $impl
diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs
new file mode 100644
index 0000000..efa54d9
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility.rs
@@ -0,0 +1,26 @@
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// @!has '$.index[*][?(@.docs=="impl Foo priv")]'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
new file mode 100644
index 0000000..3c6fefc
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
@@ -0,0 +1,28 @@
+// compile-flags: --document-hidden-items
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
new file mode 100644
index 0000000..b98d1e4
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
@@ -0,0 +1,27 @@
+// compile-flags: --document-private-items
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs
index fa88b61..d2b0665 100644
--- a/tests/rustdoc-json/impls/import_from_private.rs
+++ b/tests/rustdoc-json/impls/import_from_private.rs
@@ -4,19 +4,19 @@
 #![no_core]
 
 mod bar {
-    // @set baz = "$.index[*][?(@.kind=='struct')].id"
+    // @set baz = "$.index[*][?(@.inner.struct)].id"
     pub struct Baz;
-    // @set impl = "$.index[*][?(@.kind=='impl')].id"
+    // @set impl = "$.index[*][?(@.inner.impl)].id"
     impl Baz {
-        // @set doit = "$.index[*][?(@.kind=='function')].id"
+        // @set doit = "$.index[*][?(@.inner.function)].id"
         pub fn doit() {}
     }
 }
 
-// @set import = "$.index[*][?(@.kind=='import')].id"
+// @set import = "$.index[*][?(@.inner.import)].id"
 pub use bar::Baz;
 
-// @is "$.index[*][?(@.kind=='module')].inner.items[*]" $import
-// @is "$.index[*][?(@.kind=='import')].inner.id" $baz
-// @is "$.index[*][?(@.kind=='struct')].inner.impls[*]" $impl
-// @is "$.index[*][?(@.kind=='impl')].inner.items[*]" $doit
+// @is "$.index[*].inner.module.items[*]" $import
+// @is "$.index[*].inner.import.id" $baz
+// @is "$.index[*].inner.struct.impls[*]" $impl
+// @is "$.index[*].inner.impl.items[*]" $doit
diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs
index 74f2f08..72352ce 100644
--- a/tests/rustdoc-json/impls/local_for_foreign.rs
+++ b/tests/rustdoc-json/impls/local_for_foreign.rs
@@ -3,7 +3,7 @@
 
 /// ForeignStruct id hack
 pub use foreign_struct::ForeignStruct as _;
-// @set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.id"
+// @set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id"
 
 pub trait LocalTrait {}
 // @set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id"
@@ -12,7 +12,7 @@
 impl LocalTrait for foreign_struct::ForeignStruct {}
 
 // @set impl = "$.index[*][?(@.docs=='local for foreign')].id"
-// @is "$.index[*][?(@.docs=='local for foreign')].inner.trait.id" $LocalTrait
-// @is "$.index[*][?(@.docs=='local for foreign')].inner.for.inner.id" $ForeignStruct
+// @is "$.index[*][?(@.docs=='local for foreign')].inner.impl.trait.id" $LocalTrait
+// @is "$.index[*][?(@.docs=='local for foreign')].inner.impl.for.resolved_path.id" $ForeignStruct
 
-// @is "$.index[*][?(@.name=='LocalTrait')].inner.implementations[*]" $impl
+// @is "$.index[*][?(@.name=='LocalTrait')].inner.trait.implementations[*]" $impl
diff --git a/tests/rustdoc-json/impls/local_for_local.rs b/tests/rustdoc-json/impls/local_for_local.rs
index 93dedb7e..37a7200 100644
--- a/tests/rustdoc-json/impls/local_for_local.rs
+++ b/tests/rustdoc-json/impls/local_for_local.rs
@@ -9,7 +9,7 @@
 /// impl
 impl Trait for Struct {}
 
-// @is "$.index[*][?(@.name=='Struct')].inner.impls[*]" $impl
-// @is "$.index[*][?(@.name=='Trait')].inner.implementations[*]" $impl
-// @is "$.index[*][?(@.docs=='impl')].inner.trait.id" $trait
-// @is "$.index[*][?(@.docs=='impl')].inner.for.inner.id" $struct
+// @is "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl
+// @is "$.index[*][?(@.name=='Trait')].inner.trait.implementations[*]" $impl
+// @is "$.index[*][?(@.docs=='impl')].inner.impl.trait.id" $trait
+// @is "$.index[*][?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct
diff --git a/tests/rustdoc-json/impls/local_for_local_primitive.rs b/tests/rustdoc-json/impls/local_for_local_primitive.rs
index 8383dcc..769dd3f 100644
--- a/tests/rustdoc-json/impls/local_for_local_primitive.rs
+++ b/tests/rustdoc-json/impls/local_for_local_primitive.rs
@@ -5,14 +5,13 @@
 // @set Local = "$.index[*][?(@.name=='Local')].id"
 pub trait Local {}
 
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.trait.id" $Local
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.for.kind" '"primitive"'
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.for.inner" '"bool"'
+// @is "$.index[*][?(@.docs=='Local for bool')].inner.impl.trait.id" $Local
+// @is "$.index[*][?(@.docs=='Local for bool')].inner.impl.for.primitive" '"bool"'
 /// Local for bool
 impl Local for bool {}
 
 // @set impl =  "$.index[*][?(@.docs=='Local for bool')].id"
-// @is "$.index[*][?(@.name=='Local')].inner.implementations[*]" $impl
+// @is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
 
 // FIXME(#101695): Test bool's `impls` include "Local for bool"
 // @has "$.index[*][?(@.name=='bool')]"
diff --git a/tests/rustdoc-json/impls/local_for_primitive.rs b/tests/rustdoc-json/impls/local_for_primitive.rs
index 7702a52..85278c0 100644
--- a/tests/rustdoc-json/impls/local_for_primitive.rs
+++ b/tests/rustdoc-json/impls/local_for_primitive.rs
@@ -2,6 +2,6 @@
 pub trait Local {}
 
 // @set impl = "$.index[*][?(@.docs=='local for bool')].id"
-// @is "$.index[*][?(@.name=='Local')].inner.implementations[*]" $impl
+// @is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
 /// local for bool
 impl Local for bool {}
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index 326dab8..dc28258 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -3,30 +3,27 @@
 #![feature(no_core)]
 #![no_core]
 
-// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].name"  \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
-// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
-// @count "$.index[*][?(@.name=='longest')].inner.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='longest')].inner.generics.where_predicates" []
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name"  \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
+// @count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" []
 
-// @count "$.index[*][?(@.name=='longest')].inner.decl.inputs[*]" 2
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][0]" '"l"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][0]" '"r"'
+// @count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"'
 
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.type" '{"inner": "str", "kind": "primitive"}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\"
 
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.type" '{"inner": "str", "kind": "primitive"}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\"
 
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.type" '{"inner": "str", "kind": "primitive"}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\"
 
 pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str {
     if l.len() > r.len() { l } else { r }
diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs
index e15a533..6e105b3 100644
--- a/tests/rustdoc-json/lifetime/outlives.rs
+++ b/tests/rustdoc-json/lifetime/outlives.rs
@@ -3,21 +3,19 @@
 #![feature(no_core)]
 #![no_core]
 
-// @count "$.index[*][?(@.name=='foo')].inner.generics.params[*]" 3
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates" []
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[1].name" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].name" '"T"'
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[0].kind.lifetime.outlives" []
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[1].kind.lifetime.outlives" [\"\'a\"]
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.default" null
-// @count "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[*]" 1
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.mutable" false
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.lifetime" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.mutable" false
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.type" '{"inner": "T", "kind": "generic"}'
+// @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" []
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].name" \"\'b\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].name" '"T"'
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].kind.lifetime.outlives" []
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].kind.lifetime.outlives" [\"\'a\"]
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null
+// @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
 pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {}
diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs
index fd03d92..b827929 100644
--- a/tests/rustdoc-json/methods/abi.rs
+++ b/tests/rustdoc-json/methods/abi.rs
@@ -8,47 +8,47 @@
 pub struct Foo;
 
 impl Foo {
-    // @is "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
+    // @is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
     pub fn abi_rust() {}
 
-    // @is "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
     pub extern "C" fn abi_c() {}
 
-    // @is "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
     pub extern "system" fn abi_system() {}
 
-    // @is "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
     pub extern "C-unwind" fn abi_c_unwind() {}
 
-    // @is "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
     pub extern "system-unwind" fn abi_system_unwind() {}
 
-    // @is "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+    // @is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
     pub extern "vectorcall" fn abi_vectorcall() {}
 
-    // @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+    // @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
     pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
 }
 
 pub trait Bar {
-    // @is "$.index[*][?(@.name=='trait_abi_rust')].inner.header.abi" \"Rust\"
+    // @is "$.index[*][?(@.name=='trait_abi_rust')].inner.function.header.abi" \"Rust\"
     fn trait_abi_rust() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='trait_abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
     extern "C" fn trait_abi_c() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='trait_abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
     extern "system" fn trait_abi_system() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
     extern "C-unwind" fn trait_abi_c_unwind() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
     extern "system-unwind" fn trait_abi_system_unwind() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+    // @is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
     extern "vectorcall" fn trait_abi_vectorcall() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+    // @is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
     extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {}
 }
diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs
index b9a5e56..65977bc 100644
--- a/tests/rustdoc-json/methods/qualifiers.rs
+++ b/tests/rustdoc-json/methods/qualifiers.rs
@@ -3,34 +3,34 @@
 pub struct Foo;
 
 impl Foo {
-    // @is "$.index[*][?(@.name=='const_meth')].inner.header.async" false
-    // @is "$.index[*][?(@.name=='const_meth')].inner.header.const"  true
-    // @is "$.index[*][?(@.name=='const_meth')].inner.header.unsafe" false
+    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false
+    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.const"  true
+    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false
     pub const fn const_meth() {}
 
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.async"  false
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.unsafe" false
+    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async"  false
+    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false
     pub fn nothing_meth() {}
 
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.async"  false
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.unsafe" true
+    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async"  false
+    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true
     pub unsafe fn unsafe_meth() {}
 
-    // @is "$.index[*][?(@.name=='async_meth')].inner.header.async"  true
-    // @is "$.index[*][?(@.name=='async_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='async_meth')].inner.header.unsafe" false
+    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.async"  true
+    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false
     pub async fn async_meth() {}
 
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.async"  true
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.unsafe" true
+    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async"  true
+    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true
     pub async unsafe fn async_unsafe_meth() {}
 
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.async"  false
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.const"  true
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.unsafe" true
+    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async"  false
+    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const"  true
+    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true
     pub const unsafe fn const_unsafe_meth() {}
 
     // It's impossible for a method to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs
index ee2d2ef..e012cfc 100644
--- a/tests/rustdoc-json/nested.rs
+++ b/tests/rustdoc-json/nested.rs
@@ -2,30 +2,31 @@
 // compile-flags: --crate-version 1.0.0
 
 // @is "$.crate_version" \"1.0.0\"
-// @is "$.index[*][?(@.name=='nested')].kind" \"module\"
-// @is "$.index[*][?(@.name=='nested')].inner.is_crate" true
+// @has "$.index[*][?(@.name=='nested')].inner.module"
+// @is "$.index[*][?(@.name=='nested')].inner.module.is_crate" true
 
 // @set l1_id = "$.index[*][?(@.name=='l1')].id"
-// @ismany "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id
+// @ismany "$.index[*][?(@.name=='nested')].inner.module.items[*]" $l1_id
 
-// @is "$.index[*][?(@.name=='l1')].kind" \"module\"
-// @is "$.index[*][?(@.name=='l1')].inner.is_crate" false
+// @has "$.index[*][?(@.name=='l1')].inner.module"
+// @is "$.index[*][?(@.name=='l1')].inner.module.is_crate" false
 pub mod l1 {
-    // @is "$.index[*][?(@.name=='l3')].kind" \"module\"
-    // @is "$.index[*][?(@.name=='l3')].inner.is_crate" false
+    // @has "$.index[*][?(@.name=='l3')].inner.module"
+    // @is "$.index[*][?(@.name=='l3')].inner.module.is_crate" false
     // @set l3_id = "$.index[*][?(@.name=='l3')].id"
     pub mod l3 {
 
-        // @is "$.index[*][?(@.name=='L4')].kind" \"struct\"
-        // @is "$.index[*][?(@.name=='L4')].inner.kind" \"unit\"
+        // @has "$.index[*][?(@.name=='L4')].inner.struct"
+        // @is "$.index[*][?(@.name=='L4')].inner.struct.kind" '"unit"'
         // @set l4_id = "$.index[*][?(@.name=='L4')].id"
-        // @ismany "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
+        // @ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id
         pub struct L4;
     }
-    // @is "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\"
-    // @is "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false
-    // @is "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id
-    // @set l4_use_id = "$.index[*][?(@.inner.source=='l3::L4')].id"
+    // @is "$.index[*][?(@.inner.import)].inner.import.glob" false
+    // @is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"'
+    // @is "$.index[*][?(@.inner.import)].inner.import.glob" false
+    // @is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id
+    // @set l4_use_id = "$.index[*][?(@.inner.import)].id"
     pub use l3::L4;
 }
-// @ismany "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id
+// @ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id
diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs
index ca5a008..cabee0b 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -16,9 +16,9 @@
 
 pub struct Wrapper<T_>(PhantomData<T_>);
 
-// @count "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
+// @count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
 pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait {}
diff --git a/tests/rustdoc-json/primitives/local_primitive.rs b/tests/rustdoc-json/primitives/local_primitive.rs
index 0cf479f..562c7e4 100644
--- a/tests/rustdoc-json/primitives/local_primitive.rs
+++ b/tests/rustdoc-json/primitives/local_primitive.rs
@@ -14,7 +14,7 @@
 // @set local_i32 = "$.index[*][?(@.name=='i32')].id"
 
 // @has "$.index[*][?(@.name=='local_primitive')]"
-// @ismany "$.index[*][?(@.name=='local_primitive')].inner.items[*]" $local_i32
+// @ismany "$.index[*][?(@.name=='local_primitive')].inner.module.items[*]" $local_i32
 // @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
 
 // Let's ensure the `prim_i32` module isn't present in the output JSON:
diff --git a/tests/rustdoc-json/primitives/primitive_impls.rs b/tests/rustdoc-json/primitives/primitive_impls.rs
index 85d179e..4b7b764 100644
--- a/tests/rustdoc-json/primitives/primitive_impls.rs
+++ b/tests/rustdoc-json/primitives/primitive_impls.rs
@@ -15,7 +15,7 @@
         self
     }
 
-    // @is "$.index[*][?(@.docs=='Only core can do this')].inner.items[*]" $identity
+    // @is "$.index[*][?(@.docs=='Only core can do this')].inner.impl.items[*]" $identity
 }
 
 // @set Trait = "$.index[*][?(@.name=='Trait')].id"
@@ -30,5 +30,5 @@
 
 // @set i32 = "$.index[*][?(@.docs=='i32')].id"
 // @is "$.index[*][?(@.docs=='i32')].name" '"i32"'
-// @is "$.index[*][?(@.docs=='i32')].inner.name" '"i32"'
-// @ismany "$.index[*][?(@.docs=='i32')].inner.impls[*]" $impl_i32 $impl_trait_for_i32
+// @is "$.index[*][?(@.docs=='i32')].inner.primitive.name" '"i32"'
+// @ismany "$.index[*][?(@.docs=='i32')].inner.primitive.impls[*]" $impl_i32 $impl_trait_for_i32
diff --git a/tests/rustdoc-json/primitives/primitive_type.rs b/tests/rustdoc-json/primitives/primitive_type.rs
index 8024044..5f251b3 100644
--- a/tests/rustdoc-json/primitives/primitive_type.rs
+++ b/tests/rustdoc-json/primitives/primitive_type.rs
@@ -1,22 +1,17 @@
 #![feature(never_type)]
 
 // @is "$.index[*][?(@.name=='PrimNever')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='PrimNever')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimNever')].inner.type.inner" \"never\"
+// @is "$.index[*][?(@.name=='PrimNever')].inner.typedef.type.primitive" \"never\"
 pub type PrimNever = !;
 
-// @is "$.index[*][?(@.name=='PrimStr')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimStr')].inner.type.inner" \"str\"
+// @is "$.index[*][?(@.name=='PrimStr')].inner.typedef.type.primitive" \"str\"
 pub type PrimStr = str;
 
-// @is "$.index[*][?(@.name=='PrimBool')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimBool')].inner.type.inner" \"bool\"
+// @is "$.index[*][?(@.name=='PrimBool')].inner.typedef.type.primitive" \"bool\"
 pub type PrimBool = bool;
 
-// @is "$.index[*][?(@.name=='PrimChar')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimChar')].inner.type.inner" \"char\"
+// @is "$.index[*][?(@.name=='PrimChar')].inner.typedef.type.primitive" \"char\"
 pub type PrimChar = char;
 
-// @is "$.index[*][?(@.name=='PrimU8')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimU8')].inner.type.inner" \"u8\"
+// @is "$.index[*][?(@.name=='PrimU8')].inner.typedef.type.primitive" \"u8\"
 pub type PrimU8 = u8;
diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs
index 5180a80..f8118b8 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -13,8 +13,8 @@
 // @!is "$.index[*][?(@.name=='checked_add')]" $local_crate_id
 // @!has "$.index[*][?(@.name=='is_ascii_uppercase')]"
 
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='my_i32')].inner.id" null
+// @is "$.index[*].inner.import[?(@.name=='my_i32')].id" null
 pub use i32 as my_i32;
 
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='u32')].inner.id" null
+// @is "$.index[*].inner.import[?(@.name=='u32')].id" null
 pub use u32;
diff --git a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
index 40b681d..1c5fed8 100644
--- a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
+++ b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
@@ -1,10 +1,11 @@
 // Regression Test for https://github.com/rust-lang/rust/issues/110138
 // aux-build: enum_with_discriminant.rs
+// ignore-tidy-linelength
 
 #[doc(inline)]
 pub extern crate enum_with_discriminant;
 
 // @!has '$.index[*][?(@.docs == "Should not be inlined")]'
-// @is '$.index[*][?(@.name == "enum_with_discriminant")].kind' '"extern_crate"'
+// @has '$.index[*][?(@.name == "enum_with_discriminant")].inner.extern_crate'
 // @set enum_with_discriminant = '$.index[*][?(@.name == "enum_with_discriminant")].id'
-// @is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.items[*]' $enum_with_discriminant
+// @is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.module.items[*]' $enum_with_discriminant
diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
index f076feb..37ca279 100644
--- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
+++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
@@ -7,5 +7,5 @@
 
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.kind=='module')].name" \"export_extern_crate_as_self\"
+// @is "$.index[*][?(@.inner.module)].name" \"export_extern_crate_as_self\"
 pub extern crate self as export_extern_crate_as_self; // Must be the same name as the crate already has
diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs
index 8efb94f..553ee79 100644
--- a/tests/rustdoc-json/reexport/extern_crate_glob.rs
+++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs
@@ -6,5 +6,6 @@
 pub use enum_with_discriminant::*;
 
 // @!has '$.index[*][?(@.docs == "Should not be inlined")]'
-// @set use = '$.index[*][?(@.inner.name == "enum_with_discriminant")].id'
-// @is '$.index[*][?(@.name == "extern_crate_glob")].inner.items[*]' $use
+// @is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\"
+// @set use = '$.index[*][?(@.inner.import)].id'
+// @is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use
diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs
index f91144d..dee35ba 100644
--- a/tests/rustdoc-json/reexport/glob_collision.rs
+++ b/tests/rustdoc-json/reexport/glob_collision.rs
@@ -3,26 +3,28 @@
 #![feature(no_core)]
 #![no_core]
 
-// @set m1 = "$.index[*][?(@.name == 'm1' && @.kind == 'module')].id"
-// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.items" []
-// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.is_stripped" true
+// @set m1 = "$.index[*][?(@.name == 'm1' && @.inner.module)].id"
+// @is "$.index[*][?(@.name == 'm1')].inner.module.items" []
+// @is "$.index[*][?(@.name == 'm1')].inner.module.is_stripped" true
 mod m1 {
     pub fn f() {}
 }
-// @set m2 = "$.index[*][?(@.name == 'm2' && @.kind == 'module')].id"
-// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.items" []
-// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.is_stripped" true
+// @set m2 = "$.index[*][?(@.name == 'm2' && @.inner.module)].id"
+// @is "$.index[*][?(@.name == 'm2')].inner.module.items" []
+// @is "$.index[*][?(@.name == 'm2')].inner.module.is_stripped" true
 mod m2 {
     pub fn f(_: u8) {}
 }
 
-// @set m1_use = "$.index[*][?(@.inner.name=='m1')].id"
-// @is "$.index[*][?(@.inner.name=='m1')].inner.id" $m1
-// @is "$.index[*][?(@.inner.name=='m1')].inner.glob" true
+// @set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id"
+// @is "$.index[*].inner.import[?(@.name=='m1')].id" $m1
+// @is "$.index[*].inner.import[?(@.name=='m1')].glob" true
+/// m1 re-export
 pub use m1::*;
-// @set m2_use = "$.index[*][?(@.inner.name=='m2')].id"
-// @is "$.index[*][?(@.inner.name=='m2')].inner.id" $m2
-// @is "$.index[*][?(@.inner.name=='m2')].inner.glob" true
+// @set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id"
+// @is "$.index[*].inner.import[?(@.name=='m2')].id" $m2
+// @is "$.index[*].inner.import[?(@.name=='m2')].glob" true
+/// m2 re-export
 pub use m2::*;
 
-// @ismany "$.index[*][?(@.inner.is_crate==true)].inner.items[*]" $m1_use $m2_use
+// @ismany "$.index[*].inner.module[?(@.is_crate==true)].items[*]" $m1_use $m2_use
diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs
index da68228..8b7150c 100644
--- a/tests/rustdoc-json/reexport/glob_empty_mod.rs
+++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs
@@ -1,8 +1,8 @@
 // Regression test for https://github.com/rust-lang/rust/issues/100973
 
-// @is "$.index[*][?(@.name=='m1' && @.kind == 'module')].inner.is_stripped" true
+// @is "$.index[*][?(@.name=='m1' && @.inner.module)].inner.module.is_stripped" true
 // @set m1 = "$.index[*][?(@.name=='m1')].id"
 mod m1 {}
 
-// @is "$.index[*][?(@.inner.name=='m1' && @.kind=='import')].inner.id" $m1
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $m1
 pub use m1::*;
diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs
index 7a1e8c1..78edfaf 100644
--- a/tests/rustdoc-json/reexport/glob_extern.rs
+++ b/tests/rustdoc-json/reexport/glob_extern.rs
@@ -3,8 +3,7 @@
 #![no_core]
 #![feature(no_core)]
 
-// @is "$.index[*][?(@.name=='mod1')].kind" \"module\"
-// @is "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
+// @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
 mod mod1 {
     extern "C" {
         // @set public_fn_id = "$.index[*][?(@.name=='public_fn')].id"
@@ -12,12 +11,12 @@
         // @!has "$.index[*][?(@.name=='private_fn')]"
         fn private_fn();
     }
-    // @ismany "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id
+    // @ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $public_fn_id
     // @set mod1_id = "$.index[*][?(@.name=='mod1')].id"
 }
 
-// @is "$.index[*][?(@.kind=='import')].inner.glob" true
-// @is "$.index[*][?(@.kind=='import')].inner.id" $mod1_id
-// @set use_id = "$.index[*][?(@.kind=='import')].id"
-// @ismany "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id
+// @is "$.index[*][?(@.inner.import)].inner.import.glob" true
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id
+// @set use_id = "$.index[*][?(@.inner.import)].id"
+// @ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id
 pub use mod1::*;
diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs
index 3a83a20..ae4e87d 100644
--- a/tests/rustdoc-json/reexport/glob_private.rs
+++ b/tests/rustdoc-json/reexport/glob_private.rs
@@ -3,11 +3,9 @@
 #![no_core]
 #![feature(no_core)]
 
-// @is "$.index[*][?(@.name=='mod1')].kind" \"module\"
-// @is "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
+// @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
 mod mod1 {
-    // @is "$.index[*][?(@.name=='mod2')].kind" \"module\"
-    // @is "$.index[*][?(@.name=='mod2')].inner.is_stripped" "true"
+    // @is "$.index[*][?(@.name=='mod2')].inner.module.is_stripped" "true"
     mod mod2 {
         // @set m2pub_id = "$.index[*][?(@.name=='Mod2Public')].id"
         pub struct Mod2Public;
@@ -16,7 +14,9 @@
         struct Mod2Private;
     }
 
-    // @set mod2_use_id = "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id"
+    // @set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id"
+    // @is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\"
+    /// Mod2 re-export
     pub use self::mod2::*;
 
     // @set m1pub_id = "$.index[*][?(@.name=='Mod1Public')].id"
@@ -25,9 +25,11 @@
     struct Mod1Private;
 }
 
-// @set mod1_use_id = "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id"
+// @set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id"
+// @is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\"
+/// Mod1 re-export
 pub use mod1::*;
 
-// @ismany "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
-// @ismany "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id
-// @ismany "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id
+// @ismany "$.index[*][?(@.name=='mod2')].inner.module.items[*]" $m2pub_id
+// @ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $m1pub_id $mod2_use_id
+// @ismany "$.index[*][?(@.name=='glob_private')].inner.module.items[*]" $mod1_use_id
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs
index 7b97ebf..f81445b 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs
@@ -7,10 +7,10 @@
     pub struct Foo;
 }
 
-// @has "$.index[*][?(@.kind=='import' && @.inner.source=='foo::Foo')]"
+// @has "$.index[*].inner[?(@.import.source=='foo::Foo')]"
 pub use foo::Foo;
 
 pub mod bar {
-    // @has "$.index[*][?(@.kind=='import' && @.inner.source=='crate::foo::Foo')]"
+    // @has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]"
     pub use crate::foo::Foo;
 }
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
index f6d932d..c5c41b2 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -3,18 +3,20 @@
 
 pub mod foo {
     // @set bar_id = "$.index[*][?(@.name=='Bar')].id"
-    // @ismany "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
+    // @ismany "$.index[*][?(@.name=='foo')].inner.module.items[*]" $bar_id
     pub struct Bar;
 }
 
-// @set root_import_id = "$.index[*][?(@.inner.source=='foo::Bar')].id"
-// @is "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id
-// @has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id
+// @set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id"
+// @is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id
+// @has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id
+/// Outer re-export
 pub use foo::Bar;
 
 pub mod baz {
-    // @set baz_import_id = "$.index[*][?(@.inner.source=='crate::foo::Bar')].id"
-    // @is "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id
-    // @ismany "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
+    // @set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id"
+    // @is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id
+    // @ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id
+    /// Inner re-export
     pub use crate::foo::Bar;
 }
diff --git a/tests/rustdoc-json/reexport/macro.rs b/tests/rustdoc-json/reexport/macro.rs
index b488210..ac0632b 100644
--- a/tests/rustdoc-json/reexport/macro.rs
+++ b/tests/rustdoc-json/reexport/macro.rs
@@ -9,7 +9,8 @@
     () => {};
 }
 
-// @set repro2_id = "$.index[*][?(@.inner.name=='repro2')].id"
+// @set repro2_id = "$.index[*][?(@.docs=='Re-export')].id"
+/// Re-export
 pub use crate::repro as repro2;
 
-// @ismany "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id
+// @ismany "$.index[*][?(@.name=='macro')].inner.module.items[*]" $repro_id $repro2_id
diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs
index 7b7600e..1c49f21 100644
--- a/tests/rustdoc-json/reexport/mod_not_included.rs
+++ b/tests/rustdoc-json/reexport/mod_not_included.rs
@@ -9,6 +9,6 @@
 
 pub use m1::x;
 
-// @has "$.index[*][?(@.name=='x' && @.kind=='function')]"
-// @has "$.index[*][?(@.kind=='import' && @.inner.name=='x')].inner.source" '"m1::x"'
+// @has "$.index[*][?(@.name=='x' && @.inner.function)]"
+// @has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"'
 // @!has "$.index[*][?(@.name=='m1')]"
diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
index 687a3b2..8c8152b 100644
--- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -11,18 +11,18 @@
 #[doc(inline)]
 
 // @set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id"
-// @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.id"
+// @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id"
 /// Hack A
 pub use foo::Foo;
 
 // @set bar_id = "$.index[*][?(@.name=='bar')].id"
 pub mod bar {
-    // @is "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id
+    // @is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id
     // @set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id"
-    // @ismany "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id
+    // @ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id
     /// Hack B
     pub use foo::Foo;
 }
 
-// @ismany "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id
-// @ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id
+// @ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id
+// @ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id
diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs
index 9858538..cdcbf2a 100644
--- a/tests/rustdoc-json/reexport/private_two_names.rs
+++ b/tests/rustdoc-json/reexport/private_two_names.rs
@@ -8,15 +8,19 @@
 
 // @!has "$.index[*][?(@.name=='style')]"
 mod style {
-    // @set color_struct_id = "$.index[*][?(@.kind=='struct' && @.name=='Color')].id"
+    // @set color_struct_id = "$.index[*][?(@.inner.struct && @.name=='Color')].id"
     pub struct Color;
 }
 
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id
-// @set color_export_id = "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id"
+// @is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id
+// @is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\"
+// @set color_export_id = "$.index[*][?(@.docs=='First re-export')].id"
+/// First re-export
 pub use style::Color;
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id
-// @set colour_export_id = "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id"
+// @is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id
+// @is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\"
+// @set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id"
+/// Second re-export
 pub use style::Color as Colour;
 
-// @ismany "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id
+// @ismany "$.index[*][?(@.name=='private_two_names')].inner.module.items[*]" $color_export_id $colour_export_id
diff --git a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
index 239b1a2..6107508 100644
--- a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
+++ b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
@@ -1,9 +1,9 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/102583>.
 
 // @set impl_S = "$.index[*][?(@.docs=='impl S')].id"
-// @has "$.index[*][?(@.name=='S')].inner.impls[*]" $impl_S
+// @has "$.index[*][?(@.name=='S')].inner.struct.impls[*]" $impl_S
 // @set is_present = "$.index[*][?(@.name=='is_present')].id"
-// @is "$.index[*][?(@.docs=='impl S')].inner.items[*]" $is_present
+// @is "$.index[*][?(@.docs=='impl S')].inner.impl.items[*]" $is_present
 // @!has "$.index[*][?(@.name=='hidden_impl')]"
 // @!has "$.index[*][?(@.name=='hidden_fn')]"
 
diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs
index 8fd850f..9114460 100644
--- a/tests/rustdoc-json/reexport/rename_private.rs
+++ b/tests/rustdoc-json/reexport/rename_private.rs
@@ -3,11 +3,11 @@
 #![no_core]
 #![feature(no_core)]
 
-// @!has "$.index[*][?(@.kind=='inner')]"
+// @!has "$.index[*][?(@.name=='inner')]"
 mod inner {
     // @has "$.index[*][?(@.name=='Public')]"
     pub struct Public;
 }
 
-// @is "$.index[*][?(@.kind=='import')].inner.name" \"NewName\"
+// @is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\"
 pub use inner::Public as NewName;
diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs
index e30907f..d0fd314 100644
--- a/tests/rustdoc-json/reexport/rename_public.rs
+++ b/tests/rustdoc-json/reexport/rename_public.rs
@@ -6,12 +6,13 @@
 // @set inner_id = "$.index[*][?(@.name=='inner')].id"
 pub mod inner {
     // @set public_id = "$.index[*][?(@.name=='Public')].id"
-    // @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    // @ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
     pub struct Public;
 }
-// @set import_id = "$.index[*][?(@.inner.name=='NewName')].id"
-// @!has "$.index[*][?(@.inner.name=='Public')]"
-// @is "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\"
+// @set import_id = "$.index[*][?(@.docs=='Re-export')].id"
+// @!has "$.index[*].inner[?(@.import.name=='Public')]"
+// @is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\"
+/// Re-export
 pub use inner::Public as NewName;
 
-// @ismany "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id
+// @ismany "$.index[*][?(@.name=='rename_public')].inner.module.items[*]" $inner_id $import_id
diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs
index 2314a4e..6a765b7 100644
--- a/tests/rustdoc-json/reexport/same_name_different_types.rs
+++ b/tests/rustdoc-json/reexport/same_name_different_types.rs
@@ -16,10 +16,10 @@
     pub fn Foo() {}
 }
 
-// @ismany "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
-// @ismany "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
+// @ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct
+// @ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct
 
-// @count "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')]" 2
+// @count "$.index[*].inner[?(@.import.name == 'Foo')]" 2
 pub use nested::Foo;
-// @count "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')]" 2
+// @count "$.index[*].inner[?(@.import.name == 'Bar')]" 2
 pub use Foo as Bar;
diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
index 880dbdc..a00547d 100644
--- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
+++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -11,11 +11,13 @@
     pub trait Trait {}
 }
 
-// @set export_id = "$.index[*][?(@.inner.name=='Trait')].id"
-// @is "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id
+// @set export_id = "$.index[*][?(@.docs=='First re-export')].id"
+// @is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id
+/// First re-export
 pub use inner::Trait;
-// @set reexport_id = "$.index[*][?(@.inner.name=='Reexport')].id"
-// @is "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id
+// @set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id"
+// @is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id
+/// Second re-export
 pub use inner::Trait as Reexport;
 
-// @ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id
+// @ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.module.items[*]" $reexport_id $export_id
diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs
index d058ce0..462efee 100644
--- a/tests/rustdoc-json/reexport/simple_private.rs
+++ b/tests/rustdoc-json/reexport/simple_private.rs
@@ -8,9 +8,9 @@
     pub struct Public;
 }
 
-// @is "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
-// @is "$.index[*][?(@.kind=='import')].inner.id" $pub_id
-// @set use_id = "$.index[*][?(@.kind=='import')].id"
+// @is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\"
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id
+// @set use_id = "$.index[*][?(@.inner.import)].id"
 pub use inner::Public;
 
-// @ismany "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id
+// @ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id
diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs
index e64a0dc..1373f96 100644
--- a/tests/rustdoc-json/reexport/simple_public.rs
+++ b/tests/rustdoc-json/reexport/simple_public.rs
@@ -7,12 +7,13 @@
 pub mod inner {
 
     // @set public_id = "$.index[*][?(@.name=='Public')].id"
-    // @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    // @ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
     pub struct Public;
 }
 
-// @set import_id = "$.index[*][?(@.inner.name=='Public')].id"
-// @is "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\"
+// @set import_id = "$.index[*][?(@.docs=='Outer')].id"
+// @is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\"
+/// Outer
 pub use inner::Public;
 
-// @ismany "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id
+// @ismany "$.index[*][?(@.name=='simple_public')].inner.module.items[*]" $import_id $inner_id
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index a8d1fae..0ce81b5 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -8,8 +8,8 @@
     pub struct Secret;
 }
 
-// @is "$.index[*][?(@.name=='get_secret')].kind" \"function\"
-// @is "$.index[*][?(@.name=='get_secret')].inner.decl.output.inner.name" \"secret::Secret\"
+// @has "$.index[*][?(@.name=='get_secret')].inner.function"
+// @is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\"
 pub fn get_secret() -> secret::Secret {
     secret::Secret
 }
diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs
index b86ab93..7772601 100644
--- a/tests/rustdoc-json/structs/plain_all_pub.rs
+++ b/tests/rustdoc-json/structs/plain_all_pub.rs
@@ -5,7 +5,7 @@
 
 // @set x = "$.index[*][?(@.name=='x')].id"
 // @set y = "$.index[*][?(@.name=='y')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[1]" $y
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 2
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" false
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false
diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs
index 7800b55..1ff4489 100644
--- a/tests/rustdoc-json/structs/plain_doc_hidden.rs
+++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs
@@ -6,6 +6,6 @@
 
 // @set x = "$.index[*][?(@.name=='x')].id"
 // @!has "$.index[*][?(@.name=='y')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs
index 1d01b8b..c037c02 100644
--- a/tests/rustdoc-json/structs/plain_empty.rs
+++ b/tests/rustdoc-json/structs/plain_empty.rs
@@ -1,5 +1,5 @@
 // @is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields_stripped" false
-// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields" []
+// @has "$.index[*][?(@.name=='PlainEmpty')].inner.struct"
+// @is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false
+// @is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" []
 pub struct PlainEmpty {}
diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs
index 9b77122..ff061be 100644
--- a/tests/rustdoc-json/structs/plain_pub_priv.rs
+++ b/tests/rustdoc-json/structs/plain_pub_priv.rs
@@ -4,6 +4,6 @@
 }
 
 // @set x = "$.index[*][?(@.name=='x')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
diff --git a/tests/rustdoc-json/structs/tuple.rs b/tests/rustdoc-json/structs/tuple.rs
index 6bdb753..16ab95e 100644
--- a/tests/rustdoc-json/structs/tuple.rs
+++ b/tests/rustdoc-json/structs/tuple.rs
@@ -1,4 +1,4 @@
 // @is "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Tuple')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" '[null, null]'
+// @has "$.index[*][?(@.name=='Tuple')].inner.struct"
+// @is "$.index[*][?(@.name=='Tuple')].inner.struct.kind.tuple" '[null, null]'
 pub struct Tuple(u32, String);
diff --git a/tests/rustdoc-json/structs/tuple_empty.rs b/tests/rustdoc-json/structs/tuple_empty.rs
index 0ad6a89..4d4af85 100644
--- a/tests/rustdoc-json/structs/tuple_empty.rs
+++ b/tests/rustdoc-json/structs/tuple_empty.rs
@@ -1,2 +1,2 @@
-// @is "$.index[*][?(@.name=='TupleUnit')].inner.kind.tuple" []
+// @is "$.index[*][?(@.name=='TupleUnit')].inner.struct.kind.tuple" []
 pub struct TupleUnit();
diff --git a/tests/rustdoc-json/structs/tuple_pub_priv.rs b/tests/rustdoc-json/structs/tuple_pub_priv.rs
index 9d5a1d1..a669ba1 100644
--- a/tests/rustdoc-json/structs/tuple_pub_priv.rs
+++ b/tests/rustdoc-json/structs/tuple_pub_priv.rs
@@ -7,7 +7,7 @@
 
 // @set field = "$.index[*][?(@.docs=='field')].id"
 
-// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[0]" null
-// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[1]" $field
-// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[2]" null
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.tuple[*]" 3
+// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[0]" null
+// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[1]" $field
+// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[2]" null
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[*]" 3
diff --git a/tests/rustdoc-json/structs/unit.rs b/tests/rustdoc-json/structs/unit.rs
index 2657097..640d3fb 100644
--- a/tests/rustdoc-json/structs/unit.rs
+++ b/tests/rustdoc-json/structs/unit.rs
@@ -1,4 +1,4 @@
 // @is "$.index[*][?(@.name=='Unit')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Unit')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='Unit')].inner.kind" \"unit\"
+// @has "$.index[*][?(@.name=='Unit')].inner.struct"
+// @is "$.index[*][?(@.name=='Unit')].inner.struct.kind" \"unit\"
 pub struct Unit;
diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs
index 0047480..d721cbd 100644
--- a/tests/rustdoc-json/structs/with_generics.rs
+++ b/tests/rustdoc-json/structs/with_generics.rs
@@ -1,13 +1,13 @@
 use std::collections::HashMap;
 
 // @is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type.bounds" []
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type.bounds" []
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields_stripped" true
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields" []
+// @has "$.index[*][?(@.name=='WithGenerics')].inner.struct"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].name" \"T\"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" []
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" []
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" []
 pub struct WithGenerics<T, U> {
     stuff: Vec<T>,
     things: HashMap<U, U>,
diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs
index 9c5a37f..e0285a9 100644
--- a/tests/rustdoc-json/structs/with_primitives.rs
+++ b/tests/rustdoc-json/structs/with_primitives.rs
@@ -1,9 +1,11 @@
+// ignore-tidy-linelength
+
 // @is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields_stripped" true
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields" []
+// @has "$.index[*][?(@.name=='WithPrimitives')].inner.struct"
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" []
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" []
 pub struct WithPrimitives<'a> {
     num: u32,
     s: &'a str,
diff --git a/tests/rustdoc-json/traits/has_body.rs b/tests/rustdoc-json/traits/has_body.rs
index a57cb97..219e2d9 100644
--- a/tests/rustdoc-json/traits/has_body.rs
+++ b/tests/rustdoc-json/traits/has_body.rs
@@ -1,21 +1,21 @@
 // @has "$.index[*][?(@.name=='Foo')]"
 pub trait Foo {
-    // @is "$.index[*][?(@.name=='no_self')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='no_self')].inner.function.has_body" false
     fn no_self();
-    // @is "$.index[*][?(@.name=='move_self')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='move_self')].inner.function.has_body" false
     fn move_self(self);
-    // @is "$.index[*][?(@.name=='ref_self')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='ref_self')].inner.function.has_body" false
     fn ref_self(&self);
 
-    // @is "$.index[*][?(@.name=='no_self_def')].inner.has_body" true
+    // @is "$.index[*][?(@.name=='no_self_def')].inner.function.has_body" true
     fn no_self_def() {}
-    // @is "$.index[*][?(@.name=='move_self_def')].inner.has_body" true
+    // @is "$.index[*][?(@.name=='move_self_def')].inner.function.has_body" true
     fn move_self_def(self) {}
-    // @is "$.index[*][?(@.name=='ref_self_def')].inner.has_body" true
+    // @is "$.index[*][?(@.name=='ref_self_def')].inner.function.has_body" true
     fn ref_self_def(&self) {}
 }
 
 pub trait Bar: Clone {
-    // @is "$.index[*][?(@.name=='method')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='method')].inner.function.has_body" false
     fn method(&self, param: usize);
 }
diff --git a/tests/rustdoc-json/traits/implementors.rs b/tests/rustdoc-json/traits/implementors.rs
index db3fe5d..7d351ad 100644
--- a/tests/rustdoc-json/traits/implementors.rs
+++ b/tests/rustdoc-json/traits/implementors.rs
@@ -2,18 +2,18 @@
 #![no_core]
 
 // @set wham = "$.index[*][?(@.name=='Wham')].id"
-// @count "$.index[*][?(@.name=='Wham')].inner.implementations[*]" 1
-// @set gmWham = "$.index[*][?(@.name=='Wham')].inner.implementations[0]"
+// @count "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" 1
+// @set gmWham = "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]"
 pub trait Wham {}
 
-// @count "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[*]" 1
-// @is "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[0]" $gmWham
+// @count "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" 1
+// @is "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[0]" $gmWham
 // @set gm = "$.index[*][?(@.name=='Wham')].id"
 
 // jsonpath_lib isnt expressive enough (for now) to get the "impl" item, so we
 // just check it isn't pointing to the type, but when you port to jsondocck-ng
 // check what the impl item is
-// @!is "$.index[*][?(@.name=='Wham')].inner.implementations[0]" $gm
+// @!is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]" $gm
 pub struct GeorgeMichael {}
 
 impl Wham for GeorgeMichael {}
diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs
index 4048fdd..2123ac4 100644
--- a/tests/rustdoc-json/traits/supertrait.rs
+++ b/tests/rustdoc-json/traits/supertrait.rs
@@ -8,19 +8,19 @@
 pub trait Loud {}
 
 // @set very_loud_id = "$.index[*][?(@.name=='VeryLoud')].id"
-// @count "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1
-// @is    "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.id" $loud_id
+// @count "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[*]" 1
+// @is    "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[0].trait_bound.trait.id" $loud_id
 pub trait VeryLoud: Loud {}
 
 // @set sounds_good_id = "$.index[*][?(@.name=='SoundsGood')].id"
 pub trait SoundsGood {}
 
-// @count "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2
-// @is    "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.id" $very_loud_id
-// @is    "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.id" $sounds_good_id
+// @count "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[*]" 2
+// @is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[0].trait_bound.trait.id" $very_loud_id
+// @is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[1].trait_bound.trait.id" $sounds_good_id
 pub trait MetalBand: VeryLoud + SoundsGood {}
 
-// @count "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2
-// @is    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.id" $very_loud_id
-// @is    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.id" $sounds_good_id
+// @count "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[*]" 2
+// @is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[1].trait_bound.trait.id" $very_loud_id
+// @is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[0].trait_bound.trait.id" $sounds_good_id
 pub trait DnabLatem: SoundsGood + VeryLoud {}
diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs
index 35db929..4fcc26f 100644
--- a/tests/rustdoc-json/traits/trait_alias.rs
+++ b/tests/rustdoc-json/traits/trait_alias.rs
@@ -4,24 +4,24 @@
 #![feature(trait_alias)]
 
 // @set Orig = "$.index[*][?(@.name == 'Orig')].id"
-// @is "$.index[*][?(@.name == 'Orig')].kind" '"trait"'
+// @has "$.index[*][?(@.name == 'Orig')].inner.trait"
 pub trait Orig<T> {}
 
 // @set Alias = "$.index[*][?(@.name == 'Alias')].id"
-// @is "$.index[*][?(@.name == 'Alias')].kind" '"trait_alias"'
-// @is "$.index[*][?(@.name == 'Alias')].inner.generics" '{"params": [], "where_predicates": []}'
-// @count "$.index[*][?(@.name == 'Alias')].inner.params[*]" 1
-// @is "$.index[*][?(@.name == 'Alias')].inner.params[0].trait_bound.trait.id" $Orig
-// @is "$.index[*][?(@.name == 'Alias')].inner.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.inner" '"i32"'
+// @has "$.index[*][?(@.name == 'Alias')].inner.trait_alias"
+// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.generics" '{"params": [], "where_predicates": []}'
+// @count "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[*]" 1
+// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.id" $Orig
+// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.primitive" '"i32"'
 pub trait Alias = Orig<i32>;
 
 pub struct Struct;
 
 impl Orig<i32> for Struct {}
 
-// @is "$.index[*][?(@.name=='takes_alias')].inner.decl.inputs[0][1].kind" '"impl_trait"'
-// @is "$.index[*][?(@.name=='takes_alias')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $Alias
-// @is "$.index[*][?(@.name=='takes_alias')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
+// @has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait"
+// @is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
+// @is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
 pub fn takes_alias(_: impl Alias) {}
 // FIXME: Should the trait be mentioned in both the decl and generics?
 
diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs
index eaf2492..e5ee60f 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -1,46 +1,46 @@
 // ignore-tidy-linelength
 use std::fmt::Debug;
 
-// @count "$.index[*][?(@.name=='dyn')].inner.items[*]" 3
+// @count "$.index[*][?(@.name=='dyn')].inner.module.items[*]" 3
 // @set sync_int_gen = "$.index[*][?(@.name=='SyncIntGen')].id"
 // @set ref_fn       = "$.index[*][?(@.name=='RefFn')].id"
 // @set weird_order  = "$.index[*][?(@.name=='WeirdOrder')].id"
-// @ismany "$.index[*][?(@.name=='dyn')].inner.items[*]" $sync_int_gen $ref_fn $weird_order
+// @ismany "$.index[*][?(@.name=='dyn')].inner.module.items[*]" $sync_int_gen $ref_fn $weird_order
 
-// @is    "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
-// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"dyn_trait\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.lifetime" \"\'static\"
-// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[*]" 3
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Fn"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Send"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.name" '"Sync"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
+// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.generics" '{"params": [], "where_predicates": []}'
+// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.name" \"Box\"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.bindings" []
+// @count "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args" 1
+// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\"
+// @count "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" []
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" []
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" []
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"'
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"'
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"'
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}'
 pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
 
-// @is "$.index[*][?(@.name=='RefFn')].kind" \"typedef\"
-// @is "$.index[*][?(@.name=='RefFn')].inner.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.mutable" 'false'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.lifetime" "\"'a\""
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.kind" '"dyn_trait"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null
-// @count "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.name" '"Fn"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].inner.lifetime" "\"'b\""
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.inner.lifetime" "\"'b\""
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.mutable" 'false'
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.lifetime" "\"'a\""
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.lifetime" null
+// @count "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[*]" 1
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\""
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\""
 pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
 
-// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Send"'
-// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Debug"'
+// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"'
+// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"'
 pub type WeirdOrder = Box<dyn Send + Debug>;
diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs
index d287d5e..c30146c 100644
--- a/tests/rustdoc-json/type/extern.rs
+++ b/tests/rustdoc-json/type/extern.rs
@@ -6,5 +6,4 @@
 }
 
 // @is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"'
-// @is "$.index[*][?(@.docs=='No inner information')].kind" '"foreign_type"'
-// @!has "$.index[*][?(@.docs=='No inner information')].inner"
+// @is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\"
diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs
index d7216ec..424c5dc 100644
--- a/tests/rustdoc-json/type/fn_lifetime.rs
+++ b/tests/rustdoc-json/type/fn_lifetime.rs
@@ -1,27 +1,26 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\"
+// @has "$.index[*][?(@.name=='GenericFn')].inner.typedef"
 
-// @ismany "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
-// @has    "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime"
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\"
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+// @ismany "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].name" \"\'a\"
+// @has    "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].kind.lifetime"
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].kind.lifetime.outlives[*]" 0
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.where_predicates[*]" 0
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.generic_params[*]" 0
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.inputs[*]" 1
+// @is     "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+// @is     "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
 
 pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;
 
-// @is    "$.index[*][?(@.name=='ForAll')].kind" \"typedef\"
-// @count "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\"
-// @has   "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime"
-// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+// @has    "$.index[*][?(@.name=='ForAll')].inner.typedef"
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.generics.params[*]" 0
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.generics.where_predicates[*]" 0
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*]" 1
+// @is    "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].name" \"\'a\"
+// @has   "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].kind.lifetime"
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.inputs[*]" 1
+// @is    "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+// @is    "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
 pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs
index 9c6d454..b464287 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -9,25 +9,25 @@
 // @set my_error = "$.index[*][?(@.name=='MyError')].id"
 pub struct MyError {}
 
-// @is    "$.index[*][?(@.name=='MyResult')].kind" \"typedef\"
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\"
-// @has   "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type"
-// @has   "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type"
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" []
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\"
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef"
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.where_predicates[*]" 0
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[*]" 2
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].name" \"T\"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].name" \"E\"
+// @has   "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type"
+// @has   "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type"
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type.bounds[*]" 0
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.bounds[*]" 0
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type.default" null
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path.id" $my_error
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path.name" \"MyError\"
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.id" $result
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.name" \"Result\"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.bindings" []
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.generic"
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[1].type.generic"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\"
 pub type MyResult<T, E = MyError> = Result<T, E>;
diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs
index 2c4ee00..f7ac878 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -1,7 +1,7 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F","kind": "generic"}'
-// @is "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+// @is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.type" '{"generic": "F"}'
+// @is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
 pub fn genfn<F>(f: F)
 where
     for<'a, 'b> F: Fn(&'a i32, &'b i32),
@@ -10,14 +10,12 @@
     f(&zero, &zero);
 }
 
-// @is "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
-// @is "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.kind" '"dyn_trait"'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null
-// @count "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.name" '"Fn"'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
+// @count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
 pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
     let zero = 0;
     f(&zero, &zero);
diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs
new file mode 100644
index 0000000..64c6c53
--- /dev/null
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+#![feature(inherent_associated_types)]
+#![feature(no_core)]
+#![allow(incomplete_features)]
+#![no_core]
+
+// @set OwnerMetadata = '$.index[*][?(@.name=="OwnerMetadata")].id'
+pub struct OwnerMetadata;
+// @set Owner = '$.index[*][?(@.name=="Owner")].id'
+pub struct Owner;
+
+pub fn create() -> Owner::Metadata {
+    OwnerMetadata
+}
+// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"'
+// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null
+// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner
+
+/// impl
+impl Owner {
+    /// iat
+    pub type Metadata = OwnerMetadata;
+}
+// @set iat = '$.index[*][?(@.docs=="iat")].id'
+// @is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat
+// @is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
new file mode 100644
index 0000000..2e9b13d
--- /dev/null
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -0,0 +1,19 @@
+// ignore-tidy-linelength
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
+pub struct Carrier<'a>(&'a ());
+
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.generic_params[*].name' \""'b"\"
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.trait' null
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
+
+pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
+
+impl<'a> Carrier<'a> {
+    pub type Focus<T> = &'a mut T;
+}
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
new file mode 100644
index 0000000..942e323
--- /dev/null
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -0,0 +1,32 @@
+// ignore-tidy-linelength
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
+pub struct Parametrized<T>(T);
+
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.id' $Parametrized
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.name' '"Proj"'
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.trait' null
+pub type Test = Parametrized<i32>::Proj;
+
+/// param_bool
+impl Parametrized<bool> {
+    /// param_bool_proj
+    pub type Proj = ();
+}
+
+/// param_i32
+impl Parametrized<i32> {
+    /// param_i32_proj
+    pub type Proj = String;
+}
+
+// @set param_bool = '$.index[*][?(@.docs=="param_bool")].id'
+// @set param_i32 = '$.index[*][?(@.docs=="param_i32")].id'
+// @set param_bool_proj = '$.index[*][?(@.docs=="param_bool_proj")].id'
+// @set param_i32_proj = '$.index[*][?(@.docs=="param_i32_proj")].id'
+
+// @is '$.index[*][?(@.docs=="param_bool")].inner.impl.items[*]' $param_bool_proj
+// @is '$.index[*][?(@.docs=="param_i32")].inner.impl.items[*]' $param_i32_proj
diff --git a/tests/rustdoc-json/unions/impl.rs b/tests/rustdoc-json/unions/impl.rs
index 4454a69..7456892 100644
--- a/tests/rustdoc-json/unions/impl.rs
+++ b/tests/rustdoc-json/unions/impl.rs
@@ -1,15 +1,15 @@
 #![no_std]
 
 // @is "$.index[*][?(@.name=='Ux')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Ux')].kind" \"union\"
+// @has "$.index[*][?(@.name=='Ux')].inner.union"
 pub union Ux {
     a: u32,
     b: u64
 }
 
 // @is "$.index[*][?(@.name=='Num')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Num')].kind" \"trait\"
+// @has "$.index[*][?(@.name=='Num')].inner.trait"
 pub trait Num {}
 
-// @count "$.index[*][?(@.name=='Ux')].inner.impls" 1
+// @count "$.index[*][?(@.name=='Ux')].inner.union.impls" 1
 impl Num for Ux {}
diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs
index c9df2b8..22b70e1 100644
--- a/tests/rustdoc-json/unions/union.rs
+++ b/tests/rustdoc-json/unions/union.rs
@@ -1,6 +1,6 @@
 // @has "$.index[*][?(@.name=='Union')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Union')].kind" \"union\"
-// @!has "$.index[*][?(@.name=='Union')].inner.struct_type"
+// @has "$.index[*][?(@.name=='Union')].inner.union"
+// @!has "$.index[*][?(@.name=='Union')].inner.union.struct_type"
 // @set Union = "$.index[*][?(@.name=='Union')].id"
 pub union Union {
     int: i32,
@@ -8,8 +8,8 @@
 }
 
 
-// @is "$.index[*][?(@.name=='make_int_union')].inner.decl.output.kind" '"resolved_path"'
-// @is "$.index[*][?(@.name=='make_int_union')].inner.decl.output.inner.id" $Union
+// @has "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path"
+// @is "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path.id" $Union
 pub fn make_int_union(int: i32) -> Union {
     Union { int }
 }
diff --git a/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
new file mode 100644
index 0000000..4e74278
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
@@ -0,0 +1,10 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/111189>.
+// This test ensures that it doesn't crash.
+
+#![deny(warnings)]
+
+/// #[rustfmt::skip]
+//~^ ERROR unresolved link to `rustfmt::skip`
+/// #[clippy::whatever]
+//~^ ERROR unresolved link to `clippy::whatever`
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr
new file mode 100644
index 0000000..edd3dfa
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr
@@ -0,0 +1,21 @@
+error: unresolved link to `rustfmt::skip`
+  --> $DIR/issue-111189-resolution-ice.rs:6:7
+   |
+LL | /// #[rustfmt::skip]
+   |       ^^^^^^^^^^^^^ no item named `rustfmt` in scope
+   |
+note: the lint level is defined here
+  --> $DIR/issue-111189-resolution-ice.rs:4:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
+
+error: unresolved link to `clippy::whatever`
+  --> $DIR/issue-111189-resolution-ice.rs:8:7
+   |
+LL | /// #[clippy::whatever]
+   |       ^^^^^^^^^^^^^^^^ no item named `clippy` in scope
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs
index f1ad7c8..e99cd1f 100644
--- a/tests/rustdoc-ui/unescaped_backticks.rs
+++ b/tests/rustdoc-ui/unescaped_backticks.rs
@@ -340,3 +340,15 @@
     /// level changes.
     pub mod tracing_macro {}
 }
+
+/// Regression test for <https://github.com/rust-lang/rust/issues/111117>
+pub mod trillium_server_common {
+    /// One-indexed, because the first CloneCounter is included. If you don't
+    /// want the original to count, construct a [``CloneCounterObserver`]
+    /// instead and use [`CloneCounterObserver::counter`] to increment.
+    //~^ ERROR unescaped backtick
+    pub struct CloneCounter;
+
+    /// This is used by the above.
+    pub struct CloneCounterObserver;
+}
diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr
index e629dbc..bf1f188 100644
--- a/tests/rustdoc-ui/unescaped_backticks.stderr
+++ b/tests/rustdoc-ui/unescaped_backticks.stderr
@@ -342,6 +342,18 @@
            to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
 
 error: unescaped backtick
+  --> $DIR/unescaped_backticks.rs:348:56
+   |
+LL |     /// instead and use [`CloneCounterObserver::counter`] to increment.
+   |                                                        ^
+   |
+   = help: the opening or closing backtick of an inline code may be missing
+help: if you meant to use a literal backtick, escape it
+   |
+LL |     /// instead and use [`CloneCounterObserver::counter\`] to increment.
+   |                                                        +
+
+error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:11:5
    |
 LL | /// `
@@ -955,5 +967,5 @@
 LL | /// | table`( | )\`body |
    |                  +
 
-error: aborting due to 63 previous errors
+error: aborting due to 64 previous errors
 
diff --git a/tests/rustdoc/nested-items-issue-111415.rs b/tests/rustdoc/nested-items-issue-111415.rs
new file mode 100644
index 0000000..9b7688c
--- /dev/null
+++ b/tests/rustdoc/nested-items-issue-111415.rs
@@ -0,0 +1,36 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/111415>.
+// This test ensures that only impl blocks are documented in bodies.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// Checking there are only three sections.
+// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Traits'
+// Checking that there are only three items.
+// @count - '//*[@id="main-content"]//*[@class="item-name"]' 3
+// @has - '//*[@id="main-content"]//a[@href="struct.Bar.html"]' 'Bar'
+// @has - '//*[@id="main-content"]//a[@href="fn.foo.html"]' 'foo'
+// @has - '//*[@id="main-content"]//a[@href="trait.Foo.html"]' 'Foo'
+
+// Now checking that the `foo` method is visible in `Bar` page.
+// @has 'foo/struct.Bar.html'
+// @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub fn foo()'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar()'
+pub struct Bar;
+
+pub trait Foo {
+    fn bar() {}
+}
+
+pub fn foo() {
+    pub mod inaccessible {}
+    pub fn inner() {}
+    pub const BAR: u32 = 0;
+    impl Bar {
+        pub fn foo() {}
+    }
+    impl Foo for Bar {}
+}
diff --git a/tests/rustdoc/test-strikethrough.rs b/tests/rustdoc/test-strikethrough.rs
index c785572..5816215 100644
--- a/tests/rustdoc/test-strikethrough.rs
+++ b/tests/rustdoc/test-strikethrough.rs
@@ -1,6 +1,13 @@
 #![crate_name = "foo"]
 
-// @has foo/fn.f.html
-// @has - //del "Y"
-/// ~~Y~~
+// Test that strikethrough works with single and double tildes and that it shows up on
+// the item's dedicated page as well as the parent module's summary of items.
+
+// @has foo/index.html //del 'strike'
+// @has foo/index.html //del 'through'
+
+// @has foo/fn.f.html //del 'strike'
+// @has foo/fn.f.html //del 'through'
+
+/// ~~strike~~ ~through~
 pub fn f() {}
diff --git a/tests/ui/associated-inherent-types/inference.rs b/tests/ui/associated-inherent-types/inference.rs
index 7d6d260..ebd8e1d 100644
--- a/tests/ui/associated-inherent-types/inference.rs
+++ b/tests/ui/associated-inherent-types/inference.rs
@@ -3,7 +3,7 @@
 
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::convert::identity;
 
diff --git a/tests/ui/associated-inherent-types/issue-111879-0.rs b/tests/ui/associated-inherent-types/issue-111879-0.rs
new file mode 100644
index 0000000..e37f7d3
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-0.rs
@@ -0,0 +1,14 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that we don't crash when printing inherent projections in diagnostics.
+
+pub struct Carrier<'a>(&'a ());
+
+pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
+
+impl<'a> Carrier<'a> {
+    pub type Focus<T> = &'a mut User; //~ ERROR overflow evaluating associated type
+}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111879-0.stderr b/tests/ui/associated-inherent-types/issue-111879-0.stderr
new file mode 100644
index 0000000..7bdbad4
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-0.stderr
@@ -0,0 +1,8 @@
+error: overflow evaluating associated type `Carrier<'b>::Focus<i32>`
+  --> $DIR/issue-111879-0.rs:11:25
+   |
+LL |     pub type Focus<T> = &'a mut User;
+   |                         ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-inherent-types/issue-111879-1.rs b/tests/ui/associated-inherent-types/issue-111879-1.rs
new file mode 100644
index 0000000..7acc4f9
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-1.rs
@@ -0,0 +1,12 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that we don't crash when printing inherent projections in diagnostics.
+
+struct Foo<T>(T);
+
+impl<'a> Foo<fn(&'a ())> {
+    type Assoc = &'a ();
+}
+
+fn main(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {} //~ ERROR `main` function has wrong type
diff --git a/tests/ui/associated-inherent-types/issue-111879-1.stderr b/tests/ui/associated-inherent-types/issue-111879-1.stderr
new file mode 100644
index 0000000..689b45e
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-1.stderr
@@ -0,0 +1,12 @@
+error[E0580]: `main` function has wrong type
+  --> $DIR/issue-111879-1.rs:12:1
+   |
+LL | fn main(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected fn pointer `fn()`
+              found fn pointer `fn(for<'a> fn(Foo<fn(&'a ())>::Assoc))`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0580`.
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.rs b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
new file mode 100644
index 0000000..19bcfe3
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait, return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use
+
+trait IntFactory {
+    fn stream(&self) -> impl Iterator<Item = i32>;
+}
+trait SendIntFactory: IntFactory<stream(): Send> + Send {}
+
+fn main() {}
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr
new file mode 100644
index 0000000..c8cec49
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/supertrait-bound.rs:3:49
+   |
+LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)]
+   |                                                 ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/attr-bad-crate-attr.rc b/tests/ui/attr-bad-crate-attr.rs
similarity index 100%
rename from tests/ui/attr-bad-crate-attr.rc
rename to tests/ui/attr-bad-crate-attr.rs
diff --git a/tests/ui/attr-bad-crate-attr.stderr b/tests/ui/attr-bad-crate-attr.stderr
new file mode 100644
index 0000000..ff420ee
--- /dev/null
+++ b/tests/ui/attr-bad-crate-attr.stderr
@@ -0,0 +1,8 @@
+error: expected item after attributes
+  --> $DIR/attr-bad-crate-attr.rs:4:1
+   |
+LL | #[attr = "val"] // Unterminated
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
index 9163c8e..60128c9 100644
--- a/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
+++ b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
@@ -1,7 +1,7 @@
 // Check that closure captures for slice patterns are inferred correctly
 
 #![allow(unused_variables)]
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 // run-pass
 
diff --git a/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
index a88b323..78e965c 100644
--- a/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
+++ b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(unused_mut)]
 #![allow(unused_variables)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 // pretty-expanded FIXME #23616
 
 struct A { a: isize, b: Box<isize> }
diff --git a/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
index 40c6bfe..9acb1ec 100644
--- a/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
+++ b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
@@ -1,7 +1,7 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 struct A { a: isize, b: Box<isize> }
 
diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
new file mode 100644
index 0000000..addbe5d
--- /dev/null
+++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Zdrop-tracking-mir
+// edition:2021
+
+use std::future::Future;
+
+trait Client {
+    type Connecting<'a>: Future + Send
+    where
+        Self: 'a;
+
+    fn connect(&'_ self) -> Self::Connecting<'a>;
+    //~^ ERROR use of undeclared lifetime name `'a`
+}
+
+fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
+where
+    C: Client + Send + Sync,
+{
+    async move { c.connect().await }
+    //~^ ERROR `C` does not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
new file mode 100644
index 0000000..53abe3d
--- /dev/null
+++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
@@ -0,0 +1,24 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/erase-error-in-mir-drop-tracking.rs:11:46
+   |
+LL |     fn connect(&'_ self) -> Self::Connecting<'a>;
+   |                                              ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn connect<'a>(&'_ self) -> Self::Connecting<'a>;
+   |               ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | trait Client<'a> {
+   |             ++++
+
+error: `C` does not live long enough
+  --> $DIR/erase-error-in-mir-drop-tracking.rs:19:5
+   |
+LL |     async move { c.connect().await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/cfg/cfg-stmt-recovery.rs b/tests/ui/cfg/cfg-stmt-recovery.rs
new file mode 100644
index 0000000..2e0839d
--- /dev/null
+++ b/tests/ui/cfg/cfg-stmt-recovery.rs
@@ -0,0 +1,13 @@
+// Verify that we do not ICE when failing to parse a statement in `cfg_eval`.
+
+#![feature(cfg_eval)]
+#![feature(stmt_expr_attributes)]
+
+#[cfg_eval]
+fn main() {
+    #[cfg_eval]
+    let _ = #[cfg(FALSE)] 0;
+    //~^ ERROR removing an expression is not supported in this position
+    //~| ERROR expected expression, found `;`
+    //~| ERROR removing an expression is not supported in this position
+}
diff --git a/tests/ui/cfg/cfg-stmt-recovery.stderr b/tests/ui/cfg/cfg-stmt-recovery.stderr
new file mode 100644
index 0000000..cb15e21
--- /dev/null
+++ b/tests/ui/cfg/cfg-stmt-recovery.stderr
@@ -0,0 +1,20 @@
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-stmt-recovery.rs:9:13
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |             ^^^^^^^^^^^^^
+
+error: expected expression, found `;`
+  --> $DIR/cfg-stmt-recovery.rs:9:28
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |                            ^ expected expression
+
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-stmt-recovery.rs:9:13
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
index 56f5ac4..41b09ba 100644
--- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
+++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
@@ -1,6 +1,7 @@
 // edition:2021
 
 #![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
 
 // Should capture the discriminant since a variant of a multivariant enum is
 // mentioned in the match arm; the discriminant is captured by the closure regardless
@@ -8,9 +9,6 @@
 fn test_1_should_capture() {
     let variant = Some(2229);
     let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-
     || {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
@@ -29,8 +27,6 @@
 fn test_2_should_not_capture() {
     let variant = Some(2229);
     let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     || {
     //~^ First Pass analysis includes:
         match variant {
@@ -50,8 +46,6 @@
 fn test_3_should_not_capture_single_variant() {
     let variant = SingleVariant::Points(1);
     let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     || {
     //~^ First Pass analysis includes:
         match variant {
@@ -66,8 +60,6 @@
 fn test_6_should_capture_single_variant() {
     let variant = SingleVariant::Points(1);
     let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     || {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
@@ -88,8 +80,6 @@
 fn test_4_should_not_capture_array() {
     let array: [i32; 3] = [0; 3];
     let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     || {
     //~^ First Pass analysis includes:
         match array {
@@ -112,8 +102,6 @@
 fn test_5_should_capture_multi_variant() {
     let variant = MVariant::A;
     let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     || {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
@@ -127,6 +115,62 @@
     c();
 }
 
+// Even though all patterns are wild, we need to read the discriminant
+// in order to test the slice length
+fn test_7_should_capture_slice_len() {
+    let slice: &[i32] = &[1, 2, 3];
+    let c =  #[rustc_capture_analysis]
+    || {
+    //~^ First Pass analysis includes:
+    //~| Min Capture analysis includes:
+        match slice {
+            //~^ NOTE: Capturing slice[] -> ImmBorrow
+            //~| NOTE: Min Capture slice[] -> ImmBorrow
+            [_,_,_] => {},
+            _ => {}
+        }
+    };
+    c();
+    let c =  #[rustc_capture_analysis]
+    || {
+    //~^ First Pass analysis includes:
+    //~| Min Capture analysis includes:
+        match slice {
+            //~^ NOTE: Capturing slice[] -> ImmBorrow
+            //~| NOTE: Min Capture slice[] -> ImmBorrow
+            [] => {},
+            _ => {}
+        }
+    };
+    c();
+    let c =  #[rustc_capture_analysis]
+    || {
+    //~^ First Pass analysis includes:
+    //~| Min Capture analysis includes:
+        match slice {
+            //~^ NOTE: Capturing slice[] -> ImmBorrow
+            //~| NOTE: Min Capture slice[] -> ImmBorrow
+            [_, .. ,_] => {},
+            _ => {}
+        }
+    };
+    c();
+}
+
+// Wild pattern that doesn't bind, so no capture
+fn test_8_capture_slice_wild() {
+    let slice: &[i32] = &[1, 2, 3];
+    let c =  #[rustc_capture_analysis]
+    || {
+    //~^ First Pass analysis includes:
+        match slice {
+            [..] => {},
+            _ => {}
+        }
+    };
+    c();
+}
+
 fn main() {
     test_1_should_capture();
     test_2_should_not_capture();
@@ -134,4 +178,6 @@
     test_6_should_capture_single_variant();
     test_4_should_not_capture_array();
     test_5_should_capture_multi_variant();
+    test_7_should_capture_slice_len();
+    test_8_capture_slice_wild();
 }
diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
index 4608133..e137af1 100644
--- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
+++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
@@ -1,59 +1,5 @@
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:10:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:31:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:52:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:68:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:90:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:114:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:14:5
+  --> $DIR/patterns-capture-analysis.rs:12:5
    |
 LL | /     || {
 LL | |
@@ -65,13 +11,13 @@
    | |_____^
    |
 note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:17:15
+  --> $DIR/patterns-capture-analysis.rs:15:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:14:5
+  --> $DIR/patterns-capture-analysis.rs:12:5
    |
 LL | /     || {
 LL | |
@@ -83,13 +29,13 @@
    | |_____^
    |
 note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:17:15
+  --> $DIR/patterns-capture-analysis.rs:15:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:34:5
+  --> $DIR/patterns-capture-analysis.rs:30:5
    |
 LL | /     || {
 LL | |
@@ -100,7 +46,7 @@
    | |_____^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:55:5
+  --> $DIR/patterns-capture-analysis.rs:49:5
    |
 LL | /     || {
 LL | |
@@ -111,7 +57,7 @@
    | |_____^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:71:5
+  --> $DIR/patterns-capture-analysis.rs:63:5
    |
 LL | /     || {
 LL | |
@@ -123,18 +69,18 @@
    | |_____^
    |
 note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:74:15
+  --> $DIR/patterns-capture-analysis.rs:66:15
    |
 LL |         match variant {
    |               ^^^^^^^
 note: Capturing variant[(0, 0)] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:74:15
+  --> $DIR/patterns-capture-analysis.rs:66:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:71:5
+  --> $DIR/patterns-capture-analysis.rs:63:5
    |
 LL | /     || {
 LL | |
@@ -146,13 +92,13 @@
    | |_____^
    |
 note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:74:15
+  --> $DIR/patterns-capture-analysis.rs:66:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:93:5
+  --> $DIR/patterns-capture-analysis.rs:83:5
    |
 LL | /     || {
 LL | |
@@ -163,7 +109,7 @@
    | |_____^
 
 error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:117:5
+  --> $DIR/patterns-capture-analysis.rs:105:5
    |
 LL | /     || {
 LL | |
@@ -175,13 +121,13 @@
    | |_____^
    |
 note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:120:15
+  --> $DIR/patterns-capture-analysis.rs:108:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
 error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:117:5
+  --> $DIR/patterns-capture-analysis.rs:105:5
    |
 LL | /     || {
 LL | |
@@ -193,11 +139,130 @@
    | |_____^
    |
 note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:120:15
+  --> $DIR/patterns-capture-analysis.rs:108:15
    |
 LL |         match variant {
    |               ^^^^^^^
 
-error: aborting due to 15 previous errors
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:123:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match slice {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Capturing slice[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:126:15
+   |
+LL |         match slice {
+   |               ^^^^^
 
-For more information about this error, try `rustc --explain E0658`.
+error: Min Capture analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:123:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match slice {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Min Capture slice[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:126:15
+   |
+LL |         match slice {
+   |               ^^^^^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:135:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match slice {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Capturing slice[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:138:15
+   |
+LL |         match slice {
+   |               ^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:135:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match slice {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Min Capture slice[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:138:15
+   |
+LL |         match slice {
+   |               ^^^^^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:147:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match slice {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Capturing slice[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:150:15
+   |
+LL |         match slice {
+   |               ^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:147:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match slice {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Min Capture slice[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:150:15
+   |
+LL |         match slice {
+   |               ^^^^^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:164:5
+   |
+LL | /     || {
+LL | |
+LL | |         match slice {
+LL | |             [..] => {},
+LL | |             _ => {}
+LL | |         }
+LL | |     };
+   | |_____^
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
index bc7295a..98f8d5d 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
+++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 #![warn(rust_2021_incompatible_closure_captures)]
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 fn main() {
     if let a = "" {
diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
index 0f15f66..5496d0e 100644
--- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
+++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
@@ -3,7 +3,7 @@
 
 #![allow(unused)]
 #![allow(dead_code)]
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Int(i32);
 struct B<'a>(&'a i32);
diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
index a097424..b5e97ec1 100644
--- a/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
+++ b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
@@ -2,7 +2,7 @@
 // check-pass
 
 #![feature(rustc_attrs)]
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {
     let mut x = 1;
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
index a1b711a..87ae83d 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
@@ -11,6 +11,13 @@
 
 impl<T: ConstParamTy> ConstParamTy for S<T> {}
 
+#[derive(PartialEq, Eq, ConstParamTy)]
+struct D<T> {
+    field: u8,
+    gen: T,
+}
+
+
 fn check<T: ConstParamTy + ?Sized>() {}
 
 fn main() {
@@ -39,5 +46,8 @@
     check::<S<u8>>();
     check::<S<[&[bool]; 8]>>();
 
+    check::<D<u8>>();
+    check::<D<[&[bool]; 8]>>();
+
     // FIXME: test tuples
 }
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
index 07fd243..74283a3 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
@@ -10,4 +10,8 @@
 impl std::marker::ConstParamTy for CantParam {}
 //~^ error: the trait `ConstParamTy` cannot be implemented for this type
 
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+//~^ error: the trait `ConstParamTy` cannot be implemented for this type
+struct CantParamDerive(NotParam);
+
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
index c8e0658..52b65d6 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
@@ -7,6 +7,17 @@
 LL | impl std::marker::ConstParamTy for CantParam {}
    |                                    ^^^^^^^^^
 
-error: aborting due to previous error
+error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
+  --> $DIR/const_param_ty_impl_bad_field.rs:13:10
+   |
+LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct CantParamDerive(NotParam);
+   |                        -------- this field does not implement `ConstParamTy`
+   |
+   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
index 17ef396..37986de 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
@@ -10,6 +10,10 @@
 impl std::marker::ConstParamTy for CantParam {}
 //~^ error: the type `CantParam` does not `#[derive(Eq)]`
 
+#[derive(std::marker::ConstParamTy)]
+//~^ error: the type `CantParamDerive` does not `#[derive(Eq)]`
+struct CantParamDerive(ImplementsConstParamTy);
+
 fn check<T: std::marker::ConstParamTy>() {}
 
 fn main() {
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
index ca5abf5..52701d5 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
@@ -7,6 +7,16 @@
 note: required by a bound in `ConstParamTy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 
-error: aborting due to previous error
+error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]`
+  --> $DIR/const_param_ty_impl_no_structural_eq.rs:13:10
+   |
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive`
+   |
+note: required by a bound in `ConstParamTy`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
new file mode 100644
index 0000000..d70377a
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
@@ -0,0 +1,33 @@
+#![allow(incomplete_features)]
+#![feature(adt_const_params, structural_match)]
+
+union Union {
+    a: u8,
+}
+
+impl PartialEq for Union {
+    fn eq(&self, other: &Union) -> bool {
+        true
+    }
+}
+impl Eq for Union {}
+impl std::marker::StructuralEq for Union {}
+
+impl std::marker::ConstParamTy for Union {}
+
+#[derive(std::marker::ConstParamTy)]
+//~^ ERROR this trait cannot be derived for unions
+union UnionDerive {
+    a: u8,
+}
+
+impl PartialEq for UnionDerive {
+    fn eq(&self, other: &UnionDerive) -> bool {
+        true
+    }
+}
+impl Eq for UnionDerive {}
+impl std::marker::StructuralEq for UnionDerive {}
+
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
new file mode 100644
index 0000000..2937030
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
@@ -0,0 +1,8 @@
+error: this trait cannot be derived for unions
+  --> $DIR/const_param_ty_impl_union.rs:18:10
+   |
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr
index 70a1abb..434b074 100644
--- a/tests/ui/consts/const-eval/format.stderr
+++ b/tests/ui/consts/const-eval/format.stderr
@@ -43,62 +43,6 @@
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-note: erroneous constant used
-  --> $DIR/format.rs:2:12
-   |
-LL |     panic!("{:?}", 0);
-   |            ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:2:12
-   |
-LL |     panic!("{:?}", 0);
-   |            ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:2:20
-   |
-LL |     panic!("{:?}", 0);
-   |                    ^
-   |
-   = note: this note originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-note: erroneous constant used
-  --> $DIR/format.rs:2:20
-   |
-LL |     panic!("{:?}", 0);
-   |                    ^
-   |
-   = note: this note originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:14
-   |
-LL |     println!("{:?}", 0);
-   |              ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:14
-   |
-LL |     println!("{:?}", 0);
-   |              ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:22
-   |
-LL |     println!("{:?}", 0);
-   |                      ^
-   |
-   = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:22
-   |
-LL |     println!("{:?}", 0);
-   |                      ^
-   |
-   = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/const-integer-bool-ops.rs b/tests/ui/consts/const-integer-bool-ops.rs
index 4110ae3..35915a7 100644
--- a/tests/ui/consts/const-integer-bool-ops.rs
+++ b/tests/ui/consts/const-integer-bool-ops.rs
@@ -6,7 +6,6 @@
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR: [i32; X] = [99; 34];
-//~^ constant
 
 const X1: usize = 42 || 39;
 //~^ ERROR mismatched types
@@ -16,7 +15,6 @@
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR1: [i32; X1] = [99; 47];
-//~^ constant
 
 const X2: usize = -42 || -39;
 //~^ ERROR mismatched types
@@ -26,7 +24,6 @@
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR2: [i32; X2] = [99; 18446744073709551607];
-//~^ constant
 
 const X3: usize = -42 && -39;
 //~^ ERROR mismatched types
@@ -36,43 +33,36 @@
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR3: [i32; X3] = [99; 6];
-//~^ constant
 
 const Y: usize = 42.0 == 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR: [i32; Y] = [99; 1];
-//~^ constant
 
 const Y1: usize = 42.0 >= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR1: [i32; Y1] = [99; 1];
-//~^ constant
 
 const Y2: usize = 42.0 <= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR2: [i32; Y2] = [99; 1];
-//~^ constant
 
 const Y3: usize = 42.0 > 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR3: [i32; Y3] = [99; 0];
-//~^ constant
 
 const Y4: usize = 42.0 < 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR4: [i32; Y4] = [99; 0];
-//~^ constant
 
 const Y5: usize = 42.0 != 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR5: [i32; Y5] = [99; 0];
-//~^ constant
 
 fn main() {
     let _ = ARR;
diff --git a/tests/ui/consts/const-integer-bool-ops.stderr b/tests/ui/consts/const-integer-bool-ops.stderr
index b5c3b22..4e503e5 100644
--- a/tests/ui/consts/const-integer-bool-ops.stderr
+++ b/tests/ui/consts/const-integer-bool-ops.stderr
@@ -16,156 +16,96 @@
 LL | const X: usize = 42 && 39;
    |                  ^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:8:18
-   |
-LL | const ARR: [i32; X] = [99; 34];
-   |                  ^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:11:19
+  --> $DIR/const-integer-bool-ops.rs:10:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:11:25
+  --> $DIR/const-integer-bool-ops.rs:10:25
    |
 LL | const X1: usize = 42 || 39;
    |                         ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:11:19
+  --> $DIR/const-integer-bool-ops.rs:10:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:18:19
-   |
-LL | const ARR1: [i32; X1] = [99; 47];
-   |                   ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:21:19
+  --> $DIR/const-integer-bool-ops.rs:19:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:21:26
+  --> $DIR/const-integer-bool-ops.rs:19:26
    |
 LL | const X2: usize = -42 || -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:21:19
+  --> $DIR/const-integer-bool-ops.rs:19:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
+error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:28:19
    |
-LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
-   |                   ^^
-
-error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:31:19
-   |
 LL | const X3: usize = -42 && -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:31:26
+  --> $DIR/const-integer-bool-ops.rs:28:26
    |
 LL | const X3: usize = -42 && -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:31:19
+  --> $DIR/const-integer-bool-ops.rs:28:19
    |
 LL | const X3: usize = -42 && -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:38:19
-   |
-LL | const ARR3: [i32; X3] = [99; 6];
-   |                   ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:41:18
+  --> $DIR/const-integer-bool-ops.rs:37:18
    |
 LL | const Y: usize = 42.0 == 42.0;
    |                  ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:44:19
-   |
-LL | const ARRR: [i32; Y] = [99; 1];
-   |                   ^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:47:19
+  --> $DIR/const-integer-bool-ops.rs:42:19
    |
 LL | const Y1: usize = 42.0 >= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:50:20
-   |
-LL | const ARRR1: [i32; Y1] = [99; 1];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:53:19
+  --> $DIR/const-integer-bool-ops.rs:47:19
    |
 LL | const Y2: usize = 42.0 <= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:56:20
-   |
-LL | const ARRR2: [i32; Y2] = [99; 1];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:59:19
+  --> $DIR/const-integer-bool-ops.rs:52:19
    |
 LL | const Y3: usize = 42.0 > 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:62:20
-   |
-LL | const ARRR3: [i32; Y3] = [99; 0];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:65:19
+  --> $DIR/const-integer-bool-ops.rs:57:19
    |
 LL | const Y4: usize = 42.0 < 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:68:20
-   |
-LL | const ARRR4: [i32; Y4] = [99; 0];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:71:19
+  --> $DIR/const-integer-bool-ops.rs:62:19
    |
 LL | const Y5: usize = 42.0 != 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:74:20
-   |
-LL | const ARRR5: [i32; Y5] = [99; 0];
-   |                    ^^
-
 error: aborting due to 18 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr
index 109d15a..61b00be 100644
--- a/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr
+++ b/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr
@@ -19,12 +19,6 @@
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
 
-note: erroneous constant used
-  --> $DIR/issue-76510.rs:11:70
-   |
-LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
-   |                                                                      ^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0596, E0658, E0764.
diff --git a/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr
index 109d15a..61b00be 100644
--- a/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr
+++ b/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr
@@ -19,12 +19,6 @@
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
 
-note: erroneous constant used
-  --> $DIR/issue-76510.rs:11:70
-   |
-LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
-   |                                                                      ^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0596, E0658, E0764.
diff --git a/tests/ui/consts/const-mut-refs/issue-76510.rs b/tests/ui/consts/const-mut-refs/issue-76510.rs
index b853e27..143d2fb 100644
--- a/tests/ui/consts/const-mut-refs/issue-76510.rs
+++ b/tests/ui/consts/const-mut-refs/issue-76510.rs
@@ -9,7 +9,6 @@
 
 const fn trigger() -> [(); unsafe {
         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
-        //~^ constant
         0
     }] {
     [(); 0]
diff --git a/tests/ui/consts/const-tup-index-span.rs b/tests/ui/consts/const-tup-index-span.rs
index 18f4f59..e77d392 100644
--- a/tests/ui/consts/const-tup-index-span.rs
+++ b/tests/ui/consts/const-tup-index-span.rs
@@ -4,7 +4,6 @@
 //~^ ERROR mismatched types
 //~| expected `(usize,)`, found `usize`
 const ARR: [i32; TUP.0] = [];
-//~^ constant
 
 fn main() {
 }
diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr
index 65f0520..d5df0df 100644
--- a/tests/ui/consts/const-tup-index-span.stderr
+++ b/tests/ui/consts/const-tup-index-span.stderr
@@ -11,12 +11,6 @@
 LL | const TUP: (usize,) = (5usize << 64,);
    |                       +            ++
 
-note: erroneous constant used
-  --> $DIR/const-tup-index-span.rs:6:18
-   |
-LL | const ARR: [i32; TUP.0] = [];
-   |                  ^^^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const_forget.rs b/tests/ui/consts/const_forget.rs
index acdd6a5..f06149f 100644
--- a/tests/ui/consts/const_forget.rs
+++ b/tests/ui/consts/const_forget.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(forget_copy)]
+#![allow(forgetting_copy_types)]
 
 use std::mem::forget;
 
diff --git a/tests/ui/consts/issue-104155.rs b/tests/ui/consts/issue-104155.rs
index b3821f4..7b375dc 100644
--- a/tests/ui/consts/issue-104155.rs
+++ b/tests/ui/consts/issue-104155.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(forget_copy)]
+#![allow(forgetting_copy_types)]
 
 const _: () = core::mem::forget(Box::<u32>::default);
 const _: () = core::mem::forget(|| Box::<u32>::default());
diff --git a/tests/ui/consts/issue-54954.rs b/tests/ui/consts/issue-54954.rs
index 520bf50..7bcfa05 100644
--- a/tests/ui/consts/issue-54954.rs
+++ b/tests/ui/consts/issue-54954.rs
@@ -9,8 +9,6 @@
 }
 
 fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
-  //~^ constant
-  //~| constant
     z
 }
 
diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr
index 8505582..b0701ba 100644
--- a/tests/ui/consts/issue-54954.stderr
+++ b/tests/ui/consts/issue-54954.stderr
@@ -16,18 +16,6 @@
 LL | |     }
    | |_____- `Tt::const_val` defined here
 
-note: erroneous constant used
-  --> $DIR/issue-54954.rs:11:15
-   |
-LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
-   |               ^^^^^^^
-
-note: erroneous constant used
-  --> $DIR/issue-54954.rs:11:34
-   |
-LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
-   |                                  ^^^^^^^
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0379, E0790.
diff --git a/tests/ui/consts/issue-56164.stderr b/tests/ui/consts/issue-56164.stderr
index 003f847..e46c649 100644
--- a/tests/ui/consts/issue-56164.stderr
+++ b/tests/ui/consts/issue-56164.stderr
@@ -28,18 +28,6 @@
 LL |     input()
    |     ^^^^^^^
 
-note: erroneous constant used
-  --> $DIR/issue-56164.rs:1:18
-   |
-LL | const fn foo() { (||{})() }
-   |                  ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/issue-56164.rs:1:18
-   |
-LL | const fn foo() { (||{})() }
-   |                  ^^^^^^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0015, E0277.
diff --git a/tests/ui/consts/issue-66693.stderr b/tests/ui/consts/issue-66693.stderr
index e9a3fce..f4898fd 100644
--- a/tests/ui/consts/issue-66693.stderr
+++ b/tests/ui/consts/issue-66693.stderr
@@ -22,17 +22,5 @@
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-note: erroneous constant used
-  --> $DIR/issue-66693.rs:11:12
-   |
-LL |     panic!(&1);
-   |            ^^
-
-note: erroneous constant used
-  --> $DIR/issue-66693.rs:11:12
-   |
-LL |     panic!(&1);
-   |            ^^
-
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/crate-leading-sep.rs b/tests/ui/crate-leading-sep.rs
index 8d1d0b4f..fce97d9 100644
--- a/tests/ui/crate-leading-sep.rs
+++ b/tests/ui/crate-leading-sep.rs
@@ -1,7 +1,7 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 fn main() {
     use ::std::mem;
diff --git a/tests/ui/drop/issue-110682.rs b/tests/ui/drop/issue-110682.rs
new file mode 100644
index 0000000..35f9c7e
--- /dev/null
+++ b/tests/ui/drop/issue-110682.rs
@@ -0,0 +1,92 @@
+// build-pass
+// compile-flags: -Zmir-opt-level=3
+
+use std::fmt::Debug;
+use std::mem::ManuallyDrop;
+use std::ptr;
+
+pub trait BitRegister {}
+
+macro_rules! register {
+    ($($t:ty),+ $(,)?) => { $(
+        impl BitRegister for $t {
+        }
+    )* };
+}
+
+register!(u8, u16, u32);
+
+pub trait BitStore: Sized + Debug {
+    /// The register type that the implementor describes.
+    type Mem: BitRegister + Into<Self>;
+}
+
+macro_rules! store {
+    ($($t:ty),+ $(,)?) => { $(
+        impl BitStore for $t {
+            type Mem = Self;
+        }
+    )+ };
+}
+
+store!(u8, u16, u32,);
+
+#[repr(C)]
+pub struct BitVec<T>
+where
+    T: BitStore,
+{
+    /// Region pointer describing the live portion of the owned buffer.
+    pointer: ptr::NonNull<T>,
+    /// Allocated capacity, in elements `T`, of the owned buffer.
+    capacity: usize,
+}
+
+impl<T> BitVec<T>
+where
+    T: BitStore,
+{
+    pub fn new() -> Self {
+        let pointer = ptr::NonNull::<T>::new(ptr::null_mut()).unwrap();
+
+        BitVec { pointer, capacity: 10 }
+    }
+
+    pub fn clear(&mut self) {
+        unsafe {
+            self.set_len(0);
+        }
+    }
+
+    #[inline]
+    pub unsafe fn set_len(&mut self, new_len: usize) {}
+
+    fn with_vec<F, R>(&mut self, func: F) -> R
+    where
+        F: FnOnce(&mut ManuallyDrop<Vec<T::Mem>>) -> R,
+    {
+        let cap = self.capacity;
+        let elts = 10;
+        let mut vec = ManuallyDrop::new(unsafe { Vec::from_raw_parts(ptr::null_mut(), elts, cap) });
+        let out = func(&mut vec);
+
+        out
+    }
+}
+
+impl<T> Drop for BitVec<T>
+where
+    T: BitStore,
+{
+    #[inline]
+    fn drop(&mut self) {
+        //  The buffer elements do not have destructors.
+        self.clear();
+        //  Run the `Vec` destructor to deällocate the buffer.
+        self.with_vec(|vec| unsafe { ManuallyDrop::drop(vec) });
+    }
+}
+
+fn main() {
+    let bitvec = BitVec::<u32>::new();
+}
diff --git a/tests/ui/drop/repeat-drop.rs b/tests/ui/drop/repeat-drop.rs
index 659d35d..0afb4bb 100644
--- a/tests/ui/drop/repeat-drop.rs
+++ b/tests/ui/drop/repeat-drop.rs
@@ -1,7 +1,7 @@
 // run-pass
 // needs-unwind
 
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 static mut CHECK: usize = 0;
 
diff --git a/tests/ui/dupe-first-attr.rc b/tests/ui/dupe-first-attr.rs
similarity index 74%
rename from tests/ui/dupe-first-attr.rc
rename to tests/ui/dupe-first-attr.rs
index 8b7025b..d950743 100644
--- a/tests/ui/dupe-first-attr.rc
+++ b/tests/ui/dupe-first-attr.rs
@@ -1,24 +1,26 @@
+// run-pass
+
 // Regression test for a problem with the first mod attribute
 // being applied to every mod
 
 // pretty-expanded FIXME #23616
 
 #[cfg(target_os = "linux")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "macos")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "windows")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "freebsd")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "dragonfly")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "android")]
-mod hello;
+mod hello {}
 
-pub fn main() { }
+fn main() {}
diff --git a/tests/ui/dyn-star/param-env-infer.current.stderr b/tests/ui/dyn-star/param-env-infer.current.stderr
new file mode 100644
index 0000000..b3af7be
--- /dev/null
+++ b/tests/ui/dyn-star/param-env-infer.current.stderr
@@ -0,0 +1,18 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/param-env-infer.rs:5:12
+   |
+LL | #![feature(dyn_star, pointer_like_trait)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0282]: type annotations needed
+  --> $DIR/param-env-infer.rs:13:10
+   |
+LL |     t as _
+   |          ^ cannot infer type
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/dyn-star/param-env-infer.next.stderr b/tests/ui/dyn-star/param-env-infer.next.stderr
new file mode 100644
index 0000000..64d76bb
--- /dev/null
+++ b/tests/ui/dyn-star/param-env-infer.next.stderr
@@ -0,0 +1,73 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/param-env-infer.rs:5:12
+   |
+LL | #![feature(dyn_star, pointer_like_trait)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}`
+  --> $DIR/param-env-infer.rs:11:60
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires borrow-checking `make_dyn_star`...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `make_dyn_star`...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires preparing `make_dyn_star` for borrow checking...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires unsafety-checking `make_dyn_star`...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `make_dyn_star`...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `make_dyn_star`...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building THIR for `make_dyn_star`...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `make_dyn_star`...
+  --> $DIR/param-env-infer.rs:11:1
+   |
+LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing layout of `make_dyn_star::{opaque#0}`...
+   = note: ...which requires normalizing `make_dyn_star::{opaque#0}`...
+   = note: ...which again requires computing type of `make_dyn_star::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/param-env-infer.rs:5:1
+   |
+LL | / #![feature(dyn_star, pointer_like_trait)]
+LL | |
+LL | |
+LL | | use std::fmt::Debug;
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/dyn-star/param-env-infer.rs b/tests/ui/dyn-star/param-env-infer.rs
new file mode 100644
index 0000000..1fb16d7
--- /dev/null
+++ b/tests/ui/dyn-star/param-env-infer.rs
@@ -0,0 +1,17 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+// incremental
+
+#![feature(dyn_star, pointer_like_trait)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+
+use std::fmt::Debug;
+use std::marker::PointerLike;
+
+fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+    //[next]~^ ERROR cycle detected when computing type of `make_dyn_star::{opaque#0}`
+    t as _
+    //[current]~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/enum-discriminant/issue-41394.rs b/tests/ui/enum-discriminant/issue-41394.rs
index 07cad87..06a3308 100644
--- a/tests/ui/enum-discriminant/issue-41394.rs
+++ b/tests/ui/enum-discriminant/issue-41394.rs
@@ -5,7 +5,6 @@
 
 enum Bar {
     A = Foo::A as isize
-    //~^ const
 }
 
 fn main() {}
diff --git a/tests/ui/enum-discriminant/issue-41394.stderr b/tests/ui/enum-discriminant/issue-41394.stderr
index 1b5c646..fa95ca9 100644
--- a/tests/ui/enum-discriminant/issue-41394.stderr
+++ b/tests/ui/enum-discriminant/issue-41394.stderr
@@ -6,12 +6,6 @@
    |         |
    |         &str
 
-note: erroneous constant used
-  --> $DIR/issue-41394.rs:7:9
-   |
-LL |     A = Foo::A as isize
-   |         ^^^^^^^^^^^^^^^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/error-codes/E0746.fixed b/tests/ui/error-codes/E0746.fixed
deleted file mode 100644
index ca8319a..0000000
--- a/tests/ui/error-codes/E0746.fixed
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-rustfix
-#![allow(dead_code)]
-struct Struct;
-trait Trait {}
-impl Trait for Struct {}
-impl Trait for u32 {}
-
-fn foo() -> impl Trait { Struct }
-//~^ ERROR E0746
-
-fn bar() -> impl Trait { //~ ERROR E0746
-    if true {
-        return 0;
-    }
-    42
-}
-
-fn main() {}
diff --git a/tests/ui/error-codes/E0746.rs b/tests/ui/error-codes/E0746.rs
index bf5ba8f..86b5b74 100644
--- a/tests/ui/error-codes/E0746.rs
+++ b/tests/ui/error-codes/E0746.rs
@@ -1,5 +1,5 @@
-// run-rustfix
 #![allow(dead_code)]
+
 struct Struct;
 trait Trait {}
 impl Trait for Struct {}
diff --git a/tests/ui/error-codes/E0746.stderr b/tests/ui/error-codes/E0746.stderr
index 2153b59..9fe90ab 100644
--- a/tests/ui/error-codes/E0746.stderr
+++ b/tests/ui/error-codes/E0746.stderr
@@ -4,11 +4,14 @@
 LL | fn foo() -> dyn Trait { Struct }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn foo() -> impl Trait { Struct }
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn foo() -> Box<dyn Trait> { Box::new(Struct) }
+   |             ++++         +   +++++++++      +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/E0746.rs:11:13
@@ -16,11 +19,18 @@
 LL | fn bar() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bar() -> impl Trait {
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bar() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(0);
+LL |     }
+LL ~     Box::new(42)
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
index 0bc4fee..bb093a4 100644
--- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
+++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo {
     x: isize
diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
index 26ae669..1a9f89c 100644
--- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
+++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo {
     x: isize
diff --git a/tests/ui/extenv/extenv-escaped-var.rs b/tests/ui/extenv/extenv-escaped-var.rs
new file mode 100644
index 0000000..d898feb
--- /dev/null
+++ b/tests/ui/extenv/extenv-escaped-var.rs
@@ -0,0 +1,3 @@
+fn main() {
+    env!("\t"); //~ERROR environment variable `\t` not defined at compile time
+}
diff --git a/tests/ui/extenv/extenv-escaped-var.stderr b/tests/ui/extenv/extenv-escaped-var.stderr
new file mode 100644
index 0000000..25e218c
--- /dev/null
+++ b/tests/ui/extenv/extenv-escaped-var.stderr
@@ -0,0 +1,11 @@
+error: environment variable `\t` not defined at compile time
+  --> $DIR/extenv-escaped-var.rs:2:5
+   |
+LL |     env!("\t");
+   |     ^^^^^^^^^^
+   |
+   = help: use `std::env::var("\t")` to read the variable at run time
+   = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/extenv/issue-110547.stderr b/tests/ui/extenv/issue-110547.stderr
index 1219630..10589ec 100644
--- a/tests/ui/extenv/issue-110547.stderr
+++ b/tests/ui/extenv/issue-110547.stderr
@@ -1,28 +1,28 @@
-error: environment variable `    ` not defined at compile time
+error: environment variable `\t` not defined at compile time
   --> $DIR/issue-110547.rs:4:5
    |
 LL |     env!{"\t"};
    |     ^^^^^^^^^^
    |
-   = help: use `std::env::var("    ")` to read the variable at run time
+   = help: use `std::env::var("\t")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: environment variable `    ` not defined at compile time
+error: environment variable `\t` not defined at compile time
   --> $DIR/issue-110547.rs:5:5
    |
 LL |     env!("\t");
    |     ^^^^^^^^^^
    |
-   = help: use `std::env::var("    ")` to read the variable at run time
+   = help: use `std::env::var("\t")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: environment variable `` not defined at compile time
+error: environment variable `\u{2069}` not defined at compile time
   --> $DIR/issue-110547.rs:6:5
    |
 LL |     env!("\u{2069}");
    |     ^^^^^^^^^^^^^^^^
    |
-   = help: use `std::env::var("")` to read the variable at run time
+   = help: use `std::env::var("\u{2069}")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/extern/auxiliary/invalid-utf8.txt b/tests/ui/extern/auxiliary/invalid-utf8.txt
deleted file mode 100644
index dc1115b..0000000
--- a/tests/ui/extern/auxiliary/invalid-utf8.txt
+++ /dev/null
@@ -1 +0,0 @@
-Ã(
\ No newline at end of file
diff --git a/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis b/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis
deleted file mode 100644
index 6eb47e3..0000000
--- a/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
-</AutoVisualizer>
diff --git a/tests/ui/generator/drop-env.rs b/tests/ui/generator/drop-env.rs
index cb46953..137a407 100644
--- a/tests/ui/generator/drop-env.rs
+++ b/tests/ui/generator/drop-env.rs
@@ -4,7 +4,7 @@
 //[nomiropt]compile-flags: -Z mir-opt-level=0
 
 #![feature(generators, generator_trait)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::ops::Generator;
 use std::pin::Pin;
diff --git a/tests/ui/generator/drop-tracking-error-body.rs b/tests/ui/generator/drop-tracking-error-body.rs
new file mode 100644
index 0000000..f99d9ab
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-error-body.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Zdrop-tracking-mir --edition=2021
+
+#![feature(generators)]
+
+pub async fn async_bad_body() {
+    match true {} //~ ERROR non-exhaustive patterns: type `bool` is non-empty
+}
+
+pub fn generator_bad_body() {
+    || {
+        // 'non-exhaustive pattern' only seems to be reported once, so this annotation doesn't work
+        // keep the function around so we can make sure it doesn't ICE
+        match true {}; // ERROR non-exhaustive patterns: type `bool` is non-empty
+        yield ();
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/generator/drop-tracking-error-body.stderr b/tests/ui/generator/drop-tracking-error-body.stderr
new file mode 100644
index 0000000..28a6892
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-error-body.stderr
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: type `bool` is non-empty
+  --> $DIR/drop-tracking-error-body.rs:6:11
+   |
+LL |     match true {}
+   |           ^^^^
+   |
+   = note: the matched value is of type `bool`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match true {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/generator/issue-57017.rs b/tests/ui/generator/issue-57017.rs
index 918d233..381897c 100644
--- a/tests/ui/generator/issue-57017.rs
+++ b/tests/ui/generator/issue-57017.rs
@@ -5,7 +5,7 @@
 // [drop_tracking_mir] build-pass
 
 #![feature(generators, negative_impls)]
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 macro_rules! type_combinations {
     (
diff --git a/tests/ui/generator/non-static-is-unpin.rs b/tests/ui/generator/non-static-is-unpin.rs
index adba800..a5dde39 100644
--- a/tests/ui/generator/non-static-is-unpin.rs
+++ b/tests/ui/generator/non-static-is-unpin.rs
@@ -3,7 +3,7 @@
 // run-pass
 
 #![feature(generators, generator_trait)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::marker::{PhantomPinned, Unpin};
 
diff --git a/tests/ui/generator/resume-arg-size.rs b/tests/ui/generator/resume-arg-size.rs
index 19618f8..195166f 100644
--- a/tests/ui/generator/resume-arg-size.rs
+++ b/tests/ui/generator/resume-arg-size.rs
@@ -1,5 +1,5 @@
 #![feature(generators)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // run-pass
 
diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr
index d78f7a7..b21ff30 100644
--- a/tests/ui/generic-associated-types/equality-bound.stderr
+++ b/tests/ui/generic-associated-types/equality-bound.stderr
@@ -36,7 +36,10 @@
   --> $DIR/equality-bound.rs:9:41
    |
 LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
-   |                                         ^ use of undeclared type `I`
+   |                                         ^
+   |                                         |
+   |                                         use of undeclared type `I`
+   |                                         help: a type parameter with a similar name exists: `J`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
index 2142673..721bb72 100644
--- a/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
+++ b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
@@ -1,7 +1,7 @@
 // check-pass
 
 #![feature(decl_macro)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 macro mac() {
     mod m {
diff --git a/tests/ui/illegal-ufcs-drop.fixed b/tests/ui/illegal-ufcs-drop.fixed
index 8783682..c088c82 100644
--- a/tests/ui/illegal-ufcs-drop.fixed
+++ b/tests/ui/illegal-ufcs-drop.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo;
 
diff --git a/tests/ui/illegal-ufcs-drop.rs b/tests/ui/illegal-ufcs-drop.rs
index 2977430..1389b11 100644
--- a/tests/ui/illegal-ufcs-drop.rs
+++ b/tests/ui/illegal-ufcs-drop.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo;
 
diff --git a/tests/ui/impl-trait/arg-position-impl-trait-too-long.rs b/tests/ui/impl-trait/arg-position-impl-trait-too-long.rs
new file mode 100644
index 0000000..8ef9281
--- /dev/null
+++ b/tests/ui/impl-trait/arg-position-impl-trait-too-long.rs
@@ -0,0 +1,22 @@
+struct Header;
+struct EntryMetadata;
+struct Entry<A, B>(A, B);
+
+trait Tr {
+    type EncodedKey;
+    type EncodedValue;
+}
+
+fn test<C: Tr, R>(
+    // This APIT is long, however we shouldn't render the type name with a newline in it.
+    y: impl FnOnce(
+        &mut Header,
+        &mut [EntryMetadata],
+        &mut [Entry<C::EncodedKey, C::EncodedValue>]
+    ) -> R,
+) {
+    let () = y;
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr
new file mode 100644
index 0000000..40446a3
--- /dev/null
+++ b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/arg-position-impl-trait-too-long.rs:18:9
+   |
+LL |       y: impl FnOnce(
+   |  ________-
+LL | |         &mut Header,
+LL | |         &mut [EntryMetadata],
+LL | |         &mut [Entry<C::EncodedKey, C::EncodedValue>]
+LL | |     ) -> R,
+   | |__________- this type parameter
+LL |   ) {
+LL |       let () = y;
+   |           ^^   - this expression has type `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`
+   |           |
+   |           expected type parameter `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`, found `()`
+   |
+   = note: expected type parameter `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`
+                   found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
index cbf1daa..af36820 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
@@ -26,7 +26,7 @@
     if true {
         Struct
     } else {
-        42 //~ ERROR `if` and `else` have incompatible types
+        42
     }
 }
 fn bam() -> Box<dyn Trait> {
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
index dc1e40e..ed9261d 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -46,11 +46,10 @@
 LL | fn bap() -> Trait { Struct }
    |             ^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn bap() -> impl Trait { Struct }
-   |             ~~~~~~~~~~
+LL | fn bap() -> Box<Trait> { Box::new(Struct) }
+   |             ++++     +   +++++++++      +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
@@ -58,11 +57,14 @@
 LL | fn ban() -> dyn Trait { Struct }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn ban() -> impl Trait { Struct }
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) }
+   |             ++++         +   +++++++++      +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
@@ -70,14 +72,14 @@
 LL | fn bak() -> dyn Trait { unimplemented!() }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bak() -> impl Trait { unimplemented!() }
-   |             ~~~~~~~~~~
-help: use a boxed trait object if all return paths implement trait `Trait`
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn bak() -> Box<dyn Trait> { unimplemented!() }
-   |             ++++         +
+LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) }
+   |             ++++         +   +++++++++                +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
@@ -85,34 +87,18 @@
 LL | fn bal() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl Trait` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn bal() -> Box<dyn Trait> {
-   |             ++++         +
-help: ... and box this value
+LL | fn bal() -> impl Trait {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         return Box::new(Struct);
-   |                +++++++++      +
-help: ... and box this value
+LL ~ fn bal() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(Struct);
+LL |     }
+LL ~     Box::new(42)
    |
-LL |     Box::new(42)
-   |     +++++++++  +
-
-error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9
-   |
-LL | /     if true {
-LL | |         Struct
-   | |         ------ expected because of this
-LL | |     } else {
-LL | |         42
-   | |         ^^ expected `Struct`, found integer
-LL | |     }
-   | |_____- `if` and `else` have incompatible types
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13
@@ -120,22 +106,18 @@
 LL | fn bax() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl Trait` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn bax() -> Box<dyn Trait> {
-   |             ++++         +
-help: ... and box this value
+LL | fn bax() -> impl Trait {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         Box::new(Struct)
-   |         +++++++++      +
-help: ... and box this value
+LL ~ fn bax() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         Box::new(Struct)
+LL |     } else {
+LL ~         Box::new(42)
    |
-LL |         Box::new(42)
-   |         +++++++++  +
 
 error[E0308]: mismatched types
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16
@@ -279,11 +261,18 @@
 LL | fn bat() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bat() -> impl Trait {
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bat() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(0);
+LL |     }
+LL ~     Box::new(42)
+   |
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:66:13
@@ -291,13 +280,20 @@
 LL | fn bay() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bay() -> impl Trait {
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bay() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         Box::new(0)
+LL |     } else {
+LL ~         Box::new(42)
+   |
 
-error: aborting due to 20 previous errors
+error: aborting due to 19 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0746.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
new file mode 100644
index 0000000..cd4f261
--- /dev/null
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+
+struct S<T>(T);
+struct S2;
+
+impl<T: Default> Default for S<T> {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+impl Default for S2 {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+
+fn main() {}
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs
new file mode 100644
index 0000000..024b703
--- /dev/null
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+
+struct S<T>(T);
+struct S2;
+
+impl<T: Default> impl Default for S<T> {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+impl impl Default for S2 {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+
+fn main() {}
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
new file mode 100644
index 0000000..5aafc8b
--- /dev/null
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
@@ -0,0 +1,26 @@
+error: unexpected `impl` keyword
+  --> $DIR/extra-impl-in-trait-impl.rs:6:18
+   |
+LL | impl<T: Default> impl Default for S<T> {
+   |                  ^^^^^ help: remove the extra `impl`
+   |
+note: this is parsed as an `impl Trait` type, but a trait is expected at this position
+  --> $DIR/extra-impl-in-trait-impl.rs:6:18
+   |
+LL | impl<T: Default> impl Default for S<T> {
+   |                  ^^^^^^^^^^^^
+
+error: unexpected `impl` keyword
+  --> $DIR/extra-impl-in-trait-impl.rs:12:6
+   |
+LL | impl impl Default for S2 {
+   |      ^^^^^ help: remove the extra `impl`
+   |
+note: this is parsed as an `impl Trait` type, but a trait is expected at this position
+  --> $DIR/extra-impl-in-trait-impl.rs:12:6
+   |
+LL | impl impl Default for S2 {
+   |      ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/impl-trait/issue-103181-1.stderr b/tests/ui/impl-trait/issue-103181-1.current.stderr
similarity index 90%
rename from tests/ui/impl-trait/issue-103181-1.stderr
rename to tests/ui/impl-trait/issue-103181-1.current.stderr
index cd02660..e87a9d2 100644
--- a/tests/ui/impl-trait/issue-103181-1.stderr
+++ b/tests/ui/impl-trait/issue-103181-1.current.stderr
@@ -1,5 +1,5 @@
 error[E0046]: not all trait items implemented, missing: `Error`
-  --> $DIR/issue-103181-1.rs:9:5
+  --> $DIR/issue-103181-1.rs:11:5
    |
 LL |         type Error;
    |         ---------- `Error` from trait
diff --git a/tests/ui/impl-trait/issue-103181-1.stderr b/tests/ui/impl-trait/issue-103181-1.next.stderr
similarity index 90%
copy from tests/ui/impl-trait/issue-103181-1.stderr
copy to tests/ui/impl-trait/issue-103181-1.next.stderr
index cd02660..e87a9d2 100644
--- a/tests/ui/impl-trait/issue-103181-1.stderr
+++ b/tests/ui/impl-trait/issue-103181-1.next.stderr
@@ -1,5 +1,5 @@
 error[E0046]: not all trait items implemented, missing: `Error`
-  --> $DIR/issue-103181-1.rs:9:5
+  --> $DIR/issue-103181-1.rs:11:5
    |
 LL |         type Error;
    |         ---------- `Error` from trait
diff --git a/tests/ui/impl-trait/issue-103181-1.rs b/tests/ui/impl-trait/issue-103181-1.rs
index 197aedf..5154abc 100644
--- a/tests/ui/impl-trait/issue-103181-1.rs
+++ b/tests/ui/impl-trait/issue-103181-1.rs
@@ -1,3 +1,5 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
 // edition:2021
 
 mod hyper {
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.rs b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
new file mode 100644
index 0000000..c3a6f09
--- /dev/null
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
@@ -0,0 +1,12 @@
+trait Trait {}
+impl Trait for () {}
+
+fn foo<T: Trait, U: Trait>() -> impl Trait {
+    //~^ WARN function cannot return without recursing [unconditional_recursion]
+    let a: T = foo::<T, U>();
+    //~^ ERROR concrete type differs from previous defining opaque type use
+    loop {}
+    let _: T = foo::<U, T>();
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
new file mode 100644
index 0000000..0699174
--- /dev/null
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
@@ -0,0 +1,26 @@
+warning: function cannot return without recursing
+  --> $DIR/multiple-defining-usages-in-body.rs:4:1
+   |
+LL | fn foo<T: Trait, U: Trait>() -> impl Trait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |     let a: T = foo::<T, U>();
+   |                ------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+   = note: `#[warn(unconditional_recursion)]` on by default
+
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-defining-usages-in-body.rs:6:16
+   |
+LL |     let a: T = foo::<T, U>();
+   |                ^^^^^^^^^^^^^ expected `U`, got `T`
+   |
+note: previous use here
+  --> $DIR/multiple-defining-usages-in-body.rs:9:16
+   |
+LL |     let _: T = foo::<U, T>();
+   |                ^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
index fa7664a..a8a6288 100644
--- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
+++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
@@ -77,7 +77,7 @@
 fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
     match 13 {
         0 => 0i32,
-        1 => 1u32, //~ ERROR `match` arms have incompatible types
+        1 => 1u32,
         _ => 2u32,
     }
 }
@@ -86,7 +86,7 @@
     if false {
         0i32
     } else {
-        1u32 //~ ERROR `if` and `else` have incompatible types
+        1u32
     }
 }
 
diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
index 3c65fd9..9205d745 100644
--- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -171,39 +171,20 @@
 LL | fn hat() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn hat() -> Box<dyn std::fmt::Display> {
-   |             ++++                     +
-help: ... and box this value
+LL | fn hat() -> impl std::fmt::Display {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |             return Box::new(0i32);
-   |                    +++++++++    +
-help: ... and box this value
+LL ~ fn hat() -> Box<dyn std::fmt::Display> {
+LL |     match 13 {
+LL |         0 => {
+LL ~             return Box::new(0i32);
+LL |         }
+LL |         _ => {
+LL ~             Box::new(1u32)
    |
-LL |             Box::new(1u32)
-   |             +++++++++    +
-
-error[E0308]: `match` arms have incompatible types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14
-   |
-LL | /     match 13 {
-LL | |         0 => 0i32,
-   | |              ---- this is found to be of type `i32`
-LL | |         1 => 1u32,
-   | |              ^^^^ expected `i32`, found `u32`
-LL | |         _ => 2u32,
-LL | |     }
-   | |_____- `match` arms have incompatible types
-   |
-help: change the type of the numeric literal from `u32` to `i32`
-   |
-LL |         1 => 1i32,
-   |               ~~~
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
@@ -211,43 +192,18 @@
 LL | fn pug() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn pug() -> Box<dyn std::fmt::Display> {
-   |             ++++                     +
-help: ... and box this value
+LL | fn pug() -> impl std::fmt::Display {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         0 => Box::new(0i32),
-   |              +++++++++    +
-help: ... and box this value
+LL ~ fn pug() -> Box<dyn std::fmt::Display> {
+LL |     match 13 {
+LL ~         0 => Box::new(0i32),
+LL ~         1 => Box::new(1u32),
+LL ~         _ => Box::new(2u32),
    |
-LL |         1 => Box::new(1u32),
-   |              +++++++++    +
-help: ... and box this value
-   |
-LL |         _ => Box::new(2u32),
-   |              +++++++++    +
-
-error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9
-   |
-LL | /     if false {
-LL | |         0i32
-   | |         ---- expected because of this
-LL | |     } else {
-LL | |         1u32
-   | |         ^^^^ expected `i32`, found `u32`
-LL | |     }
-   | |_____- `if` and `else` have incompatible types
-   |
-help: change the type of the numeric literal from `u32` to `i32`
-   |
-LL |         1i32
-   |          ~~~
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13
@@ -255,24 +211,20 @@
 LL | fn man() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn man() -> Box<dyn std::fmt::Display> {
-   |             ++++                     +
-help: ... and box this value
+LL | fn man() -> impl std::fmt::Display {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         Box::new(0i32)
-   |         +++++++++    +
-help: ... and box this value
+LL ~ fn man() -> Box<dyn std::fmt::Display> {
+LL |     if false {
+LL ~         Box::new(0i32)
+LL |     } else {
+LL ~         Box::new(1u32)
    |
-LL |         Box::new(1u32)
-   |         +++++++++    +
 
-error: aborting due to 14 previous errors
+error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0308, E0746.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/imports/issue-109148.rs b/tests/ui/imports/issue-109148.rs
new file mode 100644
index 0000000..694cb49
--- /dev/null
+++ b/tests/ui/imports/issue-109148.rs
@@ -0,0 +1,15 @@
+// edition: 2021
+
+// https://github.com/rust-lang/rust/pull/111761#issuecomment-1557777314
+macro_rules! m {
+    () => {
+        extern crate core as std;
+        //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+    }
+}
+
+m!();
+
+use std::mem;
+
+fn main() {}
diff --git a/tests/ui/imports/issue-109148.stderr b/tests/ui/imports/issue-109148.stderr
new file mode 100644
index 0000000..6cc1221
--- /dev/null
+++ b/tests/ui/imports/issue-109148.stderr
@@ -0,0 +1,13 @@
+error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+  --> $DIR/issue-109148.rs:6:9
+   |
+LL |         extern crate core as std;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/imports/issue-109343.rs b/tests/ui/imports/issue-109343.rs
new file mode 100644
index 0000000..0c10259
--- /dev/null
+++ b/tests/ui/imports/issue-109343.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+pub mod f {}
+pub use unresolved::f;
+//~^ ERROR unresolved import `unresolved`
+
+/// [g]
+pub use f as g;
+
+fn main() {}
diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr
new file mode 100644
index 0000000..8d9a3ae
--- /dev/null
+++ b/tests/ui/imports/issue-109343.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-109343.rs:4:9
+   |
+LL | pub use unresolved::f;
+   |         ^^^^^^^^^^ maybe a missing crate `unresolved`?
+   |
+   = help: consider adding `extern crate unresolved` to use the `unresolved` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/invalid/foo.natvis.xml b/tests/ui/invalid/foo.natvis.xml
new file mode 100644
index 0000000..c341a40
--- /dev/null
+++ b/tests/ui/invalid/foo.natvis.xml
@@ -0,0 +1 @@
+<!-- empty -->
diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.rs b/tests/ui/invalid/invalid-debugger-visualizer-target.rs
index f9dd20d..1efb955 100644
--- a/tests/ui/invalid/invalid-debugger-visualizer-target.rs
+++ b/tests/ui/invalid/invalid-debugger-visualizer-target.rs
@@ -1,2 +1,2 @@
-#[debugger_visualizer(natvis_file = "../foo.natvis")] //~ ERROR attribute should be applied to a module
+#[debugger_visualizer(natvis_file = "./foo.natvis.xml")] //~ ERROR attribute should be applied to a module
 fn main() {}
diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
index 7944f75..c8a4d68 100644
--- a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
+++ b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
@@ -1,8 +1,8 @@
 error: attribute should be applied to a module
   --> $DIR/invalid-debugger-visualizer-target.rs:1:1
    |
-LL | #[debugger_visualizer(natvis_file = "../foo.natvis")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[debugger_visualizer(natvis_file = "./foo.natvis.xml")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/auxiliary/issue-3136-a.rc b/tests/ui/issues/auxiliary/issue-3136-a.rc
deleted file mode 100644
index cd5fd31..0000000
--- a/tests/ui/issues/auxiliary/issue-3136-a.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-#![crate_type = "lib"]
-
-#[path = "issue-3136-a.rs"]
-pub mod issue_3136_a;
diff --git a/tests/ui/issues/auxiliary/issue-3136-a.rs b/tests/ui/issues/auxiliary/issue-3136-a.rs
index 9bb546a..22bb1c8 100644
--- a/tests/ui/issues/auxiliary/issue-3136-a.rs
+++ b/tests/ui/issues/auxiliary/issue-3136-a.rs
@@ -1,11 +1,14 @@
+#![crate_type = "lib"]
+
 trait x {
     fn use_x<T>(&self);
 }
 struct y(());
 impl x for y {
     fn use_x<T>(&self) {
-        struct foo { //~ ERROR quux
-            i: ()
+        struct foo {
+            //~ ERROR quux
+            i: (),
         }
         fn new_foo<T>(i: ()) -> foo {
             foo { i: i }
diff --git a/tests/ui/issues/issue-18107.stderr b/tests/ui/issues/issue-18107.stderr
index 1669b55..cf4e063 100644
--- a/tests/ui/issues/issue-18107.stderr
+++ b/tests/ui/issues/issue-18107.stderr
@@ -4,14 +4,18 @@
 LL |     dyn AbstractRenderer
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL |     impl AbstractRenderer
+   |     ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-help: use a boxed trait object if all return paths implement trait `AbstractRenderer`
+LL ~     Box<dyn AbstractRenderer>
+LL |
+LL | {
+LL |     match 0 {
+LL ~         _ => Box::new(unimplemented!())
    |
-LL |     Box<dyn AbstractRenderer>
-   |     ++++                    +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-3136-b.rs b/tests/ui/issues/issue-3136-b.rs
index c4ca723..33d97fe 100644
--- a/tests/ui/issues/issue-3136-b.rs
+++ b/tests/ui/issues/issue-3136-b.rs
@@ -1,5 +1,5 @@
 // run-pass
-// aux-build:issue-3136-a.rc
+// aux-build:issue-3136-a.rs
 
 // pretty-expanded FIXME #23616
 
diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs
index 5a8aacb..045d40a 100644
--- a/tests/ui/iterators/collect-into-slice.rs
+++ b/tests/ui/iterators/collect-into-slice.rs
@@ -14,4 +14,10 @@
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
     process_slice(&some_generated_vec);
+
+    let some_generated_vec = (0..10).collect();
+    //~^ ERROR a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+    //~| NOTE try explicitly collecting into a `Vec<{integer}>`
+    //~| NOTE required by a bound in `collect`
+    process_slice(some_generated_vec);
 }
diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr
index 29fff8c..07dc561 100644
--- a/tests/ui/iterators/collect-into-slice.stderr
+++ b/tests/ui/iterators/collect-into-slice.stderr
@@ -28,6 +28,16 @@
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+  --> $DIR/collect-into-slice.rs:18:38
+   |
+LL |     let some_generated_vec = (0..10).collect();
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
+   |
+   = help: the trait `FromIterator<{integer}>` is not implemented for `&[i32]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/kindck/kindck-send-unsafe.rs b/tests/ui/kindck/kindck-send-unsafe.rs
index 4ef30a7..eb1f2a5 100644
--- a/tests/ui/kindck/kindck-send-unsafe.rs
+++ b/tests/ui/kindck/kindck-send-unsafe.rs
@@ -1,11 +1,15 @@
 extern crate core;
 
-fn assert_send<T:Send>() { }
+fn assert_send<T: Send>() {}
+
+fn test70() {
+    assert_send::<*mut isize>();
+    //~^ ERROR `*mut isize` cannot be sent between threads safely
+}
 
 fn test71<'a>() {
     assert_send::<*mut &'a isize>();
     //~^ ERROR `*mut &'a isize` cannot be sent between threads safely
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master b/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master
deleted file mode 100644
index 3f0444e..0000000
--- a/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master
+++ /dev/null
@@ -1,12 +0,0 @@
-fn assert_send<T:Send>() { }
-
-// unsafe ptrs are ok unless they point at unsendable things
-fn test70() {
-    assert_send::<*mut int>();
-}
-fn test71<'a>() {
-    assert_send::<*mut &'a int>(); //~ ERROR does not fulfill the required lifetime
-}
-
-fn main() {
-}
diff --git a/tests/ui/kindck/kindck-send-unsafe.stderr b/tests/ui/kindck/kindck-send-unsafe.stderr
index ceed005..f1a5054 100644
--- a/tests/ui/kindck/kindck-send-unsafe.stderr
+++ b/tests/ui/kindck/kindck-send-unsafe.stderr
@@ -1,16 +1,29 @@
-error[E0277]: `*mut &'a isize` cannot be sent between threads safely
+error[E0277]: `*mut isize` cannot be sent between threads safely
   --> $DIR/kindck-send-unsafe.rs:6:19
    |
+LL |     assert_send::<*mut isize>();
+   |                   ^^^^^^^^^^ `*mut isize` cannot be sent between threads safely
+   |
+   = help: the trait `Send` is not implemented for `*mut isize`
+note: required by a bound in `assert_send`
+  --> $DIR/kindck-send-unsafe.rs:3:19
+   |
+LL | fn assert_send<T: Send>() {}
+   |                   ^^^^ required by this bound in `assert_send`
+
+error[E0277]: `*mut &'a isize` cannot be sent between threads safely
+  --> $DIR/kindck-send-unsafe.rs:11:19
+   |
 LL |     assert_send::<*mut &'a isize>();
    |                   ^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `*mut &'a isize`
 note: required by a bound in `assert_send`
-  --> $DIR/kindck-send-unsafe.rs:3:18
+  --> $DIR/kindck-send-unsafe.rs:3:19
    |
-LL | fn assert_send<T:Send>() { }
-   |                  ^^^^ required by this bound in `assert_send`
+LL | fn assert_send<T: Send>() {}
+   |                   ^^^^ required by this bound in `assert_send`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/lint/drop_copy.rs b/tests/ui/lint/dropping_copy_types.rs
similarity index 97%
rename from tests/ui/lint/drop_copy.rs
rename to tests/ui/lint/dropping_copy_types.rs
index 0adcd34..2937320 100644
--- a/tests/ui/lint/drop_copy.rs
+++ b/tests/ui/lint/dropping_copy_types.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(drop_copy)]
+#![warn(dropping_copy_types)]
 
 use std::mem::drop;
 use std::vec::Vec;
diff --git a/tests/ui/lint/drop_copy.stderr b/tests/ui/lint/dropping_copy_types.stderr
similarity index 83%
rename from tests/ui/lint/drop_copy.stderr
rename to tests/ui/lint/dropping_copy_types.stderr
index db8e89a..b6291aa 100644
--- a/tests/ui/lint/drop_copy.stderr
+++ b/tests/ui/lint/dropping_copy_types.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:34:5
+  --> $DIR/dropping_copy_types.rs:34:5
    |
 LL |     drop(s1);
    |     ^^^^^--^
@@ -8,13 +8,13 @@
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/drop_copy.rs:3:9
+  --> $DIR/dropping_copy_types.rs:3:9
    |
-LL | #![warn(drop_copy)]
-   |         ^^^^^^^^^
+LL | #![warn(dropping_copy_types)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:35:5
+  --> $DIR/dropping_copy_types.rs:35:5
    |
 LL |     drop(s2);
    |     ^^^^^--^
@@ -24,7 +24,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:36:5
+  --> $DIR/dropping_copy_types.rs:36:5
    |
 LL |     drop(s3);
    |     ^^^^^--^
@@ -32,10 +32,10 @@
    |          argument has type `&SomeStruct`
    |
    = note: use `let _ = ...` to ignore the expression or result
-   = note: `#[warn(drop_ref)]` on by default
+   = note: `#[warn(dropping_references)]` on by default
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:37:5
+  --> $DIR/dropping_copy_types.rs:37:5
    |
 LL |     drop(s4);
    |     ^^^^^--^
@@ -45,7 +45,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:38:5
+  --> $DIR/dropping_copy_types.rs:38:5
    |
 LL |     drop(s5);
    |     ^^^^^--^
@@ -55,7 +55,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:50:5
+  --> $DIR/dropping_copy_types.rs:50:5
    |
 LL |     drop(a2);
    |     ^^^^^--^
@@ -65,7 +65,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:52:5
+  --> $DIR/dropping_copy_types.rs:52:5
    |
 LL |     drop(a4);
    |     ^^^^^--^
@@ -75,7 +75,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:71:13
+  --> $DIR/dropping_copy_types.rs:71:13
    |
 LL |             drop(println_and(13));
    |             ^^^^^---------------^
@@ -85,7 +85,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:74:14
+  --> $DIR/dropping_copy_types.rs:74:14
    |
 LL |         3 if drop(println_and(14)) == () => (),
    |              ^^^^^---------------^
@@ -95,7 +95,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:76:14
+  --> $DIR/dropping_copy_types.rs:76:14
    |
 LL |         4 => drop(2),
    |              ^^^^^-^
diff --git a/tests/ui/lint/drop_ref.rs b/tests/ui/lint/dropping_references.rs
similarity index 98%
rename from tests/ui/lint/drop_ref.rs
rename to tests/ui/lint/dropping_references.rs
index db4f756..0d5d484 100644
--- a/tests/ui/lint/drop_ref.rs
+++ b/tests/ui/lint/dropping_references.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(drop_ref)]
+#![warn(dropping_references)]
 
 struct SomeStruct;
 
diff --git a/tests/ui/lint/drop_ref.stderr b/tests/ui/lint/dropping_references.stderr
similarity index 85%
rename from tests/ui/lint/drop_ref.stderr
rename to tests/ui/lint/dropping_references.stderr
index 04c988f..7e25a46 100644
--- a/tests/ui/lint/drop_ref.stderr
+++ b/tests/ui/lint/dropping_references.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:8:5
+  --> $DIR/dropping_references.rs:8:5
    |
 LL |     drop(&SomeStruct);
    |     ^^^^^-----------^
@@ -8,13 +8,13 @@
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/drop_ref.rs:3:9
+  --> $DIR/dropping_references.rs:3:9
    |
-LL | #![warn(drop_ref)]
-   |         ^^^^^^^^
+LL | #![warn(dropping_references)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:11:5
+  --> $DIR/dropping_references.rs:11:5
    |
 LL |     drop(&owned1);
    |     ^^^^^-------^
@@ -24,7 +24,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:12:5
+  --> $DIR/dropping_references.rs:12:5
    |
 LL |     drop(&&owned1);
    |     ^^^^^--------^
@@ -34,7 +34,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:13:5
+  --> $DIR/dropping_references.rs:13:5
    |
 LL |     drop(&mut owned1);
    |     ^^^^^-----------^
@@ -44,7 +44,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:17:5
+  --> $DIR/dropping_references.rs:17:5
    |
 LL |     drop(reference1);
    |     ^^^^^----------^
@@ -54,7 +54,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:20:5
+  --> $DIR/dropping_references.rs:20:5
    |
 LL |     drop(reference2);
    |     ^^^^^----------^
@@ -64,7 +64,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:23:5
+  --> $DIR/dropping_references.rs:23:5
    |
 LL |     drop(reference3);
    |     ^^^^^----------^
@@ -74,7 +74,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:28:5
+  --> $DIR/dropping_references.rs:28:5
    |
 LL |     drop(&val);
    |     ^^^^^----^
@@ -84,7 +84,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:36:5
+  --> $DIR/dropping_references.rs:36:5
    |
 LL |     std::mem::drop(&SomeStruct);
    |     ^^^^^^^^^^^^^^^-----------^
@@ -94,7 +94,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:91:13
+  --> $DIR/dropping_references.rs:91:13
    |
 LL |             drop(println_and(&13));
    |             ^^^^^----------------^
@@ -104,7 +104,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:94:14
+  --> $DIR/dropping_references.rs:94:14
    |
 LL |         3 if drop(println_and(&14)) == () => (),
    |              ^^^^^----------------^
@@ -114,7 +114,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:96:14
+  --> $DIR/dropping_references.rs:96:14
    |
 LL |         4 => drop(&2),
    |              ^^^^^--^
diff --git a/tests/ui/lint/forget_copy.rs b/tests/ui/lint/forgetting_copy_types.rs
similarity index 96%
rename from tests/ui/lint/forget_copy.rs
rename to tests/ui/lint/forgetting_copy_types.rs
index a6b17b7..224c7bc 100644
--- a/tests/ui/lint/forget_copy.rs
+++ b/tests/ui/lint/forgetting_copy_types.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(forget_copy)]
+#![warn(forgetting_copy_types)]
 
 use std::mem::forget;
 use std::vec::Vec;
diff --git a/tests/ui/lint/forget_copy.stderr b/tests/ui/lint/forgetting_copy_types.stderr
similarity index 81%
rename from tests/ui/lint/forget_copy.stderr
rename to tests/ui/lint/forgetting_copy_types.stderr
index 37bc8a8..36d1ef5 100644
--- a/tests/ui/lint/forget_copy.stderr
+++ b/tests/ui/lint/forgetting_copy_types.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
-  --> $DIR/forget_copy.rs:34:5
+  --> $DIR/forgetting_copy_types.rs:34:5
    |
 LL |     forget(s1);
    |     ^^^^^^^--^
@@ -8,13 +8,13 @@
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/forget_copy.rs:3:9
+  --> $DIR/forgetting_copy_types.rs:3:9
    |
-LL | #![warn(forget_copy)]
-   |         ^^^^^^^^^^^
+LL | #![warn(forgetting_copy_types)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
-  --> $DIR/forget_copy.rs:35:5
+  --> $DIR/forgetting_copy_types.rs:35:5
    |
 LL |     forget(s2);
    |     ^^^^^^^--^
@@ -24,7 +24,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:36:5
+  --> $DIR/forgetting_copy_types.rs:36:5
    |
 LL |     forget(s3);
    |     ^^^^^^^--^
@@ -32,10 +32,10 @@
    |            argument has type `&SomeStruct`
    |
    = note: use `let _ = ...` to ignore the expression or result
-   = note: `#[warn(forget_ref)]` on by default
+   = note: `#[warn(forgetting_references)]` on by default
 
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
-  --> $DIR/forget_copy.rs:37:5
+  --> $DIR/forgetting_copy_types.rs:37:5
    |
 LL |     forget(s4);
    |     ^^^^^^^--^
@@ -45,7 +45,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:38:5
+  --> $DIR/forgetting_copy_types.rs:38:5
    |
 LL |     forget(s5);
    |     ^^^^^^^--^
@@ -55,7 +55,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:50:5
+  --> $DIR/forgetting_copy_types.rs:50:5
    |
 LL |     forget(a2);
    |     ^^^^^^^--^
@@ -65,7 +65,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:52:5
+  --> $DIR/forgetting_copy_types.rs:52:5
    |
 LL |     forget(a3);
    |     ^^^^^^^--^
@@ -75,7 +75,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:53:5
+  --> $DIR/forgetting_copy_types.rs:53:5
    |
 LL |     forget(a4);
    |     ^^^^^^^--^
diff --git a/tests/ui/lint/forget_ref.rs b/tests/ui/lint/forgetting_references.rs
similarity index 96%
rename from tests/ui/lint/forget_ref.rs
rename to tests/ui/lint/forgetting_references.rs
index 13f6d4b..bd51e98 100644
--- a/tests/ui/lint/forget_ref.rs
+++ b/tests/ui/lint/forgetting_references.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(forget_ref)]
+#![warn(forgetting_references)]
 
 use std::mem::forget;
 
diff --git a/tests/ui/lint/forget_ref.stderr b/tests/ui/lint/forgetting_references.stderr
similarity index 84%
rename from tests/ui/lint/forget_ref.stderr
rename to tests/ui/lint/forgetting_references.stderr
index 63fc779..5624b69 100644
--- a/tests/ui/lint/forget_ref.stderr
+++ b/tests/ui/lint/forgetting_references.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:10:5
+  --> $DIR/forgetting_references.rs:10:5
    |
 LL |     forget(&SomeStruct);
    |     ^^^^^^^-----------^
@@ -8,13 +8,13 @@
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/forget_ref.rs:3:9
+  --> $DIR/forgetting_references.rs:3:9
    |
-LL | #![warn(forget_ref)]
-   |         ^^^^^^^^^^
+LL | #![warn(forgetting_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:13:5
+  --> $DIR/forgetting_references.rs:13:5
    |
 LL |     forget(&owned);
    |     ^^^^^^^------^
@@ -24,7 +24,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:14:5
+  --> $DIR/forgetting_references.rs:14:5
    |
 LL |     forget(&&owned);
    |     ^^^^^^^-------^
@@ -34,7 +34,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:15:5
+  --> $DIR/forgetting_references.rs:15:5
    |
 LL |     forget(&mut owned);
    |     ^^^^^^^----------^
@@ -44,7 +44,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:19:5
+  --> $DIR/forgetting_references.rs:19:5
    |
 LL |     forget(&*reference1);
    |     ^^^^^^^------------^
@@ -54,7 +54,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:22:5
+  --> $DIR/forgetting_references.rs:22:5
    |
 LL |     forget(reference2);
    |     ^^^^^^^----------^
@@ -64,7 +64,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:25:5
+  --> $DIR/forgetting_references.rs:25:5
    |
 LL |     forget(reference3);
    |     ^^^^^^^----------^
@@ -74,7 +74,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:30:5
+  --> $DIR/forgetting_references.rs:30:5
    |
 LL |     forget(&val);
    |     ^^^^^^^----^
@@ -84,7 +84,7 @@
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:38:5
+  --> $DIR/forgetting_references.rs:38:5
    |
 LL |     std::mem::forget(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^-----------^
diff --git a/tests/ui/lint/issue-111359.rs b/tests/ui/lint/issue-111359.rs
new file mode 100644
index 0000000..e390c3f
--- /dev/null
+++ b/tests/ui/lint/issue-111359.rs
@@ -0,0 +1,27 @@
+#[deny(missing_debug_implementations)]
+#[deny(missing_copy_implementations)]
+
+mod priv_mod {
+    use std::convert::TryFrom;
+
+    pub struct BarPub;
+    //~^ ERROR type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
+    //~| ERROR type could implement `Copy`; consider adding `impl Copy`
+    struct BarPriv;
+
+    impl<'a> TryFrom<BarPriv> for u8 {
+        type Error = ();
+        fn try_from(o: BarPriv) -> Result<Self, ()> {
+            unimplemented!()
+        }
+    }
+
+    impl<'a> TryFrom<BarPub> for u8 {
+        type Error = ();
+        fn try_from(o: BarPub) -> Result<Self, ()> {
+            unimplemented!()
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/issue-111359.stderr b/tests/ui/lint/issue-111359.stderr
new file mode 100644
index 0000000..2296d84
--- /dev/null
+++ b/tests/ui/lint/issue-111359.stderr
@@ -0,0 +1,26 @@
+error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
+  --> $DIR/issue-111359.rs:7:5
+   |
+LL |     pub struct BarPub;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-111359.rs:1:8
+   |
+LL | #[deny(missing_debug_implementations)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type could implement `Copy`; consider adding `impl Copy`
+  --> $DIR/issue-111359.rs:7:5
+   |
+LL |     pub struct BarPub;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-111359.rs:2:8
+   |
+LL | #[deny(missing_copy_implementations)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/lint-attr-everywhere-early.rs b/tests/ui/lint/lint-attr-everywhere-early.rs
index fd0c4b4..0c820ef 100644
--- a/tests/ui/lint/lint-attr-everywhere-early.rs
+++ b/tests/ui/lint/lint-attr-everywhere-early.rs
@@ -134,6 +134,14 @@
         }
     }
 
+    match f {
+        #[deny(ellipsis_inclusive_range_patterns)]
+        Match{f1: 0...100} => {}
+        //~^ ERROR range patterns are deprecated
+        //~| WARNING this is accepted in the current edition
+        _ => {}
+    }
+
     // Statement Block
     {
         #![deny(unsafe_code)]
diff --git a/tests/ui/lint/lint-attr-everywhere-early.stderr b/tests/ui/lint/lint-attr-everywhere-early.stderr
index d6c6d5f..fac0eb4 100644
--- a/tests/ui/lint/lint-attr-everywhere-early.stderr
+++ b/tests/ui/lint/lint-attr-everywhere-early.stderr
@@ -384,92 +384,106 @@
 LL |         #[deny(while_true)]
    |                ^^^^^^^^^^
 
+error: `...` range patterns are deprecated
+  --> $DIR/lint-attr-everywhere-early.rs:139:20
+   |
+LL |         Match{f1: 0...100} => {}
+   |                    ^^^ help: use `..=` for an inclusive range
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+note: the lint level is defined here
+  --> $DIR/lint-attr-everywhere-early.rs:138:16
+   |
+LL |         #[deny(ellipsis_inclusive_range_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: usage of an `unsafe` block
-  --> $DIR/lint-attr-everywhere-early.rs:140:9
+  --> $DIR/lint-attr-everywhere-early.rs:148:9
    |
 LL |         unsafe {}
    |         ^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:139:17
+  --> $DIR/lint-attr-everywhere-early.rs:147:17
    |
 LL |         #![deny(unsafe_code)]
    |                 ^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-attr-everywhere-early.rs:144:9
+  --> $DIR/lint-attr-everywhere-early.rs:152:9
    |
 LL |         unsafe {}
    |         ^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:143:16
+  --> $DIR/lint-attr-everywhere-early.rs:151:16
    |
 LL |         #[deny(unsafe_code)]
    |                ^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-attr-everywhere-early.rs:149:5
+  --> $DIR/lint-attr-everywhere-early.rs:157:5
    |
 LL |     unsafe {};
    |     ^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:148:12
+  --> $DIR/lint-attr-everywhere-early.rs:156:12
    |
 LL |     #[deny(unsafe_code)]
    |            ^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-attr-everywhere-early.rs:151:27
+  --> $DIR/lint-attr-everywhere-early.rs:159:27
    |
 LL |     [#[deny(unsafe_code)] unsafe {123}];
    |                           ^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:151:13
+  --> $DIR/lint-attr-everywhere-early.rs:159:13
    |
 LL |     [#[deny(unsafe_code)] unsafe {123}];
    |             ^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-attr-everywhere-early.rs:152:27
+  --> $DIR/lint-attr-everywhere-early.rs:160:27
    |
 LL |     (#[deny(unsafe_code)] unsafe {123},);
    |                           ^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:152:13
+  --> $DIR/lint-attr-everywhere-early.rs:160:13
    |
 LL |     (#[deny(unsafe_code)] unsafe {123},);
    |             ^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-attr-everywhere-early.rs:154:31
+  --> $DIR/lint-attr-everywhere-early.rs:162:31
    |
 LL |     call(#[deny(unsafe_code)] unsafe {123});
    |                               ^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:154:17
+  --> $DIR/lint-attr-everywhere-early.rs:162:17
    |
 LL |     call(#[deny(unsafe_code)] unsafe {123});
    |                 ^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-attr-everywhere-early.rs:156:38
+  --> $DIR/lint-attr-everywhere-early.rs:164:38
    |
 LL |     TupleStruct(#[deny(unsafe_code)] unsafe {123});
    |                                      ^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:156:24
+  --> $DIR/lint-attr-everywhere-early.rs:164:24
    |
 LL |     TupleStruct(#[deny(unsafe_code)] unsafe {123});
    |                        ^^^^^^^^^^^
 
 error: `...` range patterns are deprecated
-  --> $DIR/lint-attr-everywhere-early.rs:167:18
+  --> $DIR/lint-attr-everywhere-early.rs:175:18
    |
 LL |             f1: 0...100,
    |                  ^^^ help: use `..=` for an inclusive range
@@ -477,10 +491,10 @@
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-early.rs:166:20
+  --> $DIR/lint-attr-everywhere-early.rs:174:20
    |
 LL |             #[deny(ellipsis_inclusive_range_patterns)]
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 36 previous errors
+error: aborting due to 37 previous errors
 
diff --git a/tests/ui/lint/lint-attr-everywhere-late.rs b/tests/ui/lint/lint-attr-everywhere-late.rs
index 1055157..a24355b 100644
--- a/tests/ui/lint/lint-attr-everywhere-late.rs
+++ b/tests/ui/lint/lint-attr-everywhere-late.rs
@@ -162,6 +162,11 @@
         }
     }
 
+    match 123 {
+        #[deny(non_snake_case)]
+        ARM_VAR => {} //~ ERROR variable `ARM_VAR` should have a snake case name
+    }
+
     // Statement Block
     {
         #![deny(enum_intrinsics_non_enums)]
diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr
index a69c2e0..9587556 100644
--- a/tests/ui/lint/lint-attr-everywhere-late.stderr
+++ b/tests/ui/lint/lint-attr-everywhere-late.stderr
@@ -305,124 +305,136 @@
 LL |         #[deny(enum_intrinsics_non_enums)]
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: variable `ARM_VAR` should have a snake case name
+  --> $DIR/lint-attr-everywhere-late.rs:167:9
+   |
+LL |         ARM_VAR => {}
+   |         ^^^^^^^ help: convert the identifier to snake case: `arm_var`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-attr-everywhere-late.rs:166:16
+   |
+LL |         #[deny(non_snake_case)]
+   |                ^^^^^^^^^^^^^^
+
 error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
-  --> $DIR/lint-attr-everywhere-late.rs:168:9
+  --> $DIR/lint-attr-everywhere-late.rs:173:9
    |
 LL |         discriminant::<i32>(&123);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
-  --> $DIR/lint-attr-everywhere-late.rs:168:29
+  --> $DIR/lint-attr-everywhere-late.rs:173:29
    |
 LL |         discriminant::<i32>(&123);
    |                             ^^^^
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:167:17
+  --> $DIR/lint-attr-everywhere-late.rs:172:17
    |
 LL |         #![deny(enum_intrinsics_non_enums)]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
-  --> $DIR/lint-attr-everywhere-late.rs:172:9
+  --> $DIR/lint-attr-everywhere-late.rs:177:9
    |
 LL |         discriminant::<i32>(&123);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
-  --> $DIR/lint-attr-everywhere-late.rs:172:29
+  --> $DIR/lint-attr-everywhere-late.rs:177:29
    |
 LL |         discriminant::<i32>(&123);
    |                             ^^^^
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:171:16
+  --> $DIR/lint-attr-everywhere-late.rs:176:16
    |
 LL |         #[deny(enum_intrinsics_non_enums)]
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
-  --> $DIR/lint-attr-everywhere-late.rs:177:5
+  --> $DIR/lint-attr-everywhere-late.rs:182:5
    |
 LL |     discriminant::<i32>(&123);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
-  --> $DIR/lint-attr-everywhere-late.rs:177:25
+  --> $DIR/lint-attr-everywhere-late.rs:182:25
    |
 LL |     discriminant::<i32>(&123);
    |                         ^^^^
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:176:12
+  --> $DIR/lint-attr-everywhere-late.rs:181:12
    |
 LL |     #[deny(enum_intrinsics_non_enums)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
-  --> $DIR/lint-attr-everywhere-late.rs:179:41
+  --> $DIR/lint-attr-everywhere-late.rs:184:41
    |
 LL |     [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
-  --> $DIR/lint-attr-everywhere-late.rs:179:61
+  --> $DIR/lint-attr-everywhere-late.rs:184:61
    |
 LL |     [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
    |                                                             ^^^^
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:179:13
+  --> $DIR/lint-attr-everywhere-late.rs:184:13
    |
 LL |     [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
-  --> $DIR/lint-attr-everywhere-late.rs:180:41
+  --> $DIR/lint-attr-everywhere-late.rs:185:41
    |
 LL |     (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
-  --> $DIR/lint-attr-everywhere-late.rs:180:61
+  --> $DIR/lint-attr-everywhere-late.rs:185:61
    |
 LL |     (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
    |                                                             ^^^^
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:180:13
+  --> $DIR/lint-attr-everywhere-late.rs:185:13
    |
 LL |     (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
-  --> $DIR/lint-attr-everywhere-late.rs:182:45
+  --> $DIR/lint-attr-everywhere-late.rs:187:45
    |
 LL |     call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
    |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
-  --> $DIR/lint-attr-everywhere-late.rs:182:65
+  --> $DIR/lint-attr-everywhere-late.rs:187:65
    |
 LL |     call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
    |                                                                 ^^^^
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:182:17
+  --> $DIR/lint-attr-everywhere-late.rs:187:17
    |
 LL |     call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
-  --> $DIR/lint-attr-everywhere-late.rs:184:52
+  --> $DIR/lint-attr-everywhere-late.rs:189:52
    |
 LL |     TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
-  --> $DIR/lint-attr-everywhere-late.rs:184:72
+  --> $DIR/lint-attr-everywhere-late.rs:189:72
    |
 LL |     TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
    |                                                                        ^^^^
 note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:184:24
+  --> $DIR/lint-attr-everywhere-late.rs:189:24
    |
 LL |     TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 31 previous errors
+error: aborting due to 32 previous errors
 
diff --git a/tests/ui/lint/lint-match-arms-2.rs b/tests/ui/lint/lint-match-arms-2.rs
new file mode 100644
index 0000000..0c11463
--- /dev/null
+++ b/tests/ui/lint/lint-match-arms-2.rs
@@ -0,0 +1,24 @@
+#![feature(if_let_guard)]
+#![allow(unused, non_snake_case)]
+
+enum E {
+    A,
+}
+
+#[allow(bindings_with_variant_name, irrefutable_let_patterns)]
+fn foo() {
+    match E::A {
+        #[deny(bindings_with_variant_name)]
+        A => {}
+    //~^ ERROR pattern binding `A` is named the same as one of the variants of the type `E`
+    }
+
+    match &E::A {
+        #[deny(irrefutable_let_patterns)]
+        a if let b = a => {}
+    //~^ ERROR irrefutable `if let` guard pattern
+        _ => {}
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/lint/lint-match-arms-2.stderr b/tests/ui/lint/lint-match-arms-2.stderr
new file mode 100644
index 0000000..062d5c1
--- /dev/null
+++ b/tests/ui/lint/lint-match-arms-2.stderr
@@ -0,0 +1,29 @@
+error[E0170]: pattern binding `A` is named the same as one of the variants of the type `E`
+  --> $DIR/lint-match-arms-2.rs:12:9
+   |
+LL |         A => {}
+   |         ^ help: to match on the variant, qualify the path: `E::A`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-match-arms-2.rs:11:16
+   |
+LL |         #[deny(bindings_with_variant_name)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable `if let` guard pattern
+  --> $DIR/lint-match-arms-2.rs:18:18
+   |
+LL |         a if let b = a => {}
+   |                  ^
+   |
+   = note: this pattern will always match, so the guard is useless
+   = help: consider removing the guard and adding a `let` inside the match arm
+note: the lint level is defined here
+  --> $DIR/lint-match-arms-2.rs:17:16
+   |
+LL |         #[deny(irrefutable_let_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0170`.
diff --git a/tests/ui/lint/unused/auxiliary/must-use-foreign.rs b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
new file mode 100644
index 0000000..f773f09
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+use std::future::Future;
+
+pub struct Manager;
+
+impl Manager {
+    #[must_use]
+    pub async fn new() -> (Self, impl Future<Output = ()>) {
+        (Manager, async {})
+    }
+}
diff --git a/tests/ui/lint/unused/must-use-foreign.rs b/tests/ui/lint/unused/must-use-foreign.rs
new file mode 100644
index 0000000..21a1105
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-foreign.rs
@@ -0,0 +1,15 @@
+// edition:2021
+// aux-build:must-use-foreign.rs
+// check-pass
+
+extern crate must_use_foreign;
+
+use must_use_foreign::Manager;
+
+async fn async_main() {
+    Manager::new().await.1.await;
+}
+
+fn main() {
+    let _ = async_main();
+}
diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs
index 4be93aa..6355f47 100644
--- a/tests/ui/lint/unused/unused-async.rs
+++ b/tests/ui/lint/unused/unused-async.rs
@@ -33,7 +33,7 @@
     foo().await; //~ ERROR unused output of future returned by `foo` that must be used
     bar(); //~ ERROR unused return value of `bar` that must be used
     //~^ ERROR unused implementer of `Future` that must be used
-    bar().await; //~ ERROR unused output of future returned by `bar` that must be used
+    bar().await; // ok, it's not an async fn
     baz(); //~ ERROR unused implementer of `Future` that must be used
     baz().await; // ok
 }
diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr
index 1c3702b..e93a406 100644
--- a/tests/ui/lint/unused/unused-async.stderr
+++ b/tests/ui/lint/unused/unused-async.stderr
@@ -52,17 +52,6 @@
 LL |     let _ = bar();
    |     +++++++
 
-error: unused output of future returned by `bar` that must be used
-  --> $DIR/unused-async.rs:36:5
-   |
-LL |     bar().await;
-   |     ^^^^^^^^^^^
-   |
-help: use `let _ = ...` to ignore the resulting value
-   |
-LL |     let _ = bar().await;
-   |     +++++++
-
 error: unused implementer of `Future` that must be used
   --> $DIR/unused-async.rs:37:5
    |
@@ -71,5 +60,5 @@
    |
    = note: futures do nothing unless you `.await` or poll them
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/liveness/liveness-unused.rs b/tests/ui/liveness/liveness-unused.rs
index 8ef6ab1..ba635e6 100644
--- a/tests/ui/liveness/liveness-unused.rs
+++ b/tests/ui/liveness/liveness-unused.rs
@@ -1,7 +1,7 @@
 #![warn(unused)]
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
-#![allow(dead_code, non_camel_case_types, trivial_numeric_casts, drop_copy)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_casts, dropping_copy_types)]
 
 use std::ops::AddAssign;
 
diff --git a/tests/ui/macros/builtin-prelude-no-accidents.stderr b/tests/ui/macros/builtin-prelude-no-accidents.stderr
index 56af618..8cd9a63 100644
--- a/tests/ui/macros/builtin-prelude-no-accidents.stderr
+++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr
@@ -4,18 +4,21 @@
 LL |     env::current_dir;
    |     ^^^ use of undeclared crate or module `env`
 
+error[E0433]: failed to resolve: use of undeclared crate or module `vec`
+  --> $DIR/builtin-prelude-no-accidents.rs:7:14
+   |
+LL |     type B = vec::Vec<u8>;
+   |              ^^^
+   |              |
+   |              use of undeclared crate or module `vec`
+   |              help: a struct with a similar name exists (notice the capitalization): `Vec`
+
 error[E0433]: failed to resolve: use of undeclared crate or module `panic`
   --> $DIR/builtin-prelude-no-accidents.rs:6:14
    |
 LL |     type A = panic::PanicInfo;
    |              ^^^^^ use of undeclared crate or module `panic`
 
-error[E0433]: failed to resolve: use of undeclared crate or module `vec`
-  --> $DIR/builtin-prelude-no-accidents.rs:7:14
-   |
-LL |     type B = vec::Vec<u8>;
-   |              ^^^ use of undeclared crate or module `vec`
-
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/macros/issue-111749.rs b/tests/ui/macros/issue-111749.rs
new file mode 100644
index 0000000..6c45e4e
--- /dev/null
+++ b/tests/ui/macros/issue-111749.rs
@@ -0,0 +1,12 @@
+macro_rules! cbor_map {
+    ($key:expr) => {
+        $key.signum();
+    };
+}
+
+fn main() {
+    cbor_map! { #[test(test)] 4};
+    //~^ ERROR removing an expression is not supported in this position
+    //~| ERROR attribute must be of the form `#[test]`
+    //~| WARNING this was previously accepted by the compiler but is being phased out
+}
diff --git a/tests/ui/macros/issue-111749.stderr b/tests/ui/macros/issue-111749.stderr
new file mode 100644
index 0000000..7db2b8e
--- /dev/null
+++ b/tests/ui/macros/issue-111749.stderr
@@ -0,0 +1,18 @@
+error: removing an expression is not supported in this position
+  --> $DIR/issue-111749.rs:8:17
+   |
+LL |     cbor_map! { #[test(test)] 4};
+   |                 ^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[test]`
+  --> $DIR/issue-111749.rs:8:17
+   |
+LL |     cbor_map! { #[test(test)] 4};
+   |                 ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+   = note: `#[deny(ill_formed_attribute_input)]` on by default
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/panic-temporaries-2018.rs b/tests/ui/macros/panic-temporaries-2018.rs
new file mode 100644
index 0000000..d914df3
--- /dev/null
+++ b/tests/ui/macros/panic-temporaries-2018.rs
@@ -0,0 +1,55 @@
+// check-pass
+// edition:2018
+
+#![allow(non_fmt_panics, unreachable_code)]
+
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
+
+struct NotSend {
+    marker: PhantomData<*const u8>,
+}
+
+const NOT_SEND: NotSend = NotSend { marker: PhantomData };
+
+impl Display for NotSend {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("this value does not implement Send")
+    }
+}
+
+async fn f(_: u8) {}
+
+// Exercises this matcher in panic_2015:
+// ($fmt:expr, $($arg:tt)+) => $crate::panicking::panic_fmt(...)
+async fn panic_fmt() {
+    // Panic returns `!`, so the await is never reached, and in particular the
+    // temporaries inside the formatting machinery are not still alive at the
+    // await point.
+    let todo = "...";
+    f(panic!("not yet implemented: {}", todo)).await;
+}
+
+// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg)
+async fn panic_display() {
+    f(panic!("{}", NOT_SEND)).await;
+}
+
+// Exercises ($msg:expr) => $crate::panicking::panic_str($msg)
+async fn panic_str() {
+    f(panic!((NOT_SEND, "...").1)).await;
+}
+
+// Exercises ($msg:expr) => $crate::panicking::unreachable_display(&$msg)
+async fn unreachable_display() {
+    f(unreachable!(NOT_SEND)).await;
+}
+
+fn require_send(_: impl Send) {}
+
+fn main() {
+    require_send(panic_fmt());
+    require_send(panic_display());
+    require_send(panic_str());
+    require_send(unreachable_display());
+}
diff --git a/tests/ui/macros/panic-temporaries.rs b/tests/ui/macros/panic-temporaries.rs
new file mode 100644
index 0000000..db65601
--- /dev/null
+++ b/tests/ui/macros/panic-temporaries.rs
@@ -0,0 +1,43 @@
+// check-pass
+// edition:2021
+
+#![allow(unreachable_code)]
+
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
+
+struct NotSend {
+    marker: PhantomData<*const u8>,
+}
+
+const NOT_SEND: NotSend = NotSend { marker: PhantomData };
+
+impl Display for NotSend {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("this value does not implement Send")
+    }
+}
+
+async fn f(_: u8) {}
+
+// Exercises this matcher in panic_2021:
+// ($($t:tt)+) => $crate::panicking::panic_fmt(...)
+async fn panic_fmt() {
+    // Panic returns `!`, so the await is never reached, and in particular the
+    // temporaries inside the formatting machinery are not still alive at the
+    // await point.
+    let todo = "...";
+    f(panic!("not yet implemented: {}", todo)).await;
+}
+
+// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg)
+async fn panic_display() {
+    f(panic!("{}", NOT_SEND)).await;
+}
+
+fn require_send(_: impl Send) {}
+
+fn main() {
+    require_send(panic_fmt());
+    require_send(panic_display());
+}
diff --git a/tests/ui/macros/parse-complex-macro-invoc-op.rs b/tests/ui/macros/parse-complex-macro-invoc-op.rs
index c50dfdf..1081038 100644
--- a/tests/ui/macros/parse-complex-macro-invoc-op.rs
+++ b/tests/ui/macros/parse-complex-macro-invoc-op.rs
@@ -4,7 +4,7 @@
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
 #![allow(stable_features)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // Test parsing binary operators after macro invocations.
 
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
index ad97f7a..b69b5bc 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
@@ -26,7 +26,7 @@
 
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem as usize\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -42,7 +42,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: &elem\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -58,7 +58,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem == 1\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -71,7 +71,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem >= 1\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -84,7 +84,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem > 0\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -97,7 +97,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem < 3\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -110,7 +110,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem <= 3\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -123,7 +123,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem != 3\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -139,7 +139,7 @@
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: *elem\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr
index 5fed903..f7bf858 100644
--- a/tests/ui/never_type/exhaustive_patterns.stderr
+++ b/tests/ui/never_type/exhaustive_patterns.stderr
@@ -14,6 +14,7 @@
 LL |     A(A),
 LL |     B(inner::Wrapper<B>),
    |     - not covered
+   = note: pattern `Either::B(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
    = note: the matched value is of type `Either<(), !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/tests/ui/never_type/never-assign-dead-code.rs b/tests/ui/never_type/never-assign-dead-code.rs
index e95a992..39df7de 100644
--- a/tests/ui/never_type/never-assign-dead-code.rs
+++ b/tests/ui/never_type/never-assign-dead-code.rs
@@ -3,7 +3,7 @@
 // check-pass
 
 #![feature(never_type)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 #![warn(unused)]
 
 fn main() {
diff --git a/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
index 73ceaee..2e9eff5 100644
--- a/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
+++ b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
@@ -5,7 +5,7 @@
 // check-pass
 // compile-flags:-Zno-leak-check
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 fn make_it() -> for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 {
     panic!()
diff --git a/tests/ui/nll/ty-outlives/projection-body.rs b/tests/ui/nll/ty-outlives/projection-body.rs
index bff9058..722d674 100644
--- a/tests/ui/nll/ty-outlives/projection-body.rs
+++ b/tests/ui/nll/ty-outlives/projection-body.rs
@@ -3,7 +3,7 @@
 //
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 trait MyTrait<'a> {
     type Output;
diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs
index 5e66e33..31de45b 100644
--- a/tests/ui/offset-of/offset-of-arg-count.rs
+++ b/tests/ui/offset-of/offset-of-arg-count.rs
@@ -12,6 +12,11 @@
     offset_of!(S, f.,); //~ ERROR expected identifier
     offset_of!(S, f..); //~ ERROR no rules expected the token
     offset_of!(S, f..,); //~ ERROR no rules expected the token
+    offset_of!(Lt<'static>, bar); // issue #111657
+    offset_of!(Lt<'_>, bar); // issue #111678
 }
 
 struct S { f: u8, }
+struct Lt<'a> {
+    bar: &'a (),
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs
index a0269ca..3b8dc0b 100644
--- a/tests/ui/offset-of/offset-of-dst-field.rs
+++ b/tests/ui/offset-of/offset-of-dst-field.rs
@@ -26,8 +26,24 @@
     z: Extern,
 }
 
+struct Delta<T: ?Sized> {
+    x: u8,
+    y: u16,
+    z: T,
+}
+
 fn main() {
     offset_of!(Alpha, z); //~ ERROR the size for values of type
     offset_of!(Beta, z); //~ ERROR the size for values of type
     offset_of!(Gamma, z); //~ ERROR the size for values of type
 }
+
+fn delta() {
+    offset_of!(Delta<Alpha>, z); //~ ERROR the size for values of type
+    offset_of!(Delta<Extern>, z); //~ ERROR the size for values of type
+    offset_of!(Delta<dyn Trait>, z); //~ ERROR the size for values of type
+}
+
+fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+    offset_of!(Delta<T>, z) //~ ERROR the size for values of type
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
index e6e0f49..128c783 100644
--- a/tests/ui/offset-of/offset-of-dst-field.stderr
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:30:5
+  --> $DIR/offset-of-dst-field.rs:36:5
    |
 LL |     offset_of!(Alpha, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -8,7 +8,7 @@
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:31:5
+  --> $DIR/offset-of-dst-field.rs:37:5
    |
 LL |     offset_of!(Beta, z);
    |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -17,7 +17,7 @@
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `Extern` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:32:5
+  --> $DIR/offset-of-dst-field.rs:38:5
    |
 LL |     offset_of!(Gamma, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -25,6 +25,53 @@
    = help: the trait `Sized` is not implemented for `Extern`
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors
+error[E0277]: the size for values of type `Extern` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:43:5
+   |
+LL |     offset_of!(Delta<Extern>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `Extern`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:44:5
+   |
+LL |     offset_of!(Delta<dyn Trait>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `dyn Trait`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:42:5
+   |
+LL |     offset_of!(Delta<Alpha>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `Alpha`
+  --> $DIR/offset-of-dst-field.rs:5:8
+   |
+LL | struct Alpha {
+   |        ^^^^^
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:48:5
+   |
+LL | fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+   |                             - this type parameter needs to be `std::marker::Sized`
+LL |     offset_of!(Delta<T>, z)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+LL + fn generic_with_maybe_sized<T>() -> usize {
+   |
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/offset-of/offset-of-inference.rs b/tests/ui/offset-of/offset-of-inference.rs
new file mode 100644
index 0000000..ba87574
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-inference.rs
@@ -0,0 +1,11 @@
+// Test that inference types in `offset_of!` don't ICE.
+
+#![feature(offset_of)]
+
+struct Foo<T> {
+    x: T,
+}
+
+fn main() {
+    let _ = core::mem::offset_of!(Foo<_>, x); //~ ERROR: type annotations needed
+}
diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr
new file mode 100644
index 0000000..2a520f6
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-inference.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/offset-of-inference.rs:10:35
+   |
+LL |     let _ = core::mem::offset_of!(Foo<_>, x);
+   |                                   ^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs
new file mode 100644
index 0000000..50c2e93
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.rs
@@ -0,0 +1,20 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+
+fn main() {
+    let _: u8 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u16 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u32 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u64 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: isize = offset_of!(S, v); //~ ERROR mismatched types
+    let _: usize = offset_of!(S, v);
+
+    offset_of!(S, v) //~ ERROR mismatched types
+}
diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr
new file mode 100644
index 0000000..6f8c947
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.stderr
@@ -0,0 +1,64 @@
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:12:17
+   |
+LL |     let _: u8 = offset_of!(S, v);
+   |            --   ^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:13:18
+   |
+LL |     let _: u16 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u16`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:14:18
+   |
+LL |     let _: u32 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:15:18
+   |
+LL |     let _: u64 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:16:20
+   |
+LL |     let _: isize = offset_of!(S, v);
+   |            -----   ^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:19:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+...
+LL |     offset_of!(S, v)
+   |     ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
index 0291b78..6b1a16b 100644
--- a/tests/ui/offset-of/offset-of-private.rs
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -8,9 +8,21 @@
         pub public: u8,
         private: u8,
     }
+    #[repr(C)]
+    pub struct FooTuple(pub u8, u8);
+    #[repr(C)]
+    struct Bar {
+        pub public: u8,
+        private: u8,
+    }
 }
 
 fn main() {
     offset_of!(m::Foo, public);
     offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
+    offset_of!(m::FooTuple, 0);
+    offset_of!(m::FooTuple, 1); //~ ERROR field `1` of struct `FooTuple` is private
+    offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private
+    offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private
+    //~| ERROR field `private` of struct `Bar` is private
 }
diff --git a/tests/ui/offset-of/offset-of-private.stderr b/tests/ui/offset-of/offset-of-private.stderr
index 8a186dd..0674b58 100644
--- a/tests/ui/offset-of/offset-of-private.stderr
+++ b/tests/ui/offset-of/offset-of-private.stderr
@@ -1,9 +1,46 @@
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:25:19
+   |
+LL |     offset_of!(m::Bar, public);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:19
+   |
+LL |     offset_of!(m::Bar, private);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
 error[E0616]: field `private` of struct `Foo` is private
-  --> $DIR/offset-of-private.rs:15:24
+  --> $DIR/offset-of-private.rs:22:24
    |
 LL |     offset_of!(m::Foo, private);
    |                        ^^^^^^^ private field
 
-error: aborting due to previous error
+error[E0616]: field `1` of struct `FooTuple` is private
+  --> $DIR/offset-of-private.rs:24:29
+   |
+LL |     offset_of!(m::FooTuple, 1);
+   |                             ^ private field
 
-For more information about this error, try `rustc --explain E0616`.
+error[E0616]: field `private` of struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:24
+   |
+LL |     offset_of!(m::Bar, private);
+   |                        ^^^^^^^ private field
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0603, E0616.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs
new file mode 100644
index 0000000..dbeef0e7
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.rs
@@ -0,0 +1,58 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct C<T> {
+    v: T,
+    w: T,
+}
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+impl S {
+    fn v_offs() -> usize {
+        offset_of!(Self, v)
+    }
+    fn v_offs_wrong_syntax() {
+        offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::`
+        offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self`
+        //~| no field `Self` on type `S`
+    }
+    fn offs_in_c() -> usize {
+        offset_of!(C<Self>, w)
+    }
+    fn offs_in_c_colon() -> usize {
+        offset_of!(C::<Self>, w)
+    }
+}
+
+mod m {
+    use std::mem::offset_of;
+    fn off() {
+        offset_of!(self::S, v); //~ ERROR cannot find type `S` in module
+        offset_of!(super::S, v);
+        offset_of!(crate::S, v);
+    }
+    impl super::n::T {
+        fn v_offs_self() -> usize {
+            offset_of!(Self, v) //~ ERROR field `v` of struct `T` is private
+        }
+    }
+}
+
+mod n {
+    pub struct T { v: u8, }
+}
+
+fn main() {
+    offset_of!(self::S, v);
+    offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope
+
+    offset_of!(S, self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `S`
+    offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `u8`
+}
diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr
new file mode 100644
index 0000000..df55546
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.stderr
@@ -0,0 +1,79 @@
+error: no rules expected the token `::`
+  --> $DIR/offset-of-self.rs:20:30
+   |
+LL |         offset_of!(Self, Self::v);
+   |                              ^^ no rules expected this token in macro call
+   |
+   = note: while trying to match sequence start
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^ expected identifier, found keyword
+
+error[E0412]: cannot find type `S` in module `self`
+  --> $DIR/offset-of-self.rs:35:26
+   |
+LL |         offset_of!(self::S, v);
+   |                          ^ not found in `self`
+   |
+help: consider importing this struct
+   |
+LL +     use S;
+   |
+help: if you import `S`, refer to it directly
+   |
+LL -         offset_of!(self::S, v);
+LL +         offset_of!(S, v);
+   |
+
+error[E0411]: cannot find type `Self` in this scope
+  --> $DIR/offset-of-self.rs:52:16
+   |
+LL | fn main() {
+   |    ---- `Self` not allowed in a function
+LL |     offset_of!(self::S, v);
+LL |     offset_of!(Self, v);
+   |                ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error[E0609]: no field `Self` on type `S`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^
+
+error[E0616]: field `v` of struct `T` is private
+  --> $DIR/offset-of-self.rs:41:30
+   |
+LL |             offset_of!(Self, v)
+   |                              ^ private field
+
+error[E0609]: no field `self` on type `S`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^
+
+error[E0609]: no field `self` on type `u8`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0411, E0412, E0609, E0616.
+For more information about an error, try `rustc --explain E0411`.
diff --git a/tests/ui/or-patterns/or-patterns-default-binding-modes.rs b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
index c138d99..df6aab0 100644
--- a/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
+++ b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
@@ -3,8 +3,8 @@
 // check-pass
 
 #![allow(irrefutable_let_patterns)]
-#![allow(drop_copy)]
-#![allow(drop_ref)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 
 fn main() {
     // A regression test for a mistake we made at one point:
diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr
index ddbfc4e..815ce4d 100644
--- a/tests/ui/panics/default-backtrace-ice.stderr
+++ b/tests/ui/panics/default-backtrace-ice.stderr
@@ -8,6 +8,8 @@
 stack backtrace:
 (end_short_backtrace)
 (begin_short_backtrace)
+(end_short_backtrace)
+(begin_short_backtrace)
 
 error: the compiler unexpectedly panicked. this is a bug.
 
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
new file mode 100644
index 0000000..38a80f8
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
@@ -0,0 +1,61 @@
+// compile-flags:-Cstrip=none
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=1
+// ignore-android FIXME #17520
+// ignore-wasm no panic support
+// ignore-openbsd no support for libbacktrace without filename
+// ignore-emscripten no panic
+// ignore-sgx Backtraces not symbolized
+// ignore-fuchsia Backtraces not symbolized
+// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
+
+/// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace`
+
+#[inline(never)]
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+#[inline(never)]
+fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+fn first() {
+    __rust_end_short_backtrace(|| second());
+}
+
+fn second() {
+    third(); // won't show up
+}
+
+fn third() {
+    fourth(); // won't show up
+}
+
+fn fourth() {
+    __rust_begin_short_backtrace(|| fifth());
+}
+
+fn fifth() {
+    __rust_end_short_backtrace(|| sixth());
+}
+
+fn sixth() {
+    seven(); // won't show up
+}
+
+fn seven() {
+    __rust_begin_short_backtrace(|| eight());
+}
+
+fn eight() {
+    panic!("debug!!!");
+}
+
+fn main() {
+    first();
+}
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
new file mode 100644
index 0000000..2592b74
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
@@ -0,0 +1,11 @@
+thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames-2.rs:56:5
+stack backtrace:
+   0: std::panicking::begin_panic
+   1: short_ice_remove_middle_frames_2::eight
+   2: short_ice_remove_middle_frames_2::seven::{{closure}}
+   3: short_ice_remove_middle_frames_2::fifth
+   4: short_ice_remove_middle_frames_2::fourth::{{closure}}
+   5: short_ice_remove_middle_frames_2::first
+   6: short_ice_remove_middle_frames_2::main
+   7: core::ops::function::FnOnce::call_once
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs
new file mode 100644
index 0000000..c872084
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames.rs
@@ -0,0 +1,57 @@
+// compile-flags:-Cstrip=none
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=1
+// ignore-android FIXME #17520
+// ignore-wasm no panic support
+// ignore-openbsd no support for libbacktrace without filename
+// ignore-emscripten no panic
+// ignore-sgx Backtraces not symbolized
+// ignore-fuchsia Backtraces not symbolized
+// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
+
+
+#[inline(never)]
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+#[inline(never)]
+fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+fn first() {
+    __rust_end_short_backtrace(|| second());
+    // do not take effect since we already has a inner call of __rust_end_short_backtrace
+}
+
+fn second() {
+    __rust_end_short_backtrace(|| third());
+}
+
+fn third() {
+    fourth(); // won't show up in backtrace
+}
+
+fn fourth() {
+    fifth(); // won't show up in backtrace
+}
+
+fn fifth() {
+    __rust_begin_short_backtrace(|| sixth());
+}
+
+fn sixth() {
+    seven();
+}
+
+fn seven() {
+    panic!("debug!!!");
+}
+
+fn main() {
+    first();
+}
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
new file mode 100644
index 0000000..9c15f2e
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
@@ -0,0 +1,12 @@
+thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames.rs:52:5
+stack backtrace:
+   0: std::panicking::begin_panic
+   1: short_ice_remove_middle_frames::seven
+   2: short_ice_remove_middle_frames::sixth
+   3: short_ice_remove_middle_frames::fifth::{{closure}}
+   4: short_ice_remove_middle_frames::second
+   5: short_ice_remove_middle_frames::first::{{closure}}
+   6: short_ice_remove_middle_frames::first
+   7: short_ice_remove_middle_frames::main
+   8: core::ops::function::FnOnce::call_once
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr
index 653be5b..e34d855 100644
--- a/tests/ui/parser/dyn-trait-compatibility.stderr
+++ b/tests/ui/parser/dyn-trait-compatibility.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
-  --> $DIR/dyn-trait-compatibility.rs:3:11
-   |
-LL | type A1 = dyn::dyn;
-   |           ^^^ use of undeclared crate or module `dyn`
-
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:1:11
    |
@@ -46,6 +40,12 @@
 LL | type A3 = dyn<<dyn as dyn>::dyn>;
    |                ^^^ not found in this scope
 
+error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
+  --> $DIR/dyn-trait-compatibility.rs:3:11
+   |
+LL | type A1 = dyn::dyn;
+   |           ^^^ use of undeclared crate or module `dyn`
+
 error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0405, E0412, E0433.
diff --git a/tests/ui/parser/impl-on-unsized-typo.rs b/tests/ui/parser/impl-on-unsized-typo.rs
new file mode 100644
index 0000000..e09c046
--- /dev/null
+++ b/tests/ui/parser/impl-on-unsized-typo.rs
@@ -0,0 +1,6 @@
+trait Tr {}
+
+impl<T ?Sized> Tr for T {}
+//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `?`
+
+fn main() {}
diff --git a/tests/ui/parser/impl-on-unsized-typo.stderr b/tests/ui/parser/impl-on-unsized-typo.stderr
new file mode 100644
index 0000000..23dcc1e
--- /dev/null
+++ b/tests/ui/parser/impl-on-unsized-typo.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,`, `:`, `=`, or `>`, found `?`
+  --> $DIR/impl-on-unsized-typo.rs:3:8
+   |
+LL | impl<T ?Sized> Tr for T {}
+   |        ^ expected one of `,`, `:`, `=`, or `>`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issues/issue-111416.rs b/tests/ui/parser/issues/issue-111416.rs
new file mode 100644
index 0000000..cfd1b6b
--- /dev/null
+++ b/tests/ui/parser/issues/issue-111416.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let my = monad_bind(mx, T: Try); //~ ERROR invalid `struct` delimiters or `fn` call arguments
+}
diff --git a/tests/ui/parser/issues/issue-111416.stderr b/tests/ui/parser/issues/issue-111416.stderr
new file mode 100644
index 0000000..ddacf4d
--- /dev/null
+++ b/tests/ui/parser/issues/issue-111416.stderr
@@ -0,0 +1,18 @@
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-111416.rs:2:14
+   |
+LL |     let my = monad_bind(mx, T: Try);
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if `monad_bind` is a struct, use braces as delimiters
+   |
+LL |     let my = monad_bind { mx, T: Try };
+   |                         ~            ~
+help: if `monad_bind` is a function, use the arguments directly
+   |
+LL -     let my = monad_bind(mx, T: Try);
+LL +     let my = monad_bind(mx, Try);
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
index 965204b..43b53b7 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
@@ -2,8 +2,8 @@
 
 // Test `@` patterns combined with `box` patterns.
 
-#![allow(drop_ref)]
-#![allow(drop_copy)]
+#![allow(dropping_references)]
+#![allow(dropping_copy_types)]
 
 #![feature(box_patterns)]
 
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
index 3eb5d2c..1df51c0 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
@@ -2,7 +2,7 @@
 
 // Test `Copy` bindings in the rhs of `@` patterns.
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 #[derive(Copy, Clone)]
 struct C;
diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
index 0550238..204cd3e 100644
--- a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
+++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {}
 
diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
index 788975d..4de1f65 100644
--- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
+++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {
     struct U;
diff --git a/tests/ui/pattern/pattern-error-continue.stderr b/tests/ui/pattern/pattern-error-continue.stderr
index e1349fb..10fcccb 100644
--- a/tests/ui/pattern/pattern-error-continue.stderr
+++ b/tests/ui/pattern/pattern-error-continue.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared type `E`
-  --> $DIR/pattern-error-continue.rs:33:9
-   |
-LL |         E::V => {}
-   |         ^ use of undeclared type `E`
-
 error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D`
   --> $DIR/pattern-error-continue.rs:18:9
    |
@@ -56,6 +50,15 @@
 LL | fn f(_c: char) {}
    |    ^ --------
 
+error[E0433]: failed to resolve: use of undeclared type `E`
+  --> $DIR/pattern-error-continue.rs:33:9
+   |
+LL |         E::V => {}
+   |         ^
+   |         |
+   |         use of undeclared type `E`
+   |         help: an enum with a similar name exists: `A`
+
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0023, E0308, E0433, E0532.
diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs
index ca4fcd8..c10c620 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.rs
+++ b/tests/ui/pattern/usefulness/consts-opaque.rs
@@ -20,11 +20,12 @@
 #[derive(PartialEq)]
 enum Baz {
     Baz1,
-    Baz2
+    Baz2,
 }
 impl Eq for Baz {}
 const BAZ: Baz = Baz::Baz1;
 
+#[rustfmt::skip]
 fn main() {
     match FOO {
         FOO => {}
@@ -124,8 +125,16 @@
 
     match WRAPQUUX {
         Wrap(_) => {}
-        WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
-        //~^ ERROR unreachable pattern
+        WRAPQUUX => {}
+    }
+
+    match WRAPQUUX {
+        Wrap(_) => {}
+    }
+
+    match WRAPQUUX {
+        //~^ ERROR: non-exhaustive patterns: `Wrap(_)` not covered
+        WRAPQUUX => {}
     }
 
     #[derive(PartialEq, Eq)]
@@ -138,8 +147,7 @@
     match WHOKNOWSQUUX {
         WHOKNOWSQUUX => {}
         WhoKnows::Yay(_) => {}
-        WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
-        //~^ ERROR unreachable pattern
+        WHOKNOWSQUUX => {}
         WhoKnows::Nope => {}
     }
 }
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
index 3f0b4a9..e01b06c 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.stderr
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -1,5 +1,5 @@
 error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:30:9
+  --> $DIR/consts-opaque.rs:31:9
    |
 LL |         FOO => {}
    |         ^^^
@@ -8,7 +8,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:37:9
+  --> $DIR/consts-opaque.rs:38:9
    |
 LL |         FOO_REF => {}
    |         ^^^^^^^
@@ -17,7 +17,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:45:9
+  --> $DIR/consts-opaque.rs:46:9
    |
 LL |         FOO_REF_REF => {}
    |         ^^^^^^^^^^^
@@ -29,7 +29,7 @@
    = note: `#[warn(indirect_structural_match)]` on by default
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:53:9
+  --> $DIR/consts-opaque.rs:54:9
    |
 LL |         BAR => {} // should not be emitting unreachable warning
    |         ^^^
@@ -38,7 +38,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:61:9
+  --> $DIR/consts-opaque.rs:62:9
    |
 LL |         BAR => {}
    |         ^^^
@@ -47,7 +47,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:70:9
+  --> $DIR/consts-opaque.rs:71:9
    |
 LL |         BAR => {}
    |         ^^^
@@ -56,7 +56,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:72:9
+  --> $DIR/consts-opaque.rs:73:9
    |
 LL |         BAR => {} // should not be emitting unreachable warning
    |         ^^^
@@ -65,7 +65,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:80:9
+  --> $DIR/consts-opaque.rs:81:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -74,7 +74,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:90:9
+  --> $DIR/consts-opaque.rs:91:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -83,7 +83,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:97:9
+  --> $DIR/consts-opaque.rs:98:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -92,7 +92,7 @@
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:32:9
+  --> $DIR/consts-opaque.rs:33:9
    |
 LL |         FOO => {}
    |         --- matches any value
@@ -107,7 +107,7 @@
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:39:9
+  --> $DIR/consts-opaque.rs:40:9
    |
 LL |         FOO_REF => {}
    |         ------- matches any value
@@ -116,7 +116,7 @@
    |         ^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:53:9
+  --> $DIR/consts-opaque.rs:54:9
    |
 LL |         Bar => {}
    |         --- matches any value
@@ -124,7 +124,7 @@
    |         ^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:56:9
+  --> $DIR/consts-opaque.rs:57:9
    |
 LL |         Bar => {}
    |         --- matches any value
@@ -133,7 +133,7 @@
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:63:9
+  --> $DIR/consts-opaque.rs:64:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -142,7 +142,7 @@
    |         ^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:65:9
+  --> $DIR/consts-opaque.rs:66:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -151,7 +151,7 @@
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:72:9
+  --> $DIR/consts-opaque.rs:73:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -160,7 +160,7 @@
    |         ^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:75:9
+  --> $DIR/consts-opaque.rs:76:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -169,7 +169,7 @@
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:82:9
+  --> $DIR/consts-opaque.rs:83:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -178,7 +178,7 @@
    |         ^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:84:9
+  --> $DIR/consts-opaque.rs:85:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -187,7 +187,7 @@
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:92:9
+  --> $DIR/consts-opaque.rs:93:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -196,7 +196,7 @@
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:99:9
+  --> $DIR/consts-opaque.rs:100:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -205,7 +205,7 @@
    |         ^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:101:9
+  --> $DIR/consts-opaque.rs:102:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -213,19 +213,24 @@
 LL |         _ => {} // should not be emitting unreachable warning
    |         ^ unreachable pattern
 
-error: unreachable pattern
-  --> $DIR/consts-opaque.rs:127:9
+error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered
+  --> $DIR/consts-opaque.rs:135:11
    |
-LL |         Wrap(_) => {}
-   |         ------- matches any value
-LL |         WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
-   |         ^^^^^^^^ unreachable pattern
-
-error: unreachable pattern
-  --> $DIR/consts-opaque.rs:141:9
+LL |     match WRAPQUUX {
+   |           ^^^^^^^^ pattern `Wrap(_)` not covered
    |
-LL |         WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
-   |         ^^^^^^^^^^^^
+note: `Wrap<fn(usize, usize) -> usize>` defined here
+  --> $DIR/consts-opaque.rs:117:12
+   |
+LL |     struct Wrap<T>(T);
+   |            ^^^^
+   = note: the matched value is of type `Wrap<fn(usize, usize) -> usize>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         WRAPQUUX => {},
+LL +         Wrap(_) => todo!()
+   |
 
-error: aborting due to 24 previous errors; 1 warning emitted
+error: aborting due to 23 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index 5a145ef..49b6dfc 100644
--- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:37:9
+  --> $DIR/empty-match.rs:58:9
    |
 LL |         _ => {},
    |         ^
@@ -11,37 +11,52 @@
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:40:9
+  --> $DIR/empty-match.rs:61:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:47:9
+  --> $DIR/empty-match.rs:68:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:50:9
+  --> $DIR/empty-match.rs:71:9
    |
 LL |         _ if false => {},
    |         ^
 
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-match.rs:76:9
+   |
+LL |     let None = x;
+   |         ^^^^ pattern `Some(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
+   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let None = x { todo!() };
+   |     ++              +++++++++++
+
 error: unreachable pattern
-  --> $DIR/empty-match.rs:57:9
+  --> $DIR/empty-match.rs:88:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:60:9
+  --> $DIR/empty-match.rs:91:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:78:20
+  --> $DIR/empty-match.rs:109:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -50,13 +65,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:79:20
+  --> $DIR/empty-match.rs:111:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -64,13 +79,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:80:20
+  --> $DIR/empty-match.rs:113:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -78,13 +93,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:81:20
+  --> $DIR/empty-match.rs:115:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -92,13 +107,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:82:20
+  --> $DIR/empty-match.rs:117:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -106,13 +121,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:83:20
+  --> $DIR/empty-match.rs:119:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -122,31 +137,32 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:84:20
+  --> $DIR/empty-match.rs:122:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:85:20
+  --> $DIR/empty-match.rs:125:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -154,7 +170,7 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:87:24
+  --> $DIR/empty-match.rs:129:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -167,13 +183,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:88:24
+  --> $DIR/empty-match.rs:133:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -185,13 +201,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:89:24
+  --> $DIR/empty-match.rs:137:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -203,13 +219,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:90:24
+  --> $DIR/empty-match.rs:141:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -221,13 +237,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:91:24
+  --> $DIR/empty-match.rs:145:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -239,13 +255,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:92:24
+  --> $DIR/empty-match.rs:149:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -259,18 +275,19 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:93:24
+  --> $DIR/empty-match.rs:153:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +298,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:94:24
+  --> $DIR/empty-match.rs:157:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -298,6 +315,7 @@
 LL +             _ => todo!()
    |
 
-error: aborting due to 22 previous errors
+error: aborting due to 23 previous errors
 
-For more information about this error, try `rustc --explain E0004`.
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
index 5a145ef..f54a3f3 100644
--- a/tests/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:37:9
+  --> $DIR/empty-match.rs:58:9
    |
 LL |         _ => {},
    |         ^
@@ -11,37 +11,51 @@
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:40:9
+  --> $DIR/empty-match.rs:61:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:47:9
+  --> $DIR/empty-match.rs:68:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:50:9
+  --> $DIR/empty-match.rs:71:9
    |
 LL |         _ if false => {},
    |         ^
 
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-match.rs:76:9
+   |
+LL |     let None = x;
+   |         ^^^^ pattern `Some(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let None = x { todo!() };
+   |     ++              +++++++++++
+
 error: unreachable pattern
-  --> $DIR/empty-match.rs:57:9
+  --> $DIR/empty-match.rs:88:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:60:9
+  --> $DIR/empty-match.rs:91:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:78:20
+  --> $DIR/empty-match.rs:109:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -50,13 +64,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:79:20
+  --> $DIR/empty-match.rs:111:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -64,13 +78,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:80:20
+  --> $DIR/empty-match.rs:113:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -78,13 +92,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:81:20
+  --> $DIR/empty-match.rs:115:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -92,13 +106,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:82:20
+  --> $DIR/empty-match.rs:117:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -106,13 +120,13 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:83:20
+  --> $DIR/empty-match.rs:119:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -122,31 +136,32 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:84:20
+  --> $DIR/empty-match.rs:122:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:85:20
+  --> $DIR/empty-match.rs:125:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -154,7 +169,7 @@
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:87:24
+  --> $DIR/empty-match.rs:129:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -167,13 +182,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:88:24
+  --> $DIR/empty-match.rs:133:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:14:8
+  --> $DIR/empty-match.rs:15:8
    |
 LL | struct NonEmptyStruct1;
    |        ^^^^^^^^^^^^^^^
@@ -185,13 +200,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:89:24
+  --> $DIR/empty-match.rs:137:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:18:8
    |
 LL | struct NonEmptyStruct2(bool);
    |        ^^^^^^^^^^^^^^^
@@ -203,13 +218,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:90:24
+  --> $DIR/empty-match.rs:141:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:16:7
+  --> $DIR/empty-match.rs:21:7
    |
 LL | union NonEmptyUnion1 {
    |       ^^^^^^^^^^^^^^
@@ -221,13 +236,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:91:24
+  --> $DIR/empty-match.rs:145:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:19:7
+  --> $DIR/empty-match.rs:26:7
    |
 LL | union NonEmptyUnion2 {
    |       ^^^^^^^^^^^^^^
@@ -239,13 +254,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:92:24
+  --> $DIR/empty-match.rs:149:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:24:5
+  --> $DIR/empty-match.rs:33:5
    |
 LL | enum NonEmptyEnum1 {
    |      -------------
@@ -259,18 +274,19 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:93:24
+  --> $DIR/empty-match.rs:153:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:27:5
+  --> $DIR/empty-match.rs:40:5
    |
 LL | enum NonEmptyEnum2 {
    |      -------------
 LL |     Foo(bool),
    |     ^^^ not covered
+...
 LL |     Bar,
    |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +297,13 @@
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:94:24
+  --> $DIR/empty-match.rs:157:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:30:6
+  --> $DIR/empty-match.rs:49:6
    |
 LL | enum NonEmptyEnum5 {
    |      ^^^^^^^^^^^^^
@@ -298,6 +314,7 @@
 LL +             _ => todo!()
    |
 
-error: aborting due to 22 previous errors
+error: aborting due to 23 previous errors
 
-For more information about this error, try `rustc --explain E0004`.
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs
index 9cdc041..062241f 100644
--- a/tests/ui/pattern/usefulness/empty-match.rs
+++ b/tests/ui/pattern/usefulness/empty-match.rs
@@ -6,28 +6,49 @@
 #![feature(never_type_fallback)]
 #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
 #![deny(unreachable_patterns)]
+//~^ NOTE the lint level is defined here
 
 extern crate empty;
 
 enum EmptyEnum {}
 
 struct NonEmptyStruct1;
+//~^ NOTE `NonEmptyStruct1` defined here
+//~| NOTE `NonEmptyStruct1` defined here
 struct NonEmptyStruct2(bool);
+//~^ NOTE `NonEmptyStruct2` defined here
+//~| NOTE `NonEmptyStruct2` defined here
 union NonEmptyUnion1 {
+    //~^ NOTE `NonEmptyUnion1` defined here
+    //~| NOTE `NonEmptyUnion1` defined here
     foo: (),
 }
 union NonEmptyUnion2 {
+    //~^ NOTE `NonEmptyUnion2` defined here
+    //~| NOTE `NonEmptyUnion2` defined here
     foo: (),
     bar: (),
 }
 enum NonEmptyEnum1 {
     Foo(bool),
+    //~^ NOTE `NonEmptyEnum1` defined here
+    //~| NOTE `NonEmptyEnum1` defined here
+    //~| NOTE not covered
+    //~| NOTE not covered
 }
 enum NonEmptyEnum2 {
     Foo(bool),
+    //~^ NOTE `NonEmptyEnum2` defined here
+    //~| NOTE `NonEmptyEnum2` defined here
+    //~| NOTE not covered
+    //~| NOTE not covered
     Bar,
+    //~^ NOTE not covered
+    //~| NOTE not covered
 }
 enum NonEmptyEnum5 {
+    //~^ NOTE `NonEmptyEnum5` defined here
+    //~| NOTE `NonEmptyEnum5` defined here
     V1, V2, V3, V4, V5,
 }
 
@@ -51,6 +72,16 @@
     }
 }
 
+fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) {
+    let None = x;
+    //~^ ERROR refutable pattern in local binding
+    //~| NOTE `let` bindings require an "irrefutable pattern"
+    //~| NOTE for more information, visit
+    //~| NOTE the matched value is of type
+    //~| NOTE pattern `Some(_)` not covered
+    //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields
+}
+
 fn never(x: !) {
     match x {} // ok
     match x {
@@ -76,20 +107,55 @@
 
 fn main() {
     match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
+                         //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
+                                     //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
+                                           //~| NOTE the matched value is of type
     match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
+                                                  //~| NOTE the matched value is of type
     match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
+                                                  //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+                                              //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
+                                              //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+                                              //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
+                                              //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+                                       //~| NOTE patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`
+                                       //~| NOTE the matched value is of type
 
     match_guarded_arm!(0u8); //~ ERROR `_` not covered
+                             //~| NOTE the matched value is of type
+                             //~| NOTE pattern `_` not covered
+                             //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
+                                         //~| NOTE pattern `NonEmptyStruct1` not covered
+                                         //~| NOTE the matched value is of type
+                                         //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
+                                               //~| NOTE the matched value is of type
+                                               //~| NOTE pattern `NonEmptyStruct2(_)` not covered
+                                               //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
+                                                      //~| NOTE the matched value is of type
+                                                      //~| NOTE pattern `NonEmptyUnion1 { .. }` not covered
+                                                      //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
+                                                      //~| NOTE the matched value is of type
+                                                      //~| NOTE pattern `NonEmptyUnion2 { .. }` not covered
+                                                      //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+                                                  //~| NOTE the matched value is of type
+                                                  //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
+                                                  //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+                                                  //~| NOTE the matched value is of type
+                                                  //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
+                                                  //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+                                           //~| NOTE the matched value is of type
+                                           //~| NOTE patterns `NonEmptyEnum5::V1`,
+                                           //~| NOTE in this expansion of match_guarded_arm!
 }
diff --git a/tests/ui/print_type_sizes/async.rs b/tests/ui/print_type_sizes/async.rs
index c73268d..f38a6e6 100644
--- a/tests/ui/print_type_sizes/async.rs
+++ b/tests/ui/print_type_sizes/async.rs
@@ -3,7 +3,7 @@
 // build-pass
 // ignore-pass
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 async fn wait() {}
 
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.rs b/tests/ui/print_type_sizes/generator_discr_placement.rs
index a77a03f..6adc14f 100644
--- a/tests/ui/print_type_sizes/generator_discr_placement.rs
+++ b/tests/ui/print_type_sizes/generator_discr_placement.rs
@@ -6,7 +6,7 @@
 
 // Avoid emitting panic handlers, like the rest of these tests...
 #![feature(generators)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 pub fn foo() {
     let a = || {
diff --git a/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
index af2bb09..0c1e931 100644
--- a/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
+++ b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
@@ -3,7 +3,7 @@
 
 // check-pass
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::marker::PhantomData;
 
diff --git a/tests/ui/resolve/issue-109250.rs b/tests/ui/resolve/issue-109250.rs
new file mode 100644
index 0000000..68e33f6
--- /dev/null
+++ b/tests/ui/resolve/issue-109250.rs
@@ -0,0 +1,3 @@
+fn main() {       //~ HELP consider importing
+    HashMap::new; //~ ERROR failed to resolve: use of undeclared type `HashMap`
+}
diff --git a/tests/ui/resolve/issue-109250.stderr b/tests/ui/resolve/issue-109250.stderr
new file mode 100644
index 0000000..d5b8c08
--- /dev/null
+++ b/tests/ui/resolve/issue-109250.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: use of undeclared type `HashMap`
+  --> $DIR/issue-109250.rs:2:5
+   |
+LL |     HashMap::new;
+   |     ^^^^^^^ use of undeclared type `HashMap`
+   |
+help: consider importing this struct
+   |
+LL + use std::collections::HashMap;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs
new file mode 100644
index 0000000..acea37b
--- /dev/null
+++ b/tests/ui/resolve/issue-111312.rs
@@ -0,0 +1,11 @@
+// edition: 2021
+
+trait Has {
+    fn has() {}
+}
+
+trait HasNot {}
+
+fn main() {
+    HasNot::has(); //~ ERROR
+}
diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr
new file mode 100644
index 0000000..4c86402
--- /dev/null
+++ b/tests/ui/resolve/issue-111312.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no function or associated item named `has` found for trait `HasNot`
+  --> $DIR/issue-111312.rs:10:13
+   |
+LL |     HasNot::has();
+   |             ^^^ function or associated item not found in `HasNot`
+   |
+note: `Has` defines an item `has`
+  --> $DIR/issue-111312.rs:3:1
+   |
+LL | trait Has {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs
new file mode 100644
index 0000000..36f3081
--- /dev/null
+++ b/tests/ui/resolve/issue-111727.rs
@@ -0,0 +1,5 @@
+// edition: 2021
+
+fn main() {
+    std::any::Any::create(); //~ ERROR
+}
diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr
new file mode 100644
index 0000000..bd74821
--- /dev/null
+++ b/tests/ui/resolve/issue-111727.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no function or associated item named `create` found for trait `Any`
+  --> $DIR/issue-111727.rs:4:20
+   |
+LL |     std::any::Any::create();
+   |                    ^^^^^^ function or associated item not found in `Any`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/issue-50599.rs b/tests/ui/resolve/issue-50599.rs
index 72238a5..0058873 100644
--- a/tests/ui/resolve/issue-50599.rs
+++ b/tests/ui/resolve/issue-50599.rs
@@ -2,5 +2,4 @@
     const N: u32 = 1_000;
     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value
     let mut digits = [0u32; M];
-    //~^ constant
 }
diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr
index d7419b6..d58b6ca 100644
--- a/tests/ui/resolve/issue-50599.stderr
+++ b/tests/ui/resolve/issue-50599.stderr
@@ -16,12 +16,6 @@
 LL +     const M: usize = (f64::from(N) * LOG10_2) as usize;
    |
 
-note: erroneous constant used
-  --> $DIR/issue-50599.rs:4:29
-   |
-LL |     let mut digits = [0u32; M];
-   |                             ^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/resolve-variant-assoc-item.stderr b/tests/ui/resolve/resolve-variant-assoc-item.stderr
index 4be1019..ed15719 100644
--- a/tests/ui/resolve/resolve-variant-assoc-item.stderr
+++ b/tests/ui/resolve/resolve-variant-assoc-item.stderr
@@ -3,12 +3,26 @@
    |
 LL |     E::V::associated_item;
    |        ^ `V` is a variant, not a module
+   |
+help: there is an enum variant `E::V`; try using the variant's enum
+   |
+LL |     E;
+   |     ~
 
 error[E0433]: failed to resolve: `V` is a variant, not a module
   --> $DIR/resolve-variant-assoc-item.rs:6:5
    |
 LL |     V::associated_item;
    |     ^ `V` is a variant, not a module
+   |
+help: there is an enum variant `E::V`; try using the variant's enum
+   |
+LL |     E;
+   |     ~
+help: an enum with a similar name exists
+   |
+LL |     E::associated_item;
+   |     ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
index 8f45b98..b9ff24c 100644
--- a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
+++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
@@ -3,7 +3,7 @@
 
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 // aux-build:monovariants.rs
 extern crate monovariants;
diff --git a/tests/ui/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfc-2294-if-let-guard/feature-gate.rs
index f0105e0..3beb20f 100644
--- a/tests/ui/rfc-2294-if-let-guard/feature-gate.rs
+++ b/tests/ui/rfc-2294-if-let-guard/feature-gate.rs
@@ -10,10 +10,12 @@
         () if (let 0 = 1) => {}
         //~^ ERROR `let` expressions in this position are unstable
         //~| ERROR expected expression, found `let` statement
+        //~| ERROR `let` expressions are not supported here
 
         () if (((let 0 = 1))) => {}
         //~^ ERROR `let` expressions in this position are unstable
         //~| ERROR expected expression, found `let` statement
+        //~| ERROR `let` expressions are not supported here
 
         () if true && let 0 = 1 => {}
         //~^ ERROR `if let` guards are experimental
@@ -26,16 +28,20 @@
         () if (let 0 = 1) && true => {}
         //~^ ERROR `let` expressions in this position are unstable
         //~| ERROR expected expression, found `let` statement
+        //~| ERROR `let` expressions are not supported here
 
         () if true && (let 0 = 1) => {}
         //~^ ERROR `let` expressions in this position are unstable
         //~| ERROR expected expression, found `let` statement
+        //~| ERROR `let` expressions are not supported here
 
         () if (let 0 = 1) && (let 0 = 1) => {}
         //~^ ERROR `let` expressions in this position are unstable
         //~| ERROR `let` expressions in this position are unstable
         //~| ERROR expected expression, found `let` statement
         //~| ERROR expected expression, found `let` statement
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
 
         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
         //~^ ERROR `if let` guards are experimental
@@ -47,6 +53,10 @@
         //~| ERROR expected expression, found `let` statement
         //~| ERROR expected expression, found `let` statement
         //~| ERROR expected expression, found `let` statement
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
+        //~| ERROR `let` expressions are not supported here
+
 
         () if let Range { start: _, end: _ } = (true..true) && false => {}
         //~^ ERROR `if let` guards are experimental
@@ -68,9 +78,11 @@
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR `let` expressions in this position are unstable
     //~| ERROR expected expression, found `let` statement
+    //~| ERROR `let` expressions are not supported here
     use_expr!((let 0 = 1));
     //~^ ERROR `let` expressions in this position are unstable
     //~| ERROR expected expression, found `let` statement
+    //~| ERROR `let` expressions are not supported here
     match () {
         #[cfg(FALSE)]
         () if let 0 = 1 => {}
diff --git a/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr
index 96fe119..dc182ce 100644
--- a/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr
@@ -5,67 +5,67 @@
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:14:18
+  --> $DIR/feature-gate.rs:15:18
    |
 LL |         () if (((let 0 = 1))) => {}
    |                  ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:26:16
+  --> $DIR/feature-gate.rs:28:16
    |
 LL |         () if (let 0 = 1) && true => {}
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:30:24
+  --> $DIR/feature-gate.rs:33:24
    |
 LL |         () if true && (let 0 = 1) => {}
    |                        ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:34:16
+  --> $DIR/feature-gate.rs:38:16
    |
 LL |         () if (let 0 = 1) && (let 0 = 1) => {}
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:34:31
+  --> $DIR/feature-gate.rs:38:31
    |
 LL |         () if (let 0 = 1) && (let 0 = 1) => {}
    |                               ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:40:42
+  --> $DIR/feature-gate.rs:46:42
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |                                          ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:40:55
+  --> $DIR/feature-gate.rs:46:55
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |                                                       ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:40:68
+  --> $DIR/feature-gate.rs:46:68
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |                                                                    ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:68:16
+  --> $DIR/feature-gate.rs:78:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:71:16
+  --> $DIR/feature-gate.rs:82:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^
 
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:80:15
+  --> $DIR/feature-gate.rs:92:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -74,11 +74,154 @@
    |               ^^^ no rules expected this token in macro call
    |
 note: while trying to match meta-variable `$e:expr`
-  --> $DIR/feature-gate.rs:61:10
+  --> $DIR/feature-gate.rs:71:10
    |
 LL |         ($e:expr) => {
    |          ^^^^^^^
 
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:10:16
+   |
+LL |         () if (let 0 = 1) => {}
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:10:16
+   |
+LL |         () if (let 0 = 1) => {}
+   |                ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:15:18
+   |
+LL |         () if (((let 0 = 1))) => {}
+   |                  ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:15:18
+   |
+LL |         () if (((let 0 = 1))) => {}
+   |                  ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:28:16
+   |
+LL |         () if (let 0 = 1) && true => {}
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:28:16
+   |
+LL |         () if (let 0 = 1) && true => {}
+   |                ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:33:24
+   |
+LL |         () if true && (let 0 = 1) => {}
+   |                        ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:33:24
+   |
+LL |         () if true && (let 0 = 1) => {}
+   |                        ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:38:16
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:38:16
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:38:31
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                               ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:38:31
+   |
+LL |         () if (let 0 = 1) && (let 0 = 1) => {}
+   |                               ^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:46:42
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                          ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:46:42
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:46:55
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                       ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:46:42
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:46:68
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                                                    ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:46:42
+   |
+LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:78:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:78:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^^^^^^^^^^^^^^^^^
+
+error: `let` expressions are not supported here
+  --> $DIR/feature-gate.rs:82:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `let`s wrapped in parentheses are not supported in a context with let chains
+  --> $DIR/feature-gate.rs:82:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^^^^^^^
+
 error[E0658]: `if let` guards are experimental
   --> $DIR/feature-gate.rs:7:12
    |
@@ -90,7 +233,7 @@
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:18:12
+  --> $DIR/feature-gate.rs:20:12
    |
 LL |         () if true && let 0 = 1 => {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +243,7 @@
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:22:12
+  --> $DIR/feature-gate.rs:24:12
    |
 LL |         () if let 0 = 1 && true => {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -110,7 +253,7 @@
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:40:12
+  --> $DIR/feature-gate.rs:46:12
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,7 +263,7 @@
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:51:12
+  --> $DIR/feature-gate.rs:61:12
    |
 LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,7 +273,7 @@
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:76:12
+  --> $DIR/feature-gate.rs:88:12
    |
 LL |         () if let 0 = 1 => {}
    |            ^^^^^^^^^^^^
@@ -149,7 +292,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:14:18
+  --> $DIR/feature-gate.rs:15:18
    |
 LL |         () if (((let 0 = 1))) => {}
    |                  ^^^^^^^^^
@@ -158,7 +301,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:18:23
+  --> $DIR/feature-gate.rs:20:23
    |
 LL |         () if true && let 0 = 1 => {}
    |                       ^^^^^^^^^
@@ -167,7 +310,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:22:15
+  --> $DIR/feature-gate.rs:24:15
    |
 LL |         () if let 0 = 1 && true => {}
    |               ^^^^^^^^^
@@ -176,7 +319,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:26:16
+  --> $DIR/feature-gate.rs:28:16
    |
 LL |         () if (let 0 = 1) && true => {}
    |                ^^^^^^^^^
@@ -185,7 +328,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:30:24
+  --> $DIR/feature-gate.rs:33:24
    |
 LL |         () if true && (let 0 = 1) => {}
    |                        ^^^^^^^^^
@@ -194,7 +337,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:34:16
+  --> $DIR/feature-gate.rs:38:16
    |
 LL |         () if (let 0 = 1) && (let 0 = 1) => {}
    |                ^^^^^^^^^
@@ -203,7 +346,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:34:31
+  --> $DIR/feature-gate.rs:38:31
    |
 LL |         () if (let 0 = 1) && (let 0 = 1) => {}
    |                               ^^^^^^^^^
@@ -212,7 +355,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:40:15
+  --> $DIR/feature-gate.rs:46:15
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |               ^^^^^^^^^
@@ -221,7 +364,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:40:28
+  --> $DIR/feature-gate.rs:46:28
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |                            ^^^^^^^^^
@@ -230,7 +373,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:40:42
+  --> $DIR/feature-gate.rs:46:42
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |                                          ^^^^^^^^^
@@ -239,7 +382,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:40:55
+  --> $DIR/feature-gate.rs:46:55
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |                                                       ^^^^^^^^^
@@ -248,7 +391,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:40:68
+  --> $DIR/feature-gate.rs:46:68
    |
 LL |         () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
    |                                                                    ^^^^^^^^^
@@ -257,7 +400,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:51:15
+  --> $DIR/feature-gate.rs:61:15
    |
 LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -266,7 +409,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:68:16
+  --> $DIR/feature-gate.rs:78:16
    |
 LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^^^^^^^
@@ -275,7 +418,7 @@
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:71:16
+  --> $DIR/feature-gate.rs:82:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
@@ -283,6 +426,6 @@
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
-error: aborting due to 34 previous errors
+error: aborting due to 45 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
index 4c15627..542be39 100644
--- a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
+++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -4,7 +4,7 @@
 // Tests ensuring that `dbg!(expr)` has the expected run-time behavior.
 // as well as some compile time properties we expect.
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 #[derive(Copy, Clone, Debug)]
 struct Unit;
diff --git a/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.rs b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.rs
new file mode 100644
index 0000000..e6dee2a
--- /dev/null
+++ b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.rs
@@ -0,0 +1,23 @@
+#![feature(let_chains)]
+
+fn let_or_guard(x: Result<Option<i32>, ()>) {
+    match x {
+        Ok(opt) if let Some(4) = opt || false  => {}
+        //~^ ERROR `let` expressions are not supported here
+        _ => {}
+    }
+}
+
+fn hiding_unsafe_mod(x: Result<Option<i32>, ()>) {
+    match x {
+        Ok(opt)
+            if {
+                unsafe mod a {};
+                //~^ ERROR module cannot be declared unsafe
+                false
+            } => {}
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.stderr b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.stderr
new file mode 100644
index 0000000..2685099
--- /dev/null
+++ b/tests/ui/rfc-2497-if-let-chains/ast-validate-guards.stderr
@@ -0,0 +1,21 @@
+error: `let` expressions are not supported here
+  --> $DIR/ast-validate-guards.rs:5:20
+   |
+LL |         Ok(opt) if let Some(4) = opt || false  => {}
+   |                    ^^^^^^^^^^^^^^^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+note: `||` operators are not supported in let chain expressions
+  --> $DIR/ast-validate-guards.rs:5:38
+   |
+LL |         Ok(opt) if let Some(4) = opt || false  => {}
+   |                                      ^^
+
+error: module cannot be declared unsafe
+  --> $DIR/ast-validate-guards.rs:15:17
+   |
+LL |                 unsafe mod a {};
+   |                 ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rust-2018/remove-extern-crate.fixed b/tests/ui/rust-2018/remove-extern-crate.fixed
index 4ed4d61..209b91a 100644
--- a/tests/ui/rust-2018/remove-extern-crate.fixed
+++ b/tests/ui/rust-2018/remove-extern-crate.fixed
@@ -5,7 +5,7 @@
 // compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
  //~ WARNING unused extern crate
 // Shouldn't suggest changing to `use`, as `another_name`
diff --git a/tests/ui/rust-2018/remove-extern-crate.rs b/tests/ui/rust-2018/remove-extern-crate.rs
index 5dafdb2..ef3c2db 100644
--- a/tests/ui/rust-2018/remove-extern-crate.rs
+++ b/tests/ui/rust-2018/remove-extern-crate.rs
@@ -5,7 +5,7 @@
 // compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 extern crate core; //~ WARNING unused extern crate
 // Shouldn't suggest changing to `use`, as `another_name`
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.rs b/tests/ui/self/arbitrary-self-from-method-substs.rs
new file mode 100644
index 0000000..0f911a2
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs.rs
@@ -0,0 +1,16 @@
+#![feature(arbitrary_self_types)]
+
+use std::ops::Deref;
+
+struct Foo(u32);
+impl Foo {
+    fn get<R: Deref<Target=Self>>(self: R) -> u32 {
+        self.0
+    }
+}
+
+fn main() {
+    let mut foo = Foo(1);
+    foo.get::<&Foo>();
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.stderr b/tests/ui/self/arbitrary-self-from-method-substs.stderr
new file mode 100644
index 0000000..6c252fa
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:14:5
+   |
+LL |     foo.get::<&Foo>();
+   |     ^^^ expected `&Foo`, found `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/self/self-ctor-inner-const.rs b/tests/ui/self/self-ctor-inner-const.rs
deleted file mode 100644
index b015397..0000000
--- a/tests/ui/self/self-ctor-inner-const.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Verify that we ban usage of `Self` as constructor from inner items.
-
-struct S0<T>(T);
-
-impl<T> S0<T> {
-    fn foo() {
-        const C: S0<u8> = Self(0);
-        //~^ ERROR can't use generic parameters from outer function
-        fn bar() -> Self {
-            //~^ ERROR can't use generic parameters from outer function
-            Self(0)
-            //~^ ERROR can't use generic parameters from outer function
-        }
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/self/self-ctor-inner-const.stderr b/tests/ui/self/self-ctor-inner-const.stderr
deleted file mode 100644
index 7287c64..0000000
--- a/tests/ui/self/self-ctor-inner-const.stderr
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:7:27
-   |
-LL |         const C: S0<u8> = Self(0);
-   |                           ^^^^
-   |                           |
-   |                           use of generic parameter from outer function
-   |                           can't use `Self` here
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:9:21
-   |
-LL | impl<T> S0<T> {
-   | ---- `Self` type implicitly declared here, by this `impl`
-...
-LL |         fn bar() -> Self {
-   |                     ^^^^
-   |                     |
-   |                     use of generic parameter from outer function
-   |                     use a type here instead
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:11:13
-   |
-LL |             Self(0)
-   |             ^^^^
-   |             |
-   |             use of generic parameter from outer function
-   |             can't use `Self` here
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/self/self-ctor-nongeneric.rs b/tests/ui/self/self-ctor-nongeneric.rs
new file mode 100644
index 0000000..0ae7f8d
--- /dev/null
+++ b/tests/ui/self/self-ctor-nongeneric.rs
@@ -0,0 +1,15 @@
+// `Self` as a constructor is currently allowed when the outer item is not generic.
+// check-pass
+
+struct S0(usize);
+
+impl S0 {
+    fn foo() {
+        const C: S0 = Self(0);
+        fn bar() -> S0 {
+            Self(0)
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/statics/issue-91050-1.rs b/tests/ui/statics/issue-91050-1.rs
index f59bcf0..c6268db 100644
--- a/tests/ui/statics/issue-91050-1.rs
+++ b/tests/ui/statics/issue-91050-1.rs
@@ -12,7 +12,7 @@
 //
 // In regular builds, the bad cast was UB, like "Invalid LLVMRustVisibility value!"
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 pub mod before {
     #[no_mangle]
diff --git a/tests/ui/suggestions/issue-109854.rs b/tests/ui/suggestions/issue-109854.rs
new file mode 100644
index 0000000..dd4542d
--- /dev/null
+++ b/tests/ui/suggestions/issue-109854.rs
@@ -0,0 +1,12 @@
+fn generate_setter() {
+    String::with_capacity(
+    //~^ ERROR this function takes 1 argument but 3 arguments were supplied
+    generate_setter,
+    r#"
+pub(crate) struct Person<T: Clone> {}
+"#,
+     r#""#,
+    );
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-109854.stderr b/tests/ui/suggestions/issue-109854.stderr
new file mode 100644
index 0000000..621a389
--- /dev/null
+++ b/tests/ui/suggestions/issue-109854.stderr
@@ -0,0 +1,31 @@
+error[E0061]: this function takes 1 argument but 3 arguments were supplied
+  --> $DIR/issue-109854.rs:2:5
+   |
+LL |       String::with_capacity(
+   |       ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | /     r#"
+LL | | pub(crate) struct Person<T: Clone> {}
+LL | | "#,
+   | |__- unexpected argument of type `&'static str`
+LL |        r#""#,
+   |        ----- unexpected argument of type `&'static str`
+   |
+note: expected `usize`, found fn item
+  --> $DIR/issue-109854.rs:4:5
+   |
+LL |     generate_setter,
+   |     ^^^^^^^^^^^^^^^
+   = note: expected type `usize`
+           found fn item `fn() {generate_setter}`
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
+help: remove the extra arguments
+   |
+LL -     generate_setter,
+LL +     /* usize */,
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/suggestions/issue-94171.rs b/tests/ui/suggestions/issue-94171.rs
new file mode 100644
index 0000000..cbb9f9c
--- /dev/null
+++ b/tests/ui/suggestions/issue-94171.rs
@@ -0,0 +1,5 @@
+fn L(]{match
+(; {`
+//~^^ ERROR mismatched closing delimiter
+//~^^ ERROR unknown start of token
+//~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/suggestions/issue-94171.stderr b/tests/ui/suggestions/issue-94171.stderr
new file mode 100644
index 0000000..b3440e4
--- /dev/null
+++ b/tests/ui/suggestions/issue-94171.stderr
@@ -0,0 +1,36 @@
+error: unknown start of token: `
+  --> $DIR/issue-94171.rs:2:5
+   |
+LL | (; {`
+   |     ^
+   |
+help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
+   |
+LL | (; {'
+   |     ~
+
+error: mismatched closing delimiter: `]`
+  --> $DIR/issue-94171.rs:1:5
+   |
+LL | fn L(]{match
+   |     ^^ mismatched closing delimiter
+   |     |
+   |     unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-94171.rs:5:52
+   |
+LL | fn L(]{match
+   |      -- unclosed delimiter
+   |      |
+   |      missing open `[` for this delimiter
+LL | (; {`
+   | -  - unclosed delimiter
+   | |
+   | unclosed delimiter
+...
+LL |
+   |                                                    ^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/issue-99597.rs b/tests/ui/suggestions/issue-99597.rs
new file mode 100644
index 0000000..8ba9e1f
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.rs
@@ -0,0 +1,15 @@
+#![allow(dead_code)]
+
+trait T1 { }
+
+trait T2 {
+    fn test(&self) { }
+}
+
+fn go(s: &impl T1) {
+    //~^ SUGGESTION (
+    s.test();
+    //~^ ERROR no method named `test`
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-99597.stderr b/tests/ui/suggestions/issue-99597.stderr
new file mode 100644
index 0000000..bdf2a07
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `test` found for reference `&impl T1` in the current scope
+  --> $DIR/issue-99597.rs:11:7
+   |
+LL |     s.test();
+   |       ^^^^ method not found in `&impl T1`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `test`, perhaps you need to restrict type parameter `impl T1` with it:
+   |
+LL | fn go(s: &(impl T1 + T2)) {
+   |           +        +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr
index 9f62763..5d8b375 100644
--- a/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr
+++ b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr
@@ -1 +1 @@
-error: The "json" format is only accepted on the nightly compiler
+error: The "json" format is only accepted on the nightly compiler with -Z unstable-options
diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs
index 307e310..fc6f5f2 100644
--- a/tests/ui/track-diagnostics/track6.rs
+++ b/tests/ui/track-diagnostics/track6.rs
@@ -1,6 +1,9 @@
 // compile-flags: -Z track-diagnostics
 // error-pattern: created at
 
+// Normalize the emitted location so this doesn't need
+// updating everytime someone adds or removes a line.
+// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
 
 
 pub trait Foo {
diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr
index 1c75376..89438ae 100644
--- a/tests/ui/track-diagnostics/track6.stderr
+++ b/tests/ui/track-diagnostics/track6.stderr
@@ -1,9 +1,9 @@
 error[E0658]: specialization is unstable
-  --> $DIR/track6.rs:11:5
+  --> $DIR/track6.rs:LL:CC
    |
 LL |     default fn bar() {}
    |     ^^^^^^^^^^^^^^^^^^^
--Ztrack-diagnostics: created at $COMPILER_DIR/rustc_session/src/parse.rs:93:5
+-Ztrack-diagnostics: created at $COMPILER_DIR/rustc_session/src/parse.rs:LL:CC
    |
    = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
    = help: add `#![feature(specialization)]` to the crate attributes to enable
diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs
index 558303c..af25010 100644
--- a/tests/ui/traits/copy-guessing.rs
+++ b/tests/ui/traits/copy-guessing.rs
@@ -1,7 +1,5 @@
-// run-pass
-
 #![allow(dead_code)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // "guessing" in trait selection can affect `copy_or_move`. Check that this
 // is correctly handled. I am not sure what is the "correct" behaviour,
@@ -20,6 +18,7 @@
 
 fn main() {
     let n = None;
+    //~^ ERROR type annotations needed for `Option<T>`
     let e = S(&n);
     let f = || {
         // S being copy is critical for this to work
diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr
new file mode 100644
index 0000000..568b7e5
--- /dev/null
+++ b/tests/ui/traits/copy-guessing.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `Option<T>`
+  --> $DIR/copy-guessing.rs:20:9
+   |
+LL |     let n = None;
+   |         ^
+   |
+help: consider giving `n` an explicit type, where the type for type parameter `T` is specified
+   |
+LL |     let n: Option<T> = None;
+   |          +++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr
index 2ff16b4..aee41c4 100644
--- a/tests/ui/traits/cycle-cache-err-60010.stderr
+++ b/tests/ui/traits/cycle-cache-err-60010.stderr
@@ -1,9 +1,25 @@
-error[E0275]: overflow evaluating the requirement `RootDatabase: RefUnwindSafe`
+error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
   --> $DIR/cycle-cache-err-60010.rs:27:13
    |
 LL |     _parse: <ParseQuery as Query<RootDatabase>>::Data,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required because it appears within the type `PhantomData<SalsaStorage>`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+note: required because it appears within the type `Unique<SalsaStorage>`
+  --> $SRC_DIR/core/src/ptr/unique.rs:LL:COL
+note: required because it appears within the type `Box<SalsaStorage>`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+note: required because it appears within the type `Runtime<RootDatabase>`
+  --> $DIR/cycle-cache-err-60010.rs:23:8
+   |
+LL | struct Runtime<DB: Database> {
+   |        ^^^^^^^
+note: required because it appears within the type `RootDatabase`
+  --> $DIR/cycle-cache-err-60010.rs:20:8
+   |
+LL | struct RootDatabase {
+   |        ^^^^^^^^^^^^
 note: required for `RootDatabase` to implement `SourceDatabase`
   --> $DIR/cycle-cache-err-60010.rs:44:9
    |
diff --git a/tests/ui/traits/impl-evaluation-order.rs b/tests/ui/traits/impl-evaluation-order.rs
index 256ce99..2ce0b6b 100644
--- a/tests/ui/traits/impl-evaluation-order.rs
+++ b/tests/ui/traits/impl-evaluation-order.rs
@@ -6,7 +6,7 @@
 
 // check-pass
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 trait A {
     type B;
diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs
index 7064a39..b174669 100644
--- a/tests/ui/traits/issue-106072.rs
+++ b/tests/ui/traits/issue-106072.rs
@@ -1,5 +1,4 @@
 #[derive(Clone)] //~  trait objects must include the `dyn` keyword
-                 //~| trait objects must include the `dyn` keyword
 struct Foo;
 trait Foo {} //~ the name `Foo` is defined multiple times
 fn main() {}
diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr
index f9b7b81..1037603 100644
--- a/tests/ui/traits/issue-106072.stderr
+++ b/tests/ui/traits/issue-106072.stderr
@@ -1,5 +1,5 @@
 error[E0428]: the name `Foo` is defined multiple times
-  --> $DIR/issue-106072.rs:4:1
+  --> $DIR/issue-106072.rs:3:1
    |
 LL | struct Foo;
    | ----------- previous definition of the type `Foo` here
@@ -16,15 +16,7 @@
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0782]: trait objects must include the `dyn` keyword
-  --> $DIR/issue-106072.rs:1:10
-   |
-LL | #[derive(Clone)]
-   |          ^^^^^
-   |
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0428, E0782.
 For more information about an error, try `rustc --explain E0428`.
diff --git a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
index 531203d..3c7fc74 100644
--- a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
+++ b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Ztrait-solver=next
 
+// check-pass
+// (should not pass, should be turned into a coherence-only test)
+
 // check that when computing `alias-eq(<() as Foo<u16, T>>::Assoc, <() as Foo<?0, T>>::Assoc)`
 // we do not infer `?0 = u8` via the `for<STOP> (): Foo<u8, STOP>` impl or `?0 = u16` by
 // relating substs as either could be a valid solution.
@@ -36,7 +39,6 @@
 {
     // `<() as Foo<u16, STOP>>::Assoc == <() as Foo<_, STOP>>::Assoc`
     let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
-    //~^ error: type annotations needed
 
     // let _: <() as Foo<u16, T>>::Assoc = output::<u8, T>(); // OK
     // let _: <() as Foo<u16, T>>::Assoc = output::<u16, T>(); // OK
diff --git a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr
deleted file mode 100644
index a671233..0000000
--- a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/alias_eq_dont_use_normalizes_to_if_substs_eq.rs:38:41
-   |
-LL |     let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
-   |                                         ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `output`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
index d4cc380..b036411 100644
--- a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
+++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Ztrait-solver=next
 
+// check-pass
+// (should not pass, should be turned into a coherence-only test)
+
 // check that a `alias-eq(<?0 as TraitB>::Assoc, <T as TraitB>::Assoc)` goal fails.
 
 // FIXME(deferred_projection_equality): add a test that this is true during coherence
@@ -14,7 +17,6 @@
 
 fn bar<T: TraitB>() {
     let _: <_ as TraitB>::Assoc = needs_a::<T>();
-    //~^ error: type annotations needed
 }
 
 fn main() {}
diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr
deleted file mode 100644
index d063d8f..0000000
--- a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/alias_eq_substs_eq_not_intercrate.rs:16:12
-   |
-LL |     let _: <_ as TraitB>::Assoc = needs_a::<T>();
-   |            ^^^^^^^^^^^^^^^^^^^^ cannot infer type for associated type `<_ as TraitB>::Assoc`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
index f115e14..e311a4a 100644
--- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
+++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
@@ -14,7 +14,7 @@
     #[cfg(fail)]
     let x = &NotSync;
     bar().await;
-    #[allow(drop_ref)]
+    #[allow(dropping_references)]
     drop(x);
 }
 
diff --git a/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs b/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs
new file mode 100644
index 0000000..d70534f
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// Verify that we can assemble inherent impl candidates on a possibly
+// unnormalized self type.
+
+trait Foo {
+    type Assoc;
+}
+impl Foo for i32 {
+    type Assoc = Bar;
+}
+
+struct Bar;
+impl Bar {
+    fn method(&self) {}
+}
+
+fn build<T: Foo>(_: T) -> T::Assoc {
+    todo!()
+}
+
+fn main() {
+    build(1i32).method();
+}
diff --git a/tests/ui/traits/new-solver/structural-resolve-field.rs b/tests/ui/traits/new-solver/structural-resolve-field.rs
new file mode 100644
index 0000000..01899c9
--- /dev/null
+++ b/tests/ui/traits/new-solver/structural-resolve-field.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#[derive(Default)]
+struct Foo {
+    x: i32,
+}
+
+fn main() {
+    let mut xs = <[Foo; 1]>::default();
+    xs[0].x = 1;
+    (&mut xs[0]).x = 2;
+}
diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.rs b/tests/ui/traits/non_lifetime_binders/universe-error1.rs
new file mode 100644
index 0000000..eadee6b
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/universe-error1.rs
@@ -0,0 +1,18 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Other<U: ?Sized> {}
+
+impl<U: ?Sized> Other<U> for U {}
+
+#[rustfmt::skip]
+fn foo<U: ?Sized>()
+where
+    for<T> T: Other<U> {}
+
+fn bar() {
+    foo::<_>();
+    //~^ ERROR the trait bound `T: Other<_>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr
new file mode 100644
index 0000000..bfcad72
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr
@@ -0,0 +1,27 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/universe-error1.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `T: Other<_>` is not satisfied
+  --> $DIR/universe-error1.rs:14:11
+   |
+LL |     foo::<_>();
+   |           ^ the trait `Other<_>` is not implemented for `T`
+   |
+note: required by a bound in `foo`
+  --> $DIR/universe-error1.rs:11:15
+   |
+LL | fn foo<U: ?Sized>()
+   |    --- required by a bound in this function
+LL | where
+LL |     for<T> T: Other<U> {}
+   |               ^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
new file mode 100644
index 0000000..d37943b
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
@@ -0,0 +1,34 @@
+//~ ERROR overflow
+// A regression test for #111729 checking that we correctly
+// track recursion depth for obligations returned by confirmation.
+use std::panic::RefUnwindSafe;
+
+trait Database {
+    type Storage;
+}
+trait Query<DB> {
+    type Data;
+}
+struct ParseQuery;
+struct RootDatabase {
+    _runtime: Runtime<RootDatabase>,
+}
+
+impl<T: RefUnwindSafe> Database for T {
+    type Storage = SalsaStorage;
+}
+impl Database for RootDatabase {
+    type Storage = SalsaStorage;
+}
+
+struct Runtime<DB: Database> {
+    _storage: Box<DB::Storage>,
+}
+struct SalsaStorage {
+    _parse: <ParseQuery as Query<RootDatabase>>::Data,
+}
+
+impl<DB: Database> Query<DB> for ParseQuery {
+    type Data = RootDatabase;
+}
+fn main() {}
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
new file mode 100644
index 0000000..8f9ce3e
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
@@ -0,0 +1,24 @@
+error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`)
+note: required because it appears within the type `RootDatabase`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8
+   |
+LL | struct RootDatabase {
+   |        ^^^^^^^^^^^^
+note: required for `RootDatabase` to implement `Database`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24
+   |
+LL | impl<T: RefUnwindSafe> Database for T {
+   |         -------------  ^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required because it appears within the type `Runtime<RootDatabase>`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8
+   |
+LL | struct Runtime<DB: Database> {
+   |        ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
index 6ed7667..f98c316 100644
--- a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
+++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
@@ -2,7 +2,7 @@
 // Check tautalogically false `Copy` bounds
 
 #![feature(trivial_bounds)]
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 fn copy_string(t: String) -> String where String: Copy { //~ WARNING trivial_bounds
     is_copy(&t);
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
new file mode 100644
index 0000000..e5bfbfd
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+type Tait<'a> = impl Sized + 'a;
+
+fn foo<'a, 'b>() {
+    if false {
+        if { return } {
+            let y: Tait<'b> = 1i32;
+            //~^ ERROR concrete type differs from previous defining opaque type use
+        }
+    }
+    let x: Tait<'a> = ();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
new file mode 100644
index 0000000..f2eb7bc
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/different_defining_uses_never_type-2.rs:8:31
+   |
+LL |             let y: Tait<'b> = 1i32;
+   |                               ^^^^ expected `()`, got `i32`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses_never_type-2.rs:12:23
+   |
+LL |     let x: Tait<'a> = ();
+   |                       ^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
new file mode 100644
index 0000000..2b30a9c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+type Tait<T> = impl Sized;
+
+fn foo<T, U>() {
+    if false {
+        if { return } {
+            let y: Tait<U> = 1i32;
+            //~^ ERROR concrete type differs from previous defining opaque type use
+        }
+    }
+    let x: Tait<T> = ();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
new file mode 100644
index 0000000..8fc2e22
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/different_defining_uses_never_type-3.rs:8:30
+   |
+LL |             let y: Tait<U> = 1i32;
+   |                              ^^^^ expected `()`, got `i32`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses_never_type-3.rs:12:22
+   |
+LL |     let x: Tait<T> = ();
+   |                      ^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
index da845e8..9ae2c34 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
@@ -8,6 +8,7 @@
 
 fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
     //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
+    //~| ERROR concrete type differs from previous defining opaque type use
     (a, a)
 }
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
index 66a6b0b..0d24d42 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -10,6 +10,15 @@
 LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
    |                                                                ++++++++++++++++++++++++++
 
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn.rs:9:45
+   |
+LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
+   |                                             ^^^^^^^^^^^^^^^^^^
+   |                                             |
+   |                                             expected `&B`, got `&A`
+   |                                             this expression supplies two conflicting concrete types for the same opaque type
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type/type-dependent-def-issue-49241.rs b/tests/ui/type/type-dependent-def-issue-49241.rs
index caf5bad..4b6bc61 100644
--- a/tests/ui/type/type-dependent-def-issue-49241.rs
+++ b/tests/ui/type/type-dependent-def-issue-49241.rs
@@ -2,5 +2,4 @@
     let v = vec![0];
     const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
     let s: [u32; l] = v.into_iter().collect();
-    //~^ constant
 }
diff --git a/tests/ui/type/type-dependent-def-issue-49241.stderr b/tests/ui/type/type-dependent-def-issue-49241.stderr
index af16a6e..64c7687 100644
--- a/tests/ui/type/type-dependent-def-issue-49241.stderr
+++ b/tests/ui/type/type-dependent-def-issue-49241.stderr
@@ -6,12 +6,6 @@
    |     |
    |     help: consider using `let` instead of `const`: `let l`
 
-note: erroneous constant used
-  --> $DIR/type-dependent-def-issue-49241.rs:4:18
-   |
-LL |     let s: [u32; l] = v.into_iter().collect();
-   |                  ^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/type/type-path-err-node-types.stderr b/tests/ui/type/type-path-err-node-types.stderr
index 1aed1db..8b12aa1 100644
--- a/tests/ui/type/type-path-err-node-types.stderr
+++ b/tests/ui/type/type-path-err-node-types.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared type `NonExistent`
-  --> $DIR/type-path-err-node-types.rs:15:5
-   |
-LL |     NonExistent::Assoc::<u8>;
-   |     ^^^^^^^^^^^ use of undeclared type `NonExistent`
-
 error[E0412]: cannot find type `Nonexistent` in this scope
   --> $DIR/type-path-err-node-types.rs:7:12
    |
@@ -22,6 +16,12 @@
 LL |     nonexistent.nonexistent::<u8>();
    |     ^^^^^^^^^^^ not found in this scope
 
+error[E0433]: failed to resolve: use of undeclared type `NonExistent`
+  --> $DIR/type-path-err-node-types.rs:15:5
+   |
+LL |     NonExistent::Assoc::<u8>;
+   |     ^^^^^^^^^^^ use of undeclared type `NonExistent`
+
 error[E0282]: type annotations needed
   --> $DIR/type-path-err-node-types.rs:23:14
    |
diff --git a/tests/ui/underscore-imports/issue-110164.rs b/tests/ui/underscore-imports/issue-110164.rs
new file mode 100644
index 0000000..6fd1341
--- /dev/null
+++ b/tests/ui/underscore-imports/issue-110164.rs
@@ -0,0 +1,19 @@
+use self::*;
+//~^ ERROR unresolved import `self::*`
+use crate::*;
+//~^ ERROR unresolved import `crate::*`
+use _::a;
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR unresolved import `_`
+use _::*;
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR unresolved import `_`
+
+fn main() {
+    use _::a;
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR unresolved import `_`
+    use _::*;
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR unresolved import `_`
+}
diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.stderr
new file mode 100644
index 0000000..5016c41
--- /dev/null
+++ b/tests/ui/underscore-imports/issue-110164.stderr
@@ -0,0 +1,71 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:5:5
+   |
+LL | use _::a;
+   |     ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:8:5
+   |
+LL | use _::*;
+   |     ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:13:9
+   |
+LL |     use _::a;
+   |         ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:16:9
+   |
+LL |     use _::*;
+   |         ^ expected identifier, found reserved identifier
+
+error[E0432]: unresolved import `self::*`
+  --> $DIR/issue-110164.rs:1:5
+   |
+LL | use self::*;
+   |     ^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `crate::*`
+  --> $DIR/issue-110164.rs:3:5
+   |
+LL | use crate::*;
+   |     ^^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:8:5
+   |
+LL | use _::*;
+   |     ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:5:5
+   |
+LL | use _::a;
+   |     ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:13:9
+   |
+LL |     use _::a;
+   |         ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:16:9
+   |
+LL |     use _::*;
+   |         ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs
index 4b001ac..cfd60a8 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.rs
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs
@@ -16,7 +16,9 @@
 }
 
 enum Foo {
+    //~^ NOTE `Foo` defined here
     A(foo::SecretlyEmpty),
+    //~^ NOTE not covered
     B(foo::NotSoSecretlyEmpty),
     C(NotSoSecretlyEmpty),
     D(u32, u32),
@@ -27,4 +29,9 @@
     let Foo::D(_y, _z) = x;
     //~^ ERROR refutable pattern in local binding
     //~| `Foo::A(_)` not covered
+    //~| NOTE `let` bindings require an "irrefutable pattern"
+    //~| NOTE for more information
+    //~| NOTE pattern `Foo::A(_)` is currently uninhabited
+    //~| NOTE the matched value is of type `Foo`
+    //~| HELP you might want to use `let else`
 }
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.stderr
index 8cafea5..daf75f5 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -1,5 +1,5 @@
 error[E0005]: refutable pattern in local binding
-  --> $DIR/uninhabited-irrefutable.rs:27:9
+  --> $DIR/uninhabited-irrefutable.rs:29:9
    |
 LL |     let Foo::D(_y, _z) = x;
    |         ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered
@@ -11,8 +11,10 @@
    |
 LL | enum Foo {
    |      ^^^
+LL |
 LL |     A(foo::SecretlyEmpty),
    |     - not covered
+   = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
    = note: the matched value is of type `Foo`
 help: you might want to use `let else` to handle the variant that isn't matched
    |
diff --git a/tests/ui/unsized-locals/align.rs b/tests/ui/unsized-locals/align.rs
new file mode 100644
index 0000000..01be8f3
--- /dev/null
+++ b/tests/ui/unsized-locals/align.rs
@@ -0,0 +1,30 @@
+// Test that unsized locals uphold alignment requirements.
+// Regression test for #71416.
+// run-pass
+#![feature(unsized_locals)]
+#![allow(incomplete_features)]
+use std::any::Any;
+
+#[repr(align(256))]
+#[allow(dead_code)]
+struct A {
+    v: u8
+}
+
+impl A {
+    fn f(&self) -> *const A {
+        assert_eq!(self as *const A as usize % 256, 0);
+        self
+    }
+}
+
+fn mk() -> Box<dyn Any> {
+    Box::new(A { v: 4 })
+}
+
+fn main() {
+    let x = *mk();
+    let dwncst = x.downcast_ref::<A>().unwrap();
+    let addr = dwncst.f();
+    assert_eq!(addr as usize % 256, 0);
+}
diff --git a/tests/ui/unsized-locals/issue-67981.rs b/tests/ui/unsized-locals/issue-67981.rs
new file mode 100644
index 0000000..3eb6498
--- /dev/null
+++ b/tests/ui/unsized-locals/issue-67981.rs
@@ -0,0 +1,9 @@
+#![feature(unsized_fn_params)]
+
+fn main() {
+    let f: fn([u8]) = |_| {};
+    //~^ERROR the size for values of type `[u8]` cannot be known at compilation time
+    let slice: Box<[u8]> = Box::new([1; 8]);
+
+    f(*slice);
+}
diff --git a/tests/ui/unsized-locals/issue-67981.stderr b/tests/ui/unsized-locals/issue-67981.stderr
new file mode 100644
index 0000000..a4b179a
--- /dev/null
+++ b/tests/ui/unsized-locals/issue-67981.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-67981.rs:4:24
+   |
+LL |     let f: fn([u8]) = |_| {};
+   |                        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     let f: fn([u8]) = |&_| {};
+   |                        +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.rs b/tests/ui/unsized/box-instead-of-dyn-fn.rs
index 2fa741b..321c2eb 100644
--- a/tests/ui/unsized/box-instead-of-dyn-fn.rs
+++ b/tests/ui/unsized/box-instead-of-dyn-fn.rs
@@ -8,7 +8,6 @@
         move || println!("{a}")
     } else {
         Box::new(move || println!("{}", b))
-        //~^ ERROR `if` and `else` have incompatible types
     }
 }
 
diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.stderr b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
index bfb7c39..6087f5c 100644
--- a/tests/ui/unsized/box-instead-of-dyn-fn.stderr
+++ b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
@@ -1,42 +1,21 @@
-error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/box-instead-of-dyn-fn.rs:10:9
-   |
-LL | /     if a % 2 == 0 {
-LL | |         move || println!("{a}")
-   | |         -----------------------
-   | |         |
-   | |         the expected closure
-   | |         expected because of this
-LL | |     } else {
-LL | |         Box::new(move || println!("{}", b))
-   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found `Box<[closure@box-instead-of-dyn-fn.rs:10:18]>`
-LL | |
-LL | |     }
-   | |_____- `if` and `else` have incompatible types
-   |
-   = note: expected closure `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:16]`
-               found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:25]>`
-
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/box-instead-of-dyn-fn.rs:5:56
    |
 LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a {
    |                                                        ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl Fn() + 'a` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box<dyn Fn() + 'a> {
-   |                                                        ++++             +
-help: ... and box this value
+LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> impl Fn() + 'a {
+   |                                                        ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         Box::new(move || println!("{a}"))
-   |         +++++++++                       +
+LL ~ fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box<dyn Fn() + 'a> {
+LL |
+LL |     if a % 2 == 0 {
+LL ~         Box::new(move || println!("{a}"))
+   |
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0746.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0746`.
diff --git a/tests/ui/unsized/issue-91801.stderr b/tests/ui/unsized/issue-91801.stderr
index 8795aa1..da5c432 100644
--- a/tests/ui/unsized/issue-91801.stderr
+++ b/tests/ui/unsized/issue-91801.stderr
@@ -4,11 +4,10 @@
 LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
    |                                                                             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 10:70]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a`
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a {
-   |                                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box<Validator<'a>> {
+   |                                                                             ++++             +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/unsized/issue-91803.stderr b/tests/ui/unsized/issue-91803.stderr
index 2dad9e8..a43b8d0 100644
--- a/tests/ui/unsized/issue-91803.stderr
+++ b/tests/ui/unsized/issue-91803.stderr
@@ -4,11 +4,14 @@
 LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> {
    |                                           ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Foo<'a>` as the return type, as all return paths are of type `Box<_>`, which implements `Foo<'a>`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn or<'a>(first: &'static dyn Foo<'a>) -> impl Foo<'a> {
-   |                                           ~~~~~~~~~~~~
+   |                                           ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn or<'a>(first: &'static dyn Foo<'a>) -> Box<dyn Foo<'a>> {
+   |                                           ++++           +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/use/use-self-type.stderr b/tests/ui/use/use-self-type.stderr
index e615394..3da04a8 100644
--- a/tests/ui/use/use-self-type.stderr
+++ b/tests/ui/use/use-self-type.stderr
@@ -8,7 +8,7 @@
   --> $DIR/use-self-type.rs:6:13
    |
 LL |         use Self::f;
-   |             ^^^^ `Self` is only available in impls, traits, and type definitions
+   |             ^^^^ `Self` cannot be used in imports
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs
index d65703e..c4fa850 100644
--- a/tests/ui/weird-exprs.rs
+++ b/tests/ui/weird-exprs.rs
@@ -5,13 +5,16 @@
 
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
+#![allow(redundant_semicolons)]
 #![allow(unreachable_code)]
 #![allow(unused_braces, unused_must_use, unused_parens)]
 #![allow(uncommon_codepoints, confusable_idents)]
+#![allow(unused_imports)]
 #![allow(unreachable_patterns)]
 
 #![recursion_limit = "256"]
 
+extern crate core;
 use std::cell::Cell;
 use std::mem::swap;
 
@@ -204,6 +207,30 @@
     assert!(matches!(x(..), |_| Some(4)));
 }
 
+fn semisemisemisemisemi() {
+    ;;;;;;; ;;;;;;; ;;;    ;;; ;;
+    ;;      ;;      ;;;;  ;;;; ;;
+    ;;;;;;; ;;;;;   ;; ;;;; ;; ;;
+         ;; ;;      ;;  ;;  ;; ;;
+    ;;;;;;; ;;;;;;; ;;      ;; ;;
+}
+
+fn useful_syntax() {
+    use {{std::{{collections::{{HashMap}}}}}};
+    use ::{{{{core}, {std}}}};
+    use {{::{{core as core2}}}};
+}
+
+fn infcx() {
+    pub mod cx {
+        pub mod cx {
+            pub use super::cx;
+            pub struct Cx;
+        }
+    }
+    let _cx: cx::cx::Cx = cx::cx::cx::cx::cx::Cx;
+}
+
 pub fn main() {
     strange();
     funny();
@@ -227,4 +254,7 @@
     function();
     bathroom_stall();
     closure_matching();
+    semisemisemisemisemi();
+    useful_syntax();
+    infcx();
 }
diff --git a/triagebot.toml b/triagebot.toml
index 54c8b20..d7cd3ea 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -371,31 +371,6 @@
 message = "Some changes might have occurred in exhaustiveness checking"
 cc = ["@Nadrieril"]
 
-[mentions."library"]
-message = """
-Hey! It looks like you've submitted a new PR for the library teams!
-
-If this PR contains changes to any `rust-lang/rust` public library APIs then \
-please comment with `@rustbot label +T-libs-api -T-libs` to tag it \
-appropriately. If this PR contains changes to any unstable APIs please edit \
-the PR description to add a link to the relevant [API Change \
-Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html) \
-or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29) \
-if you haven't already. If you're unsure where your change falls no worries, \
-just leave it as is and the reviewer will take a look and make a decision to \
-forward on if necessary.
-
-Examples of `T-libs-api` changes:
-
-* Stabilizing library features
-* Introducing insta-stable changes such as new implementations of existing \
-  stable traits on existing stable types
-* Introducing new or changing existing unstable library APIs (excluding \
-  permanently unstable features / features without a tracking issue)
-* Changing public documentation in ways that create new stability guarantees
-* Changing observable runtime behavior of library APIs
-"""
-
 [mentions."src/librustdoc/clean/types.rs"]
 cc = ["@camelid"]
 
@@ -507,11 +482,11 @@
     "@petrochenkov",
     "@davidtwco",
     "@oli-obk",
-    "@lcnr",
     "@wesleywiser",
 ]
 compiler-team-contributors = [
     "@compiler-errors",
+    "@eholk",
     "@jackh726",
     "@TaKO8Ki",
     "@WaffleLapkin",
@@ -532,6 +507,7 @@
     "@Mark-Simulacrum",
     "@albertlarsan68",
     "@ozkanonur",
+    "@clubby789",
 ]
 infra-ci = [
     "@Mark-Simulacrum",
@@ -616,6 +592,7 @@
 "/compiler/rustc_llvm" =                     ["@cuviper"]
 "/compiler/rustc_middle/src/mir" =           ["compiler", "mir"]
 "/compiler/rustc_middle/src/traits" =        ["compiler", "types"]
+"/compiler/rustc_middle/src/ty" =            ["compiler", "types"]
 "/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"]
 "/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"]
 "/compiler/rustc_mir_build/src/build" =      ["compiler", "mir"]