about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--Cargo.lock52
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs8
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs159
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs10
-rw-r--r--compiler/rustc_lint/messages.ftl1
-rw-r--r--compiler/rustc_lint/src/early/diagnostics/check_cfg.rs8
-rw-r--r--compiler/rustc_lint/src/lints.rs10
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs6
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs6
-rw-r--r--compiler/rustc_middle/src/ty/context.rs21
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs62
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs13
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs8
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs12
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs6
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs98
-rw-r--r--compiler/rustc_type_ir/src/interner.rs9
-rw-r--r--library/core/src/array/mod.rs2
-rw-r--r--library/core/src/ffi/c_str.rs41
-rw-r--r--library/core/src/hint.rs2
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/option.rs30
-rw-r--r--library/core/src/sync/atomic.rs14
-rw-r--r--library/std/src/panic.rs2
-rw-r--r--library/std/src/panicking.rs8
-rw-r--r--library/std/src/sync/mpmc/list.rs2
-rw-r--r--library/std/src/sys/net/connection/uefi/mod.rs59
-rw-r--r--library/std/src/sys/net/connection/uefi/tcp.rs21
-rw-r--r--library/std/src/sys/net/connection/uefi/tcp4.rs118
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs10
-rw-r--r--library/std/src/sys/pal/windows/os.rs2
-rw-r--r--library/std/src/sys/process/unix/common.rs116
-rw-r--r--library/std/src/sys/process/unix/common/cstring_array.rs115
-rw-r--r--library/std/src/sys/thread_local/guard/key.rs4
-rw-r--r--library/std/tests/path.rs31
-rw-r--r--src/bootstrap/src/utils/shared_helpers.rs11
-rw-r--r--src/ci/citool/Cargo.lock12
-rw-r--r--src/ci/citool/Cargo.toml2
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh3
-rw-r--r--src/doc/rustc/src/platform-support/solaris.md1
-rw-r--r--src/doc/rustdoc/src/write-documentation/the-doc-attribute.md6
-rw-r--r--src/doc/unstable-book/src/compiler-flags/eagerly-emit-delayed-bugs.md12
-rw-r--r--src/doc/unstable-book/src/compiler-flags/track-diagnostics.md11
-rw-r--r--src/doc/unstable-book/src/compiler-flags/treat-err-as-bug.md13
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/clean/utils.rs53
-rw-r--r--src/librustdoc/clean/utils/tests.rs42
-rw-r--r--src/librustdoc/html/render/sidebar.rs2
-rw-r--r--src/librustdoc/html/render/write_shared.rs71
-rw-r--r--src/librustdoc/lib.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/generate-copyright/Cargo.toml2
-rw-r--r--src/tools/miri/src/shims/panic.rs10
-rw-r--r--src/tools/miri/src/shims/windows/env.rs6
-rw-r--r--src/tools/miri/tests/fail/panic/bad_unwind.stderr4
-rw-r--r--src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr8
-rw-r--r--src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr8
-rw-r--r--src/tools/miri/tests/pass/backtrace/backtrace-global-alloc.stderr8
-rw-r--r--src/tools/miri/tests/pass/backtrace/backtrace-std.stderr8
-rw-r--r--src/tools/rustbook/Cargo.lock53
-rw-r--r--src/tools/rustbook/Cargo.toml2
-rw-r--r--tests/assembly/asm/aarch64-types.rs7
-rw-r--r--tests/codegen/frame-pointer.rs4
-rw-r--r--tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir36
-rw-r--r--tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir4
-rw-r--r--tests/rustdoc-js/auxiliary/interner.rs8
-rw-r--r--tests/rustdoc-js/looks-like-rustc-interner.js6
-rw-r--r--tests/ui/async-await/dyn/mut-is-pointer-like.stderr28
-rw-r--r--tests/ui/async-await/dyn/works.stderr36
-rw-r--r--tests/ui/check-cfg/wrong-version-syntax.fixed14
-rw-r--r--tests/ui/check-cfg/wrong-version-syntax.rs14
-rw-r--r--tests/ui/check-cfg/wrong-version-syntax.stderr17
-rw-r--r--tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr21
-rw-r--r--tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs1
-rw-r--r--tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr19
-rw-r--r--tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs1
-rw-r--r--tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr20
-rw-r--r--tests/ui/error-codes/E0038.rs2
-rw-r--r--tests/ui/error-codes/E0038.stderr31
-rw-r--r--tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr34
-rw-r--r--tests/ui/generic-associated-types/trait-objects.rs2
-rw-r--r--tests/ui/generic-associated-types/trait-objects.stderr34
-rw-r--r--tests/ui/impl-trait/in-trait/dyn-compatibility.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/dyn-compatibility.stderr36
-rw-r--r--tests/ui/issues/issue-18959.rs1
-rw-r--r--tests/ui/issues/issue-18959.stderr22
-rw-r--r--tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs18
-rw-r--r--tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr49
-rw-r--r--tests/ui/traits/test-2.rs1
-rw-r--r--tests/ui/traits/test-2.stderr25
-rw-r--r--tests/ui/unsafe-binders/non-strucutral-type-diag.rs17
-rw-r--r--tests/ui/unsafe-binders/non-strucutral-type-diag.stderr13
-rw-r--r--triagebot.toml11
106 files changed, 1054 insertions, 962 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e155e253784..aadc7c48ea8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,7 +5,7 @@ and we appreciate all of them.
 
 The best way to get started is by asking for help in the [#new
 members](https://rust-lang.zulipchat.com/#narrow/stream/122652-new-members)
-Zulip stream. We have lots of docs below of how to get started on your own, but
+Zulip stream. We have a lot of documentation below on how to get started on your own, but
 the Zulip stream is the best place to *ask* for help.
 
 Documentation for contributing to the compiler or tooling is located in the [Guide to Rustc
@@ -14,7 +14,7 @@ standard library in the [Standard library developers Guide][std-dev-guide], comm
 
 ## Making changes to subtrees and submodules
 
-For submodules, changes need to be made against the repository corresponding the
+For submodules, changes need to be made against the repository corresponding to the
 submodule, and not the main `rust-lang/rust` repository.
 
 For subtrees, prefer sending a PR against the subtree's repository if it does
@@ -25,7 +25,7 @@ rustc-dev-guide change that does not accompany a compiler change).
 
 The [rustc-dev-guide] is meant to help document how rustc –the Rust compiler– works,
 as well as to help new contributors get involved in rustc development. It is recommended
-to read and understand the [rustc-dev-guide] before making a contribution. This guide
+that you read and understand the [rustc-dev-guide] before making a contribution. This guide
 talks about the different bots in the Rust ecosystem, the Rust development tools,
 bootstrapping, the compiler architecture, source code representation, and more.
 
@@ -33,7 +33,7 @@ bootstrapping, the compiler architecture, source code representation, and more.
 
 There are many ways you can get help when you're stuck. Rust has many platforms for this:
 [internals], [rust-zulip], and [rust-discord]. It is recommended to ask for help on
-the [rust-zulip], but any of these platforms are a great way to seek help and even
+the [rust-zulip], but any of these platforms are great ways to seek help and even
 find a mentor! You can learn more about asking questions and getting help in the
 [Asking Questions](https://rustc-dev-guide.rust-lang.org/getting-started.html#asking-questions) chapter of the [rustc-dev-guide].
 
diff --git a/Cargo.lock b/Cargo.lock
index 4e5040349e0..177ff6594e2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -183,7 +183,20 @@ version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7"
 dependencies = [
- "askama_derive",
+ "askama_derive 0.13.1",
+ "itoa",
+ "percent-encoding",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "askama"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
+dependencies = [
+ "askama_derive 0.14.0",
  "itoa",
  "percent-encoding",
  "serde",
@@ -196,7 +209,24 @@ version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac"
 dependencies = [
- "askama_parser",
+ "askama_parser 0.13.0",
+ "basic-toml",
+ "memchr",
+ "proc-macro2",
+ "quote",
+ "rustc-hash 2.1.1",
+ "serde",
+ "serde_derive",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "askama_derive"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
+dependencies = [
+ "askama_parser 0.14.0",
  "basic-toml",
  "memchr",
  "proc-macro2",
@@ -220,6 +250,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "askama_parser"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
+dependencies = [
+ "memchr",
+ "serde",
+ "serde_derive",
+ "winnow 0.7.10",
+]
+
+[[package]]
 name = "autocfg"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -540,7 +582,7 @@ name = "clippy"
 version = "0.1.89"
 dependencies = [
  "anstream",
- "askama",
+ "askama 0.13.1",
  "cargo_metadata 0.18.1",
  "clippy_config",
  "clippy_lints",
@@ -1389,7 +1431,7 @@ name = "generate-copyright"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "askama",
+ "askama 0.14.0",
  "cargo_metadata 0.18.1",
  "serde",
  "serde_json",
@@ -4622,7 +4664,7 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "arrayvec",
- "askama",
+ "askama 0.14.0",
  "base64",
  "expect-test",
  "indexmap",
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index a614b4f00ff..53b5dff9c6b 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -291,6 +291,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             probe::ObjectPick => {
                 let trait_def_id = pick.item.container_id(self.tcx);
 
+                // If the trait is not object safe (specifically, we care about when
+                // the receiver is not valid), then there's a chance that we will not
+                // actually be able to recover the object by derefing the receiver like
+                // we should if it were valid.
+                if !self.tcx.is_dyn_compatible(trait_def_id) {
+                    return ty::GenericArgs::extend_with_error(self.tcx, trait_def_id, &[]);
+                }
+
                 // This shouldn't happen for non-region error kinds, but may occur
                 // when we have error regions. Specifically, since we canonicalize
                 // during method steps, we may successfully deref when we assemble
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index a1a0926cd81..26ecaebe97f 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -17,8 +17,7 @@ use tracing::debug;
 
 use crate::infer::InferCtxt;
 use crate::infer::canonical::{
-    Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind,
-    OriginalQueryValues,
+    Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarKind, OriginalQueryValues,
 };
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -174,10 +173,8 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
         match r.kind() {
             ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r,
 
-            ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
-                CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) },
-                r,
-            ),
+            ty::RePlaceholder(placeholder) => canonicalizer
+                .canonical_var_for_region(CanonicalVarKind::PlaceholderRegion(placeholder), r),
 
             ty::ReVar(vid) => {
                 let universe = infcx
@@ -186,10 +183,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
                     .unwrap_region_constraints()
                     .probe_value(vid)
                     .unwrap_err();
-                canonicalizer.canonical_var_for_region(
-                    CanonicalVarInfo { kind: CanonicalVarKind::Region(universe) },
-                    r,
-                )
+                canonicalizer.canonical_var_for_region(CanonicalVarKind::Region(universe), r)
             }
 
             _ => {
@@ -294,7 +288,7 @@ struct Canonicalizer<'cx, 'tcx> {
     /// Set to `None` to disable the resolution of inference variables.
     infcx: Option<&'cx InferCtxt<'tcx>>,
     tcx: TyCtxt<'tcx>,
-    variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>,
+    variables: SmallVec<[CanonicalVarKind<'tcx>; 8]>,
     query_state: &'cx mut OriginalQueryValues<'tcx>,
     // Note that indices is only used once `var_values` is big enough to be
     // heap-allocated.
@@ -368,9 +362,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                             ui = ty::UniverseIndex::ROOT;
                         }
                         self.canonicalize_ty_var(
-                            CanonicalVarInfo {
-                                kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
-                            },
+                            CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
                             t,
                         )
                     }
@@ -382,10 +374,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                 if nt != t {
                     return self.fold_ty(nt);
                 } else {
-                    self.canonicalize_ty_var(
-                        CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
-                        t,
-                    )
+                    self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t)
                 }
             }
             ty::Infer(ty::FloatVar(vid)) => {
@@ -393,10 +382,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                 if nt != t {
                     return self.fold_ty(nt);
                 } else {
-                    self.canonicalize_ty_var(
-                        CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
-                        t,
-                    )
+                    self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Float), t)
                 }
             }
 
@@ -408,10 +394,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                 if !self.canonicalize_mode.preserve_universes() {
                     placeholder.universe = ty::UniverseIndex::ROOT;
                 }
-                self.canonicalize_ty_var(
-                    CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
-                    t,
-                )
+                self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(placeholder), t)
             }
 
             ty::Bound(debruijn, _) => {
@@ -483,10 +466,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                             // FIXME: perf problem described in #55921.
                             ui = ty::UniverseIndex::ROOT;
                         }
-                        return self.canonicalize_const_var(
-                            CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
-                            ct,
-                        );
+                        return self.canonicalize_const_var(CanonicalVarKind::Const(ui), ct);
                     }
                 }
             }
@@ -501,10 +481,8 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                 }
             }
             ty::ConstKind::Placeholder(placeholder) => {
-                return self.canonicalize_const_var(
-                    CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
-                    ct,
-                );
+                return self
+                    .canonicalize_const_var(CanonicalVarKind::PlaceholderConst(placeholder), ct);
             }
             _ => {}
         }
@@ -595,7 +573,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         debug_assert!(!out_value.has_infer() && !out_value.has_placeholders());
 
         let canonical_variables =
-            tcx.mk_canonical_var_infos(&canonicalizer.universe_canonicalized_variables());
+            tcx.mk_canonical_var_kinds(&canonicalizer.universe_canonicalized_variables());
 
         let max_universe = canonical_variables
             .iter()
@@ -610,18 +588,22 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// or returns an existing variable if `kind` has already been
     /// seen. `kind` is expected to be an unbound variable (or
     /// potentially a free region).
-    fn canonical_var(&mut self, info: CanonicalVarInfo<'tcx>, kind: GenericArg<'tcx>) -> BoundVar {
+    fn canonical_var(
+        &mut self,
+        var_kind: CanonicalVarKind<'tcx>,
+        value: GenericArg<'tcx>,
+    ) -> BoundVar {
         let Canonicalizer { variables, query_state, indices, .. } = self;
 
         let var_values = &mut query_state.var_values;
 
-        let universe = info.universe();
+        let universe = var_kind.universe();
         if universe != ty::UniverseIndex::ROOT {
             assert!(self.canonicalize_mode.preserve_universes());
 
             // Insert universe into the universe map. To preserve the order of the
             // universes in the value being canonicalized, we don't update the
-            // universe in `info` until we have finished canonicalizing.
+            // universe in `var_kind` until we have finished canonicalizing.
             match query_state.universe_map.binary_search(&universe) {
                 Err(idx) => query_state.universe_map.insert(idx, universe),
                 Ok(_) => {}
@@ -636,14 +618,14 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         if !var_values.spilled() {
             // `var_values` is stack-allocated. `indices` isn't used yet. Do a
             // direct linear search of `var_values`.
-            if let Some(idx) = var_values.iter().position(|&k| k == kind) {
+            if let Some(idx) = var_values.iter().position(|&v| v == value) {
                 // `kind` is already present in `var_values`.
                 BoundVar::new(idx)
             } else {
                 // `kind` isn't present in `var_values`. Append it. Likewise
-                // for `info` and `variables`.
-                variables.push(info);
-                var_values.push(kind);
+                // for `var_kind` and `variables`.
+                variables.push(var_kind);
+                var_values.push(value);
                 assert_eq!(variables.len(), var_values.len());
 
                 // If `var_values` has become big enough to be heap-allocated,
@@ -653,7 +635,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
                     *indices = var_values
                         .iter()
                         .enumerate()
-                        .map(|(i, &kind)| (kind, BoundVar::new(i)))
+                        .map(|(i, &value)| (value, BoundVar::new(i)))
                         .collect();
                 }
                 // The cv is the index of the appended element.
@@ -661,9 +643,9 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
             }
         } else {
             // `var_values` is large. Do a hashmap search via `indices`.
-            *indices.entry(kind).or_insert_with(|| {
-                variables.push(info);
-                var_values.push(kind);
+            *indices.entry(value).or_insert_with(|| {
+                variables.push(var_kind);
+                var_values.push(value);
                 assert_eq!(variables.len(), var_values.len());
                 BoundVar::new(variables.len() - 1)
             })
@@ -673,7 +655,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// Replaces the universe indexes used in `var_values` with their index in
     /// `query_state.universe_map`. This minimizes the maximum universe used in
     /// the canonicalized value.
-    fn universe_canonicalized_variables(self) -> SmallVec<[CanonicalVarInfo<'tcx>; 8]> {
+    fn universe_canonicalized_variables(self) -> SmallVec<[CanonicalVarKind<'tcx>; 8]> {
         if self.query_state.universe_map.len() == 1 {
             return self.variables;
         }
@@ -688,37 +670,33 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
 
         self.variables
             .iter()
-            .map(|v| CanonicalVarInfo {
-                kind: match v.kind {
-                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
-                        return *v;
-                    }
-                    CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
-                        CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
-                    }
-                    CanonicalVarKind::Region(u) => {
-                        CanonicalVarKind::Region(reverse_universe_map[&u])
-                    }
-                    CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
-                    CanonicalVarKind::PlaceholderTy(placeholder) => {
-                        CanonicalVarKind::PlaceholderTy(ty::Placeholder {
-                            universe: reverse_universe_map[&placeholder.universe],
-                            ..placeholder
-                        })
-                    }
-                    CanonicalVarKind::PlaceholderRegion(placeholder) => {
-                        CanonicalVarKind::PlaceholderRegion(ty::Placeholder {
-                            universe: reverse_universe_map[&placeholder.universe],
-                            ..placeholder
-                        })
-                    }
-                    CanonicalVarKind::PlaceholderConst(placeholder) => {
-                        CanonicalVarKind::PlaceholderConst(ty::Placeholder {
-                            universe: reverse_universe_map[&placeholder.universe],
-                            ..placeholder
-                        })
-                    }
-                },
+            .map(|&kind| match kind {
+                CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
+                    return kind;
+                }
+                CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
+                }
+                CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
+                CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
+                CanonicalVarKind::PlaceholderTy(placeholder) => {
+                    CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+                        universe: reverse_universe_map[&placeholder.universe],
+                        ..placeholder
+                    })
+                }
+                CanonicalVarKind::PlaceholderRegion(placeholder) => {
+                    CanonicalVarKind::PlaceholderRegion(ty::Placeholder {
+                        universe: reverse_universe_map[&placeholder.universe],
+                        ..placeholder
+                    })
+                }
+                CanonicalVarKind::PlaceholderConst(placeholder) => {
+                    CanonicalVarKind::PlaceholderConst(ty::Placeholder {
+                        universe: reverse_universe_map[&placeholder.universe],
+                        ..placeholder
+                    })
+                }
             })
             .collect()
     }
@@ -740,20 +718,17 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         &mut self,
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
-        self.canonical_var_for_region(
-            CanonicalVarInfo { kind: CanonicalVarKind::Region(ty::UniverseIndex::ROOT) },
-            r,
-        )
+        self.canonical_var_for_region(CanonicalVarKind::Region(ty::UniverseIndex::ROOT), r)
     }
 
     /// Creates a canonical variable (with the given `info`)
     /// representing the region `r`; return a region referencing it.
     fn canonical_var_for_region(
         &mut self,
-        info: CanonicalVarInfo<'tcx>,
+        var_kind: CanonicalVarKind<'tcx>,
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
-        let var = self.canonical_var(info, r.into());
+        let var = self.canonical_var(var_kind, r.into());
         let br = ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon };
         ty::Region::new_bound(self.cx(), self.binder_index, br)
     }
@@ -762,9 +737,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// if `ty_var` is bound to anything; if so, canonicalize
     /// *that*. Otherwise, create a new canonical variable for
     /// `ty_var`.
-    fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>) -> Ty<'tcx> {
+    fn canonicalize_ty_var(
+        &mut self,
+        var_kind: CanonicalVarKind<'tcx>,
+        ty_var: Ty<'tcx>,
+    ) -> Ty<'tcx> {
         debug_assert!(!self.infcx.is_some_and(|infcx| ty_var != infcx.shallow_resolve(ty_var)));
-        let var = self.canonical_var(info, ty_var.into());
+        let var = self.canonical_var(var_kind, ty_var.into());
         Ty::new_bound(self.tcx, self.binder_index, var.into())
     }
 
@@ -774,13 +753,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// `const_var`.
     fn canonicalize_const_var(
         &mut self,
-        info: CanonicalVarInfo<'tcx>,
-        const_var: ty::Const<'tcx>,
+        var_kind: CanonicalVarKind<'tcx>,
+        ct_var: ty::Const<'tcx>,
     ) -> ty::Const<'tcx> {
         debug_assert!(
-            !self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
+            !self.infcx.is_some_and(|infcx| ct_var != infcx.shallow_resolve_const(ct_var))
         );
-        let var = self.canonical_var(info, const_var.into());
+        let var = self.canonical_var(var_kind, ct_var.into());
         ty::Const::new_bound(self.tcx, self.binder_index, var)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 3be07dbe208..5dffedc7099 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -81,14 +81,14 @@ impl<'tcx> InferCtxt<'tcx> {
     fn instantiate_canonical_vars(
         &self,
         span: Span,
-        variables: &List<CanonicalVarInfo<'tcx>>,
+        variables: &List<CanonicalVarKind<'tcx>>,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> CanonicalVarValues<'tcx> {
         CanonicalVarValues {
             var_values: self.tcx.mk_args_from_iter(
                 variables
                     .iter()
-                    .map(|info| self.instantiate_canonical_var(span, info, &universe_map)),
+                    .map(|kind| self.instantiate_canonical_var(span, kind, &universe_map)),
             ),
         }
     }
@@ -104,10 +104,10 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn instantiate_canonical_var(
         &self,
         span: Span,
-        cv_info: CanonicalVarInfo<'tcx>,
+        kind: CanonicalVarKind<'tcx>,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> GenericArg<'tcx> {
-        match cv_info.kind {
+        match kind {
             CanonicalVarKind::Ty(ty_kind) => {
                 let ty = match ty_kind {
                     CanonicalTyVarKind::General(ui) => {
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 1ae864c454f..ec72e05494b 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -445,17 +445,17 @@ impl<'tcx> InferCtxt<'tcx> {
         // a fresh inference variable.
         let result_args = CanonicalVarValues {
             var_values: self.tcx.mk_args_from_iter(
-                query_response.variables.iter().enumerate().map(|(index, info)| {
-                    if info.universe() != ty::UniverseIndex::ROOT {
+                query_response.variables.iter().enumerate().map(|(index, var_kind)| {
+                    if var_kind.universe() != ty::UniverseIndex::ROOT {
                         // A variable from inside a binder of the query. While ideally these shouldn't
                         // exist at all, we have to deal with them for now.
-                        self.instantiate_canonical_var(cause.span, info, |u| {
+                        self.instantiate_canonical_var(cause.span, var_kind, |u| {
                             universe_map[u.as_usize()]
                         })
-                    } else if info.is_existential() {
+                    } else if var_kind.is_existential() {
                         match opt_values[BoundVar::new(index)] {
                             Some(k) => k,
-                            None => self.instantiate_canonical_var(cause.span, info, |u| {
+                            None => self.instantiate_canonical_var(cause.span, var_kind, |u| {
                                 universe_map[u.as_usize()]
                             }),
                         }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 08180bf8f8b..7fdf26bf3af 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -835,6 +835,7 @@ lint_unexpected_cfg_name_similar_name = there is a config with a similar name
 lint_unexpected_cfg_name_similar_name_different_values = there is a config with a similar name and different values
 lint_unexpected_cfg_name_similar_name_no_value = there is a config with a similar name and no value
 lint_unexpected_cfg_name_similar_name_value = there is a config with a similar name and value
+lint_unexpected_cfg_name_version_syntax = there is a similar config predicate: `version("..")`
 lint_unexpected_cfg_name_with_similar_value = found config with similar value
 
 lint_unexpected_cfg_value = unexpected `cfg` condition value: {$has_value ->
diff --git a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs
index 946dbc34f71..e2f5dd315d5 100644
--- a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs
@@ -140,6 +140,14 @@ pub(super) fn unexpected_cfg_name(
 
     let code_sugg = if is_feature_cfg && is_from_cargo {
         lints::unexpected_cfg_name::CodeSuggestion::DefineFeatures
+    // Suggest correct `version("..")` predicate syntax
+    } else if let Some((_value, value_span)) = value
+        && name == sym::version
+    {
+        lints::unexpected_cfg_name::CodeSuggestion::VersionSyntax {
+            between_name_and_value: name_span.between(value_span),
+            after_value: value_span.shrink_to_hi(),
+        }
     // Suggest the most probable if we found one
     } else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
         is_feature_cfg |= best_match == sym::feature;
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 7268a7f704f..af8fa8ffa1f 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2273,6 +2273,16 @@ pub(crate) mod unexpected_cfg_name {
     pub(crate) enum CodeSuggestion {
         #[help(lint_unexpected_cfg_define_features)]
         DefineFeatures,
+        #[multipart_suggestion(
+            lint_unexpected_cfg_name_version_syntax,
+            applicability = "machine-applicable"
+        )]
+        VersionSyntax {
+            #[suggestion_part(code = "(")]
+            between_name_and_value: Span,
+            #[suggestion_part(code = ")")]
+            after_value: Span,
+        },
         #[suggestion(
             lint_unexpected_cfg_name_similar_name_value,
             applicability = "maybe-incorrect",
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 5b860374496..2bbc48b633c 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -27,7 +27,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lock;
 use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
 pub use rustc_type_ir as ir;
-pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
+pub use rustc_type_ir::CanonicalTyVarKind;
 use smallvec::SmallVec;
 
 use crate::mir::ConstraintCategory;
@@ -35,9 +35,9 @@ use crate::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt}
 
 pub type CanonicalQueryInput<'tcx, V> = ir::CanonicalQueryInput<TyCtxt<'tcx>, V>;
 pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
-pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>;
+pub type CanonicalVarKind<'tcx> = ir::CanonicalVarKind<TyCtxt<'tcx>>;
 pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
-pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
+pub type CanonicalVarKinds<'tcx> = &'tcx List<CanonicalVarKind<'tcx>>;
 
 /// When we canonicalize a value to form a query, we wind up replacing
 /// various parts of it with canonical variables. This struct stores
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 5ff87959a80..e0f70737add 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -18,7 +18,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::{Span, SpanDecoder, SpanEncoder};
 
 use crate::arena::ArenaAllocatable;
-use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::{CanonicalVarKind, CanonicalVarKinds};
 use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance};
 use crate::mir::mono::MonoItem;
 use crate::mir::{self};
@@ -310,11 +310,11 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> {
     }
 }
 
-impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarInfos<'tcx> {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
     fn decode(decoder: &mut D) -> Self {
         let len = decoder.read_usize();
         decoder.interner().mk_canonical_var_infos_from_iter(
-            (0..len).map::<CanonicalVarInfo<'tcx>, _>(|_| Decodable::decode(decoder)),
+            (0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
         )
     }
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index c205d53b93f..8c915fea950 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -60,7 +60,7 @@ use tracing::{debug, instrument};
 
 use crate::arena::Arena;
 use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind, CanonicalVarKinds};
 use crate::lint::lint_level;
 use crate::metadata::ModChild;
 use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature};
@@ -107,9 +107,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.mk_predefined_opaques_in_body(data)
     }
     type LocalDefIds = &'tcx ty::List<LocalDefId>;
-    type CanonicalVars = CanonicalVarInfos<'tcx>;
-    fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
-        self.mk_canonical_var_infos(infos)
+    type CanonicalVarKinds = CanonicalVarKinds<'tcx>;
+    fn mk_canonical_var_kinds(
+        self,
+        kinds: &[ty::CanonicalVarKind<Self>],
+    ) -> Self::CanonicalVarKinds {
+        self.mk_canonical_var_kinds(kinds)
     }
 
     type ExternalConstraints = ExternalConstraints<'tcx>;
@@ -833,7 +836,7 @@ pub struct CtxtInterners<'tcx> {
     const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
     args: InternedSet<'tcx, GenericArgs<'tcx>>,
     type_lists: InternedSet<'tcx, List<Ty<'tcx>>>,
-    canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
+    canonical_var_kinds: InternedSet<'tcx, List<CanonicalVarKind<'tcx>>>,
     region: InternedSet<'tcx, RegionKind<'tcx>>,
     poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
     predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
@@ -872,7 +875,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             type_lists: InternedSet::with_capacity(N * 4),
             region: InternedSet::with_capacity(N * 4),
             poly_existential_predicates: InternedSet::with_capacity(N / 4),
-            canonical_var_infos: InternedSet::with_capacity(N / 2),
+            canonical_var_kinds: InternedSet::with_capacity(N / 2),
             predicate: InternedSet::with_capacity(N),
             clauses: InternedSet::with_capacity(N),
             projs: InternedSet::with_capacity(N * 4),
@@ -2675,7 +2678,7 @@ slice_interners!(
     const_lists: pub mk_const_list(Const<'tcx>),
     args: pub mk_args(GenericArg<'tcx>),
     type_lists: pub mk_type_list(Ty<'tcx>),
-    canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
+    canonical_var_kinds: pub mk_canonical_var_kinds(CanonicalVarKind<'tcx>),
     poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
     projs: pub mk_projs(ProjectionKind),
     place_elems: pub mk_place_elems(PlaceElem<'tcx>),
@@ -3055,9 +3058,9 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
     where
         I: Iterator<Item = T>,
-        T: CollectAndApply<CanonicalVarInfo<'tcx>, &'tcx List<CanonicalVarInfo<'tcx>>>,
+        T: CollectAndApply<CanonicalVarKind<'tcx>, &'tcx List<CanonicalVarKind<'tcx>>>,
     {
-        T::collect_and_apply(iter, |xs| self.mk_canonical_var_infos(xs))
+        T::collect_and_apply(iter, |xs| self.mk_canonical_var_kinds(xs))
     }
 
     pub fn mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output
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 b7d203e3cd7..e233358f386 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
@@ -382,6 +382,9 @@ fn extend_type_not_partial_eq<'tcx>(
         fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
             match ty.kind() {
                 ty::Dynamic(..) => return ControlFlow::Break(()),
+                // Unsafe binders never implement `PartialEq`, so avoid walking into them
+                // which would require instantiating its binder with placeholders too.
+                ty::UnsafeBinder(..) => return ControlFlow::Break(()),
                 ty::FnPtr(..) => return ControlFlow::Continue(()),
                 ty::Adt(def, _args) => {
                     let ty_def_id = def.did();
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index bbb4a162027..93b8940ee37 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -4,8 +4,8 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::solve::{Goal, QueryInput};
 use rustc_type_ir::{
-    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, InferCtxtLike,
-    Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, InferCtxtLike, Interner,
+    TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 
 use crate::delegate::SolverDelegate;
@@ -50,7 +50,7 @@ pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
 
     // Mutable fields.
     variables: &'a mut Vec<I::GenericArg>,
-    primitive_var_infos: Vec<CanonicalVarInfo<I>>,
+    var_kinds: Vec<CanonicalVarKind<I>>,
     variable_lookup_table: HashMap<I::GenericArg, usize>,
     binder_index: ty::DebruijnIndex,
 
@@ -73,7 +73,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
 
             variables,
             variable_lookup_table: Default::default(),
-            primitive_var_infos: Vec::new(),
+            var_kinds: Vec::new(),
             binder_index: ty::INNERMOST,
 
             cache: Default::default(),
@@ -106,7 +106,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
 
             variables,
             variable_lookup_table: Default::default(),
-            primitive_var_infos: Vec::new(),
+            var_kinds: Vec::new(),
             binder_index: ty::INNERMOST,
 
             cache: Default::default(),
@@ -123,7 +123,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             // We're able to reuse the `variable_lookup_table` as whether or not
             // it already contains an entry for `'static` does not matter.
             variable_lookup_table: env_canonicalizer.variable_lookup_table,
-            primitive_var_infos: env_canonicalizer.primitive_var_infos,
+            var_kinds: env_canonicalizer.var_kinds,
             binder_index: ty::INNERMOST,
 
             // We do not reuse the cache as it may contain entries whose canonicalized
@@ -149,7 +149,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
     fn get_or_insert_bound_var(
         &mut self,
         arg: impl Into<I::GenericArg>,
-        canonical_var_info: CanonicalVarInfo<I>,
+        kind: CanonicalVarKind<I>,
     ) -> ty::BoundVar {
         // FIXME: 16 is made up and arbitrary. We should look at some
         // perf data here.
@@ -162,14 +162,14 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             *self.variable_lookup_table.entry(arg).or_insert_with(|| {
                 let var = self.variables.len();
                 self.variables.push(arg);
-                self.primitive_var_infos.push(canonical_var_info);
+                self.var_kinds.push(kind);
                 var
             })
         } else {
             self.variables.iter().position(|&v| v == arg).unwrap_or_else(|| {
                 let var = self.variables.len();
                 self.variables.push(arg);
-                self.primitive_var_infos.push(canonical_var_info);
+                self.var_kinds.push(kind);
                 var
             })
         };
@@ -177,8 +177,8 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
         ty::BoundVar::from(idx)
     }
 
-    fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) {
-        let mut var_infos = self.primitive_var_infos;
+    fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVarKinds) {
+        let mut var_kinds = self.var_kinds;
         // See the rustc-dev-guide section about how we deal with universes
         // during canonicalization in the new solver.
         match self.canonicalize_mode {
@@ -192,25 +192,25 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             // information for placeholders and inference variables created inside
             // of the query.
             CanonicalizeMode::Response { max_input_universe } => {
-                for var in var_infos.iter_mut() {
+                for var in var_kinds.iter_mut() {
                     let uv = var.universe();
                     let new_uv = ty::UniverseIndex::from(
                         uv.index().saturating_sub(max_input_universe.index()),
                     );
                     *var = var.with_updated_universe(new_uv);
                 }
-                let max_universe = var_infos
+                let max_universe = var_kinds
                     .iter()
-                    .map(|info| info.universe())
+                    .map(|kind| kind.universe())
                     .max()
                     .unwrap_or(ty::UniverseIndex::ROOT);
 
-                let var_infos = self.delegate.cx().mk_canonical_var_infos(&var_infos);
-                return (max_universe, var_infos);
+                let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&var_kinds);
+                return (max_universe, var_kinds);
             }
         }
 
-        // Given a `var_infos` with existentials `En` and universals `Un` in
+        // Given a `var_kinds` with existentials `En` and universals `Un` in
         // universes `n`, this algorithm compresses them in place so that:
         //
         // - the new universe indices are as small as possible
@@ -219,12 +219,12 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
         //   2. put a placeholder in the same universe as an existential which cannot name it
         //
         // Let's walk through an example:
-        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
-        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
-        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
-        // - var_infos: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
-        // - var_infos: [E0, U1, E2, U1, E1, E6, U6], curr_compressed_uv: 2, next_orig_uv: 6
-        // - var_infos: [E0, U1, E1, U1, E1, E3, U3], curr_compressed_uv: 2, next_orig_uv: -
+        // - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
+        // - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
+        // - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
+        // - var_kinds: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
+        // - var_kinds: [E0, U1, E2, U1, E1, E6, U6], curr_compressed_uv: 2, next_orig_uv: 6
+        // - var_kinds: [E0, U1, E1, U1, E1, E3, U3], curr_compressed_uv: 2, next_orig_uv: -
         //
         // This algorithm runs in `O(mn)` where `n` is the number of different universes and
         // `m` the number of variables. This should be fine as both are expected to be small.
@@ -232,7 +232,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
         let mut existential_in_new_uv = None;
         let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
         while let Some(orig_uv) = next_orig_uv.take() {
-            let mut update_uv = |var: &mut CanonicalVarInfo<I>, orig_uv, is_existential| {
+            let mut update_uv = |var: &mut CanonicalVarKind<I>, orig_uv, is_existential| {
                 let uv = var.universe();
                 match uv.cmp(&orig_uv) {
                     Ordering::Less => (), // Already updated
@@ -284,7 +284,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             // Whenever we compress the universe of a placeholder, no existential with
             // an already compressed universe can name that placeholder.
             for is_existential in [false, true] {
-                for var in var_infos.iter_mut() {
+                for var in var_kinds.iter_mut() {
                     // We simply put all regions from the input into the highest
                     // compressed universe, so we only deal with them at the end.
                     if !var.is_region() {
@@ -298,7 +298,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
 
         // We put all regions into a separate universe.
         let mut first_region = true;
-        for var in var_infos.iter_mut() {
+        for var in var_kinds.iter_mut() {
             if var.is_region() {
                 if first_region {
                     first_region = false;
@@ -309,8 +309,8 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             }
         }
 
-        let var_infos = self.delegate.cx().mk_canonical_var_infos(&var_infos);
-        (curr_compressed_uv, var_infos)
+        let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&var_kinds);
+        (curr_compressed_uv, var_kinds)
     }
 
     fn cached_fold_ty(&mut self, t: I::Ty) -> I::Ty {
@@ -391,7 +391,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             }
         };
 
-        let var = self.get_or_insert_bound_var(t, CanonicalVarInfo { kind });
+        let var = self.get_or_insert_bound_var(t, kind);
 
         Ty::new_anon_bound(self.cx(), self.binder_index, var)
     }
@@ -475,7 +475,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
             }
         };
 
-        let var = self.get_or_insert_bound_var(r, CanonicalVarInfo { kind });
+        let var = self.get_or_insert_bound_var(r, kind);
 
         Region::new_anon_bound(self.cx(), self.binder_index, var)
     }
@@ -525,7 +525,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
             | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
         };
 
-        let var = self.get_or_insert_bound_var(c, CanonicalVarInfo { kind });
+        let var = self.get_or_insert_bound_var(c, kind);
 
         Const::new_anon_bound(self.cx(), self.binder_index, var)
     }
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index bb923612cff..32dc85b3e6a 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -61,7 +61,7 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
 
     fn instantiate_canonical_var_with_infer(
         &self,
-        cv_info: ty::CanonicalVarInfo<Self::Interner>,
+        kind: ty::CanonicalVarKind<Self::Interner>,
         span: <Self::Interner as Interner>::Span,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> <Self::Interner as Interner>::GenericArg;
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index c62f2e2e0e9..455a178595b 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -360,15 +360,15 @@ where
         }
 
         let var_values = delegate.cx().mk_args_from_iter(
-            response.variables.iter().enumerate().map(|(index, info)| {
-                if info.universe() != ty::UniverseIndex::ROOT {
+            response.variables.iter().enumerate().map(|(index, var_kind)| {
+                if var_kind.universe() != ty::UniverseIndex::ROOT {
                     // A variable from inside a binder of the query. While ideally these shouldn't
                     // exist at all (see the FIXME at the start of this method), we have to deal with
                     // them for now.
-                    delegate.instantiate_canonical_var_with_infer(info, span, |idx| {
+                    delegate.instantiate_canonical_var_with_infer(var_kind, span, |idx| {
                         prev_universe + idx.index()
                     })
-                } else if info.is_existential() {
+                } else if var_kind.is_existential() {
                     // As an optimization we sometimes avoid creating a new inference variable here.
                     //
                     // All new inference variables we create start out in the current universe of the caller.
@@ -379,12 +379,13 @@ where
                     if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] {
                         v
                     } else {
-                        delegate.instantiate_canonical_var_with_infer(info, span, |_| prev_universe)
+                        delegate
+                            .instantiate_canonical_var_with_infer(var_kind, span, |_| prev_universe)
                     }
                 } else {
                     // For placeholders which were already part of the input, we simply map this
                     // universal bound variable back the placeholder of the input.
-                    original_values[info.expect_placeholder_index()]
+                    original_values[var_kind.expect_placeholder_index()]
                 }
             }),
         );
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 9a4b95903a9..dfabb94ebfc 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -91,7 +91,7 @@ where
 
     /// The variable info for the `var_values`, only used to make an ambiguous response
     /// with no constraints.
-    variables: I::CanonicalVars,
+    variables: I::CanonicalVarKinds,
 
     /// What kind of goal we're currently computing, see the enum definition
     /// for more info.
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 8173146e2fe..2a641807154 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -354,7 +354,7 @@ where
 fn response_no_constraints_raw<I: Interner>(
     cx: I,
     max_universe: ty::UniverseIndex,
-    variables: I::CanonicalVars,
+    variables: I::CanonicalVarKinds,
     certainty: Certainty,
 ) -> CanonicalResponse<I> {
     ty::Canonical {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
index 87c07cd3109..4b75a6e5dbf 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,6 +16,10 @@ pub(crate) fn target() -> Target {
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             max_atomic_width: Some(128),
             stack_probes: StackProbeType::Inline,
             mcount: "\u{1}_mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
index e785069c78a..2a16d1de3b5 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -20,6 +20,10 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             abi: "ilp32".into(),
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             stack_probes: StackProbeType::Inline,
             mcount: "\u{1}_mcount".into(),
             endian: Endian::Big,
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
index 41c25393e12..d8651f305fe 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
 // for target ABI requirements.
@@ -20,6 +22,10 @@ pub(crate) fn target() -> Target {
             // As documented in https://developer.android.com/ndk/guides/cpu-features.html
             // the neon (ASIMD) and FP must exist on all android aarch64 targets.
             features: "+v8a,+neon,+fp-armv8".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             stack_probes: StackProbeType::Inline,
             supported_sanitizers: SanitizerSet::CFI
                 | SanitizerSet::HWADDRESS
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
index c6be2c20ea2..4220d74dfc8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -14,6 +16,10 @@ pub(crate) fn target() -> Target {
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             mcount: "\u{1}_mcount".into(),
             max_atomic_width: Some(128),
             stack_probes: StackProbeType::Inline,
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
index 166bb1ed215..a22c1289677 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
@@ -1,4 +1,4 @@
-use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,6 +15,10 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             abi: "ilp32".into(),
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             max_atomic_width: Some(128),
             stack_probes: StackProbeType::Inline,
             mcount: "\u{1}_mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index 58ba06e124c..58daaa03675 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -26,6 +28,12 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
-        options: TargetOptions { mcount: "\u{1}_mcount".into(), ..base },
+        options: TargetOptions {
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
+             mcount: "\u{1}_mcount".into(), ..base
+         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
index f2994b1232e..51cdebf22db 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_ohos::opts();
@@ -16,6 +18,10 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             mcount: "\u{1}_mcount".into(),
             stack_probes: StackProbeType::Inline,
             supported_sanitizers: SanitizerSet::ADDRESS
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index a60642b953c..b68a7845366 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -5,7 +5,7 @@ use rustc_hir::LangItem;
 use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
 use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
 use rustc_infer::infer::canonical::{
-    Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
+    Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarKind, CanonicalVarValues,
 };
 use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt};
 use rustc_infer::traits::solve::Goal;
@@ -190,11 +190,11 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
 
     fn instantiate_canonical_var_with_infer(
         &self,
-        cv_info: CanonicalVarInfo<'tcx>,
+        kind: CanonicalVarKind<'tcx>,
         span: Span,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> ty::GenericArg<'tcx> {
-        self.0.instantiate_canonical_var(span, cv_info, universe_map)
+        self.0.instantiate_canonical_var(span, kind, universe_map)
     }
 
     fn add_item_bounds_for_hidden_type(
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 67b67df4b28..2b1b0617cef 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -41,7 +41,7 @@ pub struct CanonicalQueryInput<I: Interner, V> {
 pub struct Canonical<I: Interner, V> {
     pub value: V,
     pub max_universe: UniverseIndex,
-    pub variables: I::CanonicalVars,
+    pub variables: I::CanonicalVarKinds,
 }
 
 impl<I: Interner, V> Canonical<I, V> {
@@ -89,63 +89,6 @@ impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
 /// a copy of the canonical value in some other inference context,
 /// with fresh inference variables replacing the canonical values.
 #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
-#[cfg_attr(
-    feature = "nightly",
-    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
-)]
-pub struct CanonicalVarInfo<I: Interner> {
-    pub kind: CanonicalVarKind<I>,
-}
-
-impl<I: Interner> CanonicalVarInfo<I> {
-    pub fn universe(self) -> UniverseIndex {
-        self.kind.universe()
-    }
-
-    #[must_use]
-    pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarInfo<I> {
-        CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
-    }
-
-    pub fn is_existential(&self) -> bool {
-        match self.kind {
-            CanonicalVarKind::Ty(_) => true,
-            CanonicalVarKind::PlaceholderTy(_) => false,
-            CanonicalVarKind::Region(_) => true,
-            CanonicalVarKind::PlaceholderRegion(..) => false,
-            CanonicalVarKind::Const(_) => true,
-            CanonicalVarKind::PlaceholderConst(_) => false,
-        }
-    }
-
-    pub fn is_region(&self) -> bool {
-        match self.kind {
-            CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
-            CanonicalVarKind::Ty(_)
-            | CanonicalVarKind::PlaceholderTy(_)
-            | CanonicalVarKind::Const(_)
-            | CanonicalVarKind::PlaceholderConst(_) => false,
-        }
-    }
-
-    pub fn expect_placeholder_index(self) -> usize {
-        match self.kind {
-            CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::Const(_) => {
-                panic!("expected placeholder: {self:?}")
-            }
-
-            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
-            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
-            CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.var().as_usize(),
-        }
-    }
-}
-
-/// Describes the "kind" of the canonical variable. This is a "kind"
-/// in the type-theory sense of the term -- i.e., a "meta" type system
-/// that analyzes type-like values.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
@@ -214,6 +157,39 @@ impl<I: Interner> CanonicalVarKind<I> {
             }
         }
     }
+
+    pub fn is_existential(self) -> bool {
+        match self {
+            CanonicalVarKind::Ty(_) => true,
+            CanonicalVarKind::PlaceholderTy(_) => false,
+            CanonicalVarKind::Region(_) => true,
+            CanonicalVarKind::PlaceholderRegion(..) => false,
+            CanonicalVarKind::Const(_) => true,
+            CanonicalVarKind::PlaceholderConst(_) => false,
+        }
+    }
+
+    pub fn is_region(self) -> bool {
+        match self {
+            CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::PlaceholderTy(_)
+            | CanonicalVarKind::Const(_)
+            | CanonicalVarKind::PlaceholderConst(_) => false,
+        }
+    }
+
+    pub fn expect_placeholder_index(self) -> usize {
+        match self {
+            CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::Const(_) => {
+                panic!("expected placeholder: {self:?}")
+            }
+
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
+            CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.var().as_usize(),
+        }
+    }
 }
 
 /// Rust actually has more than one category of type variables;
@@ -306,11 +282,11 @@ impl<I: Interner> CanonicalVarValues<I> {
 
     // Given a list of canonical variables, construct a set of values which are
     // the identity response.
-    pub fn make_identity(cx: I, infos: I::CanonicalVars) -> CanonicalVarValues<I> {
+    pub fn make_identity(cx: I, infos: I::CanonicalVarKinds) -> CanonicalVarValues<I> {
         CanonicalVarValues {
             var_values: cx.mk_args_from_iter(infos.iter().enumerate().map(
-                |(i, info)| -> I::GenericArg {
-                    match info.kind {
+                |(i, kind)| -> I::GenericArg {
+                    match kind {
                         CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
                             Ty::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index c10241cfcf0..7e88114df46 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -64,13 +64,16 @@ pub trait Interner:
         + TypeVisitable<Self>
         + SliceLike<Item = Self::LocalDefId>;
 
-    type CanonicalVars: Copy
+    type CanonicalVarKinds: Copy
         + Debug
         + Hash
         + Eq
-        + SliceLike<Item = ty::CanonicalVarInfo<Self>>
+        + SliceLike<Item = ty::CanonicalVarKind<Self>>
         + Default;
-    fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
+    fn mk_canonical_var_kinds(
+        self,
+        kinds: &[ty::CanonicalVarKind<Self>],
+    ) -> Self::CanonicalVarKinds;
 
     type ExternalConstraints: Copy
         + Debug
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 4476e3f7923..221ca91e005 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -588,7 +588,7 @@ impl<T, const N: usize> [T; N] {
     /// Returns a mutable slice containing the entire array. Equivalent to
     /// `&mut s[..]`.
     #[stable(feature = "array_as_slice", since = "1.57.0")]
-    #[rustc_const_unstable(feature = "const_array_as_mut_slice", issue = "133333")]
+    #[rustc_const_stable(feature = "const_array_as_mut_slice", since = "CURRENT_RUSTC_VERSION")]
     pub const fn as_mut_slice(&mut self) -> &mut [T] {
         self
     }
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index ac07c645c01..825402116e5 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -511,13 +511,8 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap();
-    /// assert_eq!(cstr.count_bytes(), 3);
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"\0").unwrap();
-    /// assert_eq!(cstr.count_bytes(), 0);
+    /// assert_eq!(c"foo".count_bytes(), 3);
+    /// assert_eq!(c"".count_bytes(), 0);
     /// ```
     #[inline]
     #[must_use]
@@ -533,19 +528,8 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// use std::ffi::CStr;
-    /// # use std::ffi::FromBytesWithNulError;
-    ///
-    /// # fn main() { test().unwrap(); }
-    /// # fn test() -> Result<(), FromBytesWithNulError> {
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0")?;
-    /// assert!(!cstr.is_empty());
-    ///
-    /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?;
-    /// assert!(empty_cstr.is_empty());
+    /// assert!(!c"foo".is_empty());
     /// assert!(c"".is_empty());
-    /// # Ok(())
-    /// # }
     /// ```
     #[inline]
     #[stable(feature = "cstr_is_empty", since = "1.71.0")]
@@ -569,10 +553,7 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_bytes(), b"foo");
+    /// assert_eq!(c"foo".to_bytes(), b"foo");
     /// ```
     #[inline]
     #[must_use = "this returns the result of the operation, \
@@ -598,10 +579,7 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");
+    /// assert_eq!(c"foo".to_bytes_with_nul(), b"foo\0");
     /// ```
     #[inline]
     #[must_use = "this returns the result of the operation, \
@@ -623,10 +601,8 @@ impl CStr {
     ///
     /// ```
     /// #![feature(cstr_bytes)]
-    /// use std::ffi::CStr;
     ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert!(cstr.bytes().eq(*b"foo"));
+    /// assert!(c"foo".bytes().eq(*b"foo"));
     /// ```
     #[inline]
     #[unstable(feature = "cstr_bytes", issue = "112115")]
@@ -645,10 +621,7 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_str(), Ok("foo"));
+    /// assert_eq!(c"foo".to_str(), Ok("foo"));
     /// ```
     #[stable(feature = "cstr_to_str", since = "1.4.0")]
     #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 6eefb304689..8ea9de7e9e5 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -231,7 +231,7 @@ pub const unsafe fn assert_unchecked(cond: bool) {
 ///
 /// # Examples
 ///
-/// ```
+/// ```ignore-wasm
 /// use std::sync::atomic::{AtomicBool, Ordering};
 /// use std::sync::Arc;
 /// use std::{hint, thread};
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index b76213fdd41..c49513f7a6d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -158,7 +158,6 @@
 #![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
-#![feature(let_chains)]
 #![feature(link_llvm_intrinsics)]
 #![feature(macro_metavar_expr)]
 #![feature(marker_trait_attr)]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index aed5a043c11..1d264b26076 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -120,20 +120,22 @@
 //!
 //! Rust guarantees to optimize the following types `T` such that
 //! [`Option<T>`] has the same size, alignment, and [function call ABI] as `T`. In some
-//! of these cases, Rust further guarantees that
-//! `transmute::<_, Option<T>>([0u8; size_of::<T>()])` is sound and
-//! produces `Option::<T>::None`. These cases are identified by the
-//! second column:
-//!
-//! | `T`                                                                 | `transmute::<_, Option<T>>([0u8; size_of::<T>()])` sound? |
-//! |---------------------------------------------------------------------|----------------------------------------------------------------------|
-//! | [`Box<U>`] (specifically, only `Box<U, Global>`)                    | when `U: Sized`                                                      |
-//! | `&U`                                                                | when `U: Sized`                                                      |
-//! | `&mut U`                                                            | when `U: Sized`                                                      |
-//! | `fn`, `extern "C" fn`[^extern_fn]                                   | always                                                               |
-//! | [`num::NonZero*`]                                                   | always                                                               |
-//! | [`ptr::NonNull<U>`]                                                 | when `U: Sized`                                                      |
-//! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type                                     |
+//! of these cases, Rust further guarantees the following:
+//! - `transmute::<_, Option<T>>([0u8; size_of::<T>()])` is sound and produces
+//!   `Option::<T>::None`
+//! - `transmute::<_, [u8; size_of::<T>()]>(Option::<T>::None)` is sound and produces
+//!   `[0u8; size_of::<T>()]`
+//! These cases are identified by the second column:
+//!
+//! | `T`                                                                 | Transmuting between `[0u8; size_of::<T>()]` and `Option::<T>::None` sound? |
+//! |---------------------------------------------------------------------|----------------------------------------------------------------------------|
+//! | [`Box<U>`] (specifically, only `Box<U, Global>`)                    | when `U: Sized`                                                            |
+//! | `&U`                                                                | when `U: Sized`                                                            |
+//! | `&mut U`                                                            | when `U: Sized`                                                            |
+//! | `fn`, `extern "C" fn`[^extern_fn]                                   | always                                                                     |
+//! | [`num::NonZero*`]                                                   | always                                                                     |
+//! | [`ptr::NonNull<U>`]                                                 | when `U: Sized`                                                            |
+//! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type                                           |
 //!
 //! [^extern_fn]: this remains true for any argument/return types and any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`)
 //!
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 84c7f1aafe1..bd5a58d74ba 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -193,7 +193,7 @@
 //!
 //! A simple spinlock:
 //!
-//! ```
+//! ```ignore-wasm
 //! use std::sync::Arc;
 //! use std::sync::atomic::{AtomicUsize, Ordering};
 //! use std::{hint, thread};
@@ -622,7 +622,7 @@ impl AtomicBool {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```ignore-wasm
     /// #![feature(atomic_from_mut)]
     /// use std::sync::atomic::{AtomicBool, Ordering};
     ///
@@ -653,7 +653,7 @@ impl AtomicBool {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```rust,ignore-wasm
     /// #![feature(atomic_from_mut)]
     /// use std::sync::atomic::{AtomicBool, Ordering};
     ///
@@ -1548,7 +1548,7 @@ impl<T> AtomicPtr<T> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```ignore-wasm
     /// #![feature(atomic_from_mut)]
     /// use std::ptr::null_mut;
     /// use std::sync::atomic::{AtomicPtr, Ordering};
@@ -1585,7 +1585,7 @@ impl<T> AtomicPtr<T> {
     ///
     /// # Examples
     ///
-    /// ```
+    /// ```ignore-wasm
     /// #![feature(atomic_from_mut)]
     /// use std::ptr::null_mut;
     /// use std::sync::atomic::{AtomicPtr, Ordering};
@@ -2692,7 +2692,7 @@ macro_rules! atomic_int {
             ///
             /// # Examples
             ///
-            /// ```
+            /// ```ignore-wasm
             /// #![feature(atomic_from_mut)]
             #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
             ///
@@ -2725,7 +2725,7 @@ macro_rules! atomic_int {
             ///
             /// # Examples
             ///
-            /// ```
+            /// ```ignore-wasm
             /// #![feature(atomic_from_mut)]
             #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")]
             ///
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index f3b26ac64df..234fb284a59 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -356,7 +356,7 @@ pub use core::panic::abort_unwind;
 /// ```
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
-    unsafe { panicking::r#try(f) }
+    unsafe { panicking::catch_unwind(f) }
 }
 
 /// Triggers a panic without invoking the panic hook.
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 4bfedf78366..7873049d20b 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -499,13 +499,13 @@ pub use realstd::rt::panic_count;
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
 #[cfg(feature = "panic_immediate_abort")]
-pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
+pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
     Ok(f())
 }
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
 #[cfg(not(feature = "panic_immediate_abort"))]
-pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
+pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
     union Data<F, R> {
         f: ManuallyDrop<F>,
         r: ManuallyDrop<R>,
@@ -541,7 +541,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     let data_ptr = (&raw mut data) as *mut u8;
     // SAFETY:
     //
-    // Access to the union's fields: this is `std` and we know that the `r#try`
+    // Access to the union's fields: this is `std` and we know that the `catch_unwind`
     // intrinsic fills in the `r` or `p` union field based on its return value.
     //
     // The call to `intrinsics::catch_unwind` is made safe by:
@@ -602,7 +602,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     // This function cannot be marked as `unsafe` because `intrinsics::catch_unwind`
     // expects normal function pointers.
     #[inline]
-    #[rustc_nounwind] // `intrinsic::r#try` requires catch fn to be nounwind
+    #[rustc_nounwind] // `intrinsic::catch_unwind` requires catch fn to be nounwind
     fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) {
         // SAFETY: this is the responsibility of the caller, see above.
         //
diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs
index 3fcfb85cf2a..050f26b097a 100644
--- a/library/std/src/sync/mpmc/list.rs
+++ b/library/std/src/sync/mpmc/list.rs
@@ -575,7 +575,7 @@ impl<T> Channel<T> {
         // After this point `head.block` is not modified again and it will be deallocated if it's
         // non-null. The `Drop` code of the channel, which runs after this function, also attempts
         // to deallocate `head.block` if it's non-null. Therefore this function must maintain the
-        // invariant that if a deallocation of head.block is attemped then it must also be set to
+        // invariant that if a deallocation of head.block is attempted then it must also be set to
         // NULL. Failing to do so will lead to the Drop code attempting a double free. For this
         // reason both reads above do an atomic swap instead of a simple atomic load.
 
diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs
index da217439626..46d67c8e510 100644
--- a/library/std/src/sys/net/connection/uefi/mod.rs
+++ b/library/std/src/sys/net/connection/uefi/mod.rs
@@ -4,11 +4,14 @@ use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
 use crate::sys::unsupported;
 use crate::time::Duration;
 
-pub struct TcpStream(!);
+mod tcp;
+pub(crate) mod tcp4;
+
+pub struct TcpStream(#[expect(dead_code)] tcp::Tcp);
 
 impl TcpStream {
-    pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
-        unsupported()
+    pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
+        tcp::Tcp::connect(addr?).map(Self)
     }
 
     pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
@@ -16,105 +19,105 @@ impl TcpStream {
     }
 
     pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 
     pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0
+        unsupported()
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0
+        unsupported()
     }
 
     pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        self.0
+        unsupported()
     }
 
     pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
-        self.0
+        unsupported()
     }
 
     pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 
     pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        self.0
+        unsupported()
     }
 
     pub fn is_read_vectored(&self) -> bool {
-        self.0
+        false
     }
 
     pub fn write(&self, _: &[u8]) -> io::Result<usize> {
-        self.0
+        unsupported()
     }
 
     pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.0
+        unsupported()
     }
 
     pub fn is_write_vectored(&self) -> bool {
-        self.0
+        false
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        self.0
+        unsupported()
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        self.0
+        unsupported()
     }
 
     pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
-        self.0
+        unsupported()
     }
 
     pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 
     pub fn linger(&self) -> io::Result<Option<Duration>> {
-        self.0
+        unsupported()
     }
 
     pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
-        self.0
+        unsupported()
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        self.0
+        unsupported()
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        self.0
+        unsupported()
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        self.0
+        unsupported()
     }
 }
 
 impl fmt::Debug for TcpStream {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+        todo!()
     }
 }
 
diff --git a/library/std/src/sys/net/connection/uefi/tcp.rs b/library/std/src/sys/net/connection/uefi/tcp.rs
new file mode 100644
index 00000000000..f87accdc41d
--- /dev/null
+++ b/library/std/src/sys/net/connection/uefi/tcp.rs
@@ -0,0 +1,21 @@
+use super::tcp4;
+use crate::io;
+use crate::net::SocketAddr;
+
+pub(crate) enum Tcp {
+    V4(#[expect(dead_code)] tcp4::Tcp4),
+}
+
+impl Tcp {
+    pub(crate) fn connect(addr: &SocketAddr) -> io::Result<Self> {
+        match addr {
+            SocketAddr::V4(x) => {
+                let temp = tcp4::Tcp4::new()?;
+                temp.configure(true, Some(x), None)?;
+                temp.connect()?;
+                Ok(Tcp::V4(temp))
+            }
+            SocketAddr::V6(_) => todo!(),
+        }
+    }
+}
diff --git a/library/std/src/sys/net/connection/uefi/tcp4.rs b/library/std/src/sys/net/connection/uefi/tcp4.rs
new file mode 100644
index 00000000000..f7ca373b52b
--- /dev/null
+++ b/library/std/src/sys/net/connection/uefi/tcp4.rs
@@ -0,0 +1,118 @@
+use r_efi::efi::{self, Status};
+use r_efi::protocols::tcp4;
+
+use crate::io;
+use crate::net::SocketAddrV4;
+use crate::ptr::NonNull;
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sys::pal::helpers;
+
+const TYPE_OF_SERVICE: u8 = 8;
+const TIME_TO_LIVE: u8 = 255;
+
+pub(crate) struct Tcp4 {
+    protocol: NonNull<tcp4::Protocol>,
+    flag: AtomicBool,
+    #[expect(dead_code)]
+    service_binding: helpers::ServiceProtocol,
+}
+
+const DEFAULT_ADDR: efi::Ipv4Address = efi::Ipv4Address { addr: [0u8; 4] };
+
+impl Tcp4 {
+    pub(crate) fn new() -> io::Result<Self> {
+        let service_binding = helpers::ServiceProtocol::open(tcp4::SERVICE_BINDING_PROTOCOL_GUID)?;
+        let protocol = helpers::open_protocol(service_binding.child_handle(), tcp4::PROTOCOL_GUID)?;
+
+        Ok(Self { service_binding, protocol, flag: AtomicBool::new(false) })
+    }
+
+    pub(crate) fn configure(
+        &self,
+        active: bool,
+        remote_address: Option<&SocketAddrV4>,
+        station_address: Option<&SocketAddrV4>,
+    ) -> io::Result<()> {
+        let protocol = self.protocol.as_ptr();
+
+        let (remote_address, remote_port) = if let Some(x) = remote_address {
+            (helpers::ipv4_to_r_efi(*x.ip()), x.port())
+        } else {
+            (DEFAULT_ADDR, 0)
+        };
+
+        // FIXME: Remove when passive connections with proper subnet handling are added
+        assert!(station_address.is_none());
+        let use_default_address = efi::Boolean::TRUE;
+        let (station_address, station_port) = (DEFAULT_ADDR, 0);
+        let subnet_mask = helpers::ipv4_to_r_efi(crate::net::Ipv4Addr::new(0, 0, 0, 0));
+
+        let mut config_data = tcp4::ConfigData {
+            type_of_service: TYPE_OF_SERVICE,
+            time_to_live: TIME_TO_LIVE,
+            access_point: tcp4::AccessPoint {
+                use_default_address,
+                remote_address,
+                remote_port,
+                active_flag: active.into(),
+                station_address,
+                station_port,
+                subnet_mask,
+            },
+            control_option: crate::ptr::null_mut(),
+        };
+
+        let r = unsafe { ((*protocol).configure)(protocol, &mut config_data) };
+        if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
+    }
+
+    pub(crate) fn connect(&self) -> io::Result<()> {
+        let evt = unsafe { self.create_evt() }?;
+        let completion_token =
+            tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
+
+        let protocol = self.protocol.as_ptr();
+        let mut conn_token = tcp4::ConnectionToken { completion_token };
+
+        let r = unsafe { ((*protocol).connect)(protocol, &mut conn_token) };
+        if r.is_error() {
+            return Err(io::Error::from_raw_os_error(r.as_usize()));
+        }
+
+        self.wait_for_flag();
+
+        if completion_token.status.is_error() {
+            Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
+        } else {
+            Ok(())
+        }
+    }
+
+    unsafe fn create_evt(&self) -> io::Result<helpers::OwnedEvent> {
+        self.flag.store(false, Ordering::Relaxed);
+        helpers::OwnedEvent::new(
+            efi::EVT_NOTIFY_SIGNAL,
+            efi::TPL_CALLBACK,
+            Some(toggle_atomic_flag),
+            Some(unsafe { NonNull::new_unchecked(self.flag.as_ptr().cast()) }),
+        )
+    }
+
+    fn wait_for_flag(&self) {
+        while !self.flag.load(Ordering::Relaxed) {
+            let _ = self.poll();
+        }
+    }
+
+    fn poll(&self) -> io::Result<()> {
+        let protocol = self.protocol.as_ptr();
+        let r = unsafe { ((*protocol).poll)(protocol) };
+
+        if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
+    }
+}
+
+extern "efiapi" fn toggle_atomic_flag(_: r_efi::efi::Event, ctx: *mut crate::ffi::c_void) {
+    let flag = unsafe { AtomicBool::from_ptr(ctx.cast()) };
+    flag.store(true, Ordering::Relaxed);
+}
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 6ee3e0a8b66..e47263348db 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -653,7 +653,6 @@ pub(crate) struct ServiceProtocol {
 }
 
 impl ServiceProtocol {
-    #[expect(dead_code)]
     pub(crate) fn open(service_guid: r_efi::efi::Guid) -> io::Result<Self> {
         let handles = locate_handles(service_guid)?;
 
@@ -670,7 +669,6 @@ impl ServiceProtocol {
         Err(io::const_error!(io::ErrorKind::NotFound, "no service binding protocol found"))
     }
 
-    #[expect(dead_code)]
     pub(crate) fn child_handle(&self) -> NonNull<crate::ffi::c_void> {
         self.child_handle
     }
@@ -732,6 +730,10 @@ impl OwnedEvent {
         }
     }
 
+    pub(crate) fn as_ptr(&self) -> efi::Event {
+        self.0.as_ptr()
+    }
+
     pub(crate) fn into_raw(self) -> *mut crate::ffi::c_void {
         let r = self.0.as_ptr();
         crate::mem::forget(self);
@@ -755,3 +757,7 @@ impl Drop for OwnedEvent {
         }
     }
 }
+
+pub(crate) const fn ipv4_to_r_efi(addr: crate::net::Ipv4Addr) -> efi::Ipv4Address {
+    efi::Ipv4Address { addr: addr.octets() }
+}
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index 1ebbbec9e91..f331282d2d7 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -202,8 +202,6 @@ fn home_dir_crt() -> Option<PathBuf> {
             |buf, mut sz| {
                 // GetUserProfileDirectoryW does not quite use the usual protocol for
                 // negotiating the buffer size, so we have to translate.
-                // FIXME(#141254): We rely on the *undocumented* property that this function will
-                // always set the size, not just on failure.
                 match c::GetUserProfileDirectoryW(
                     ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN),
                     buf,
diff --git a/library/std/src/sys/process/unix/common.rs b/library/std/src/sys/process/unix/common.rs
index e205a839005..b6777b76668 100644
--- a/library/std/src/sys/process/unix/common.rs
+++ b/library/std/src/sys/process/unix/common.rs
@@ -1,8 +1,10 @@
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
-use libc::{EXIT_FAILURE, EXIT_SUCCESS, c_char, c_int, gid_t, pid_t, uid_t};
+use libc::{EXIT_FAILURE, EXIT_SUCCESS, c_int, gid_t, pid_t, uid_t};
 
+pub use self::cstring_array::CStringArray;
+use self::cstring_array::CStringIter;
 use crate::collections::BTreeMap;
 use crate::ffi::{CStr, CString, OsStr, OsString};
 use crate::os::unix::prelude::*;
@@ -14,7 +16,9 @@ use crate::sys::fs::OpenOptions;
 use crate::sys::pipe::{self, AnonPipe};
 use crate::sys::process::env::{CommandEnv, CommandEnvs};
 use crate::sys_common::{FromInner, IntoInner};
-use crate::{fmt, io, ptr};
+use crate::{fmt, io};
+
+mod cstring_array;
 
 cfg_if::cfg_if! {
     if #[cfg(target_os = "fuchsia")] {
@@ -77,13 +81,7 @@ cfg_if::cfg_if! {
 
 pub struct Command {
     program: CString,
-    args: Vec<CString>,
-    /// Exactly what will be passed to `execvp`.
-    ///
-    /// First element is a pointer to `program`, followed by pointers to
-    /// `args`, followed by a `null`. Be careful when modifying `program` or
-    /// `args` to properly update this as well.
-    argv: Argv,
+    args: CStringArray,
     env: CommandEnv,
 
     program_kind: ProgramKind,
@@ -102,14 +100,6 @@ pub struct Command {
     pgroup: Option<pid_t>,
 }
 
-// Create a new type for argv, so that we can make it `Send` and `Sync`
-struct Argv(Vec<*const c_char>);
-
-// It is safe to make `Argv` `Send` and `Sync`, because it contains
-// pointers to memory owned by `Command.args`
-unsafe impl Send for Argv {}
-unsafe impl Sync for Argv {}
-
 // passed back to std::process with the pipes connected to the child, if any
 // were requested
 pub struct StdioPipes {
@@ -171,42 +161,17 @@ impl ProgramKind {
 }
 
 impl Command {
-    #[cfg(not(target_os = "linux"))]
     pub fn new(program: &OsStr) -> Command {
         let mut saw_nul = false;
         let program_kind = ProgramKind::new(program.as_ref());
         let program = os2c(program, &mut saw_nul);
+        let mut args = CStringArray::with_capacity(1);
+        args.push(program.clone());
         Command {
-            argv: Argv(vec![program.as_ptr(), ptr::null()]),
-            args: vec![program.clone()],
             program,
-            program_kind,
+            args,
             env: Default::default(),
-            cwd: None,
-            chroot: None,
-            uid: None,
-            gid: None,
-            saw_nul,
-            closures: Vec::new(),
-            groups: None,
-            stdin: None,
-            stdout: None,
-            stderr: None,
-            pgroup: None,
-        }
-    }
-
-    #[cfg(target_os = "linux")]
-    pub fn new(program: &OsStr) -> Command {
-        let mut saw_nul = false;
-        let program_kind = ProgramKind::new(program.as_ref());
-        let program = os2c(program, &mut saw_nul);
-        Command {
-            argv: Argv(vec![program.as_ptr(), ptr::null()]),
-            args: vec![program.clone()],
-            program,
             program_kind,
-            env: Default::default(),
             cwd: None,
             chroot: None,
             uid: None,
@@ -217,6 +182,7 @@ impl Command {
             stdin: None,
             stdout: None,
             stderr: None,
+            #[cfg(target_os = "linux")]
             create_pidfd: false,
             pgroup: None,
         }
@@ -225,20 +191,11 @@ impl Command {
     pub fn set_arg_0(&mut self, arg: &OsStr) {
         // Set a new arg0
         let arg = os2c(arg, &mut self.saw_nul);
-        debug_assert!(self.argv.0.len() > 1);
-        self.argv.0[0] = arg.as_ptr();
-        self.args[0] = arg;
+        self.args.write(0, arg);
     }
 
     pub fn arg(&mut self, arg: &OsStr) {
-        // Overwrite the trailing null pointer in `argv` and then add a new null
-        // pointer.
         let arg = os2c(arg, &mut self.saw_nul);
-        self.argv.0[self.args.len()] = arg.as_ptr();
-        self.argv.0.push(ptr::null());
-
-        // Also make sure we keep track of the owned value to schedule a
-        // destructor for this memory.
         self.args.push(arg);
     }
 
@@ -295,6 +252,8 @@ impl Command {
 
     pub fn get_args(&self) -> CommandArgs<'_> {
         let mut iter = self.args.iter();
+        // argv[0] contains the program name, but we are only interested in the
+        // arguments so skip it.
         iter.next();
         CommandArgs { iter }
     }
@@ -307,12 +266,12 @@ impl Command {
         self.cwd.as_ref().map(|cs| Path::new(OsStr::from_bytes(cs.as_bytes())))
     }
 
-    pub fn get_argv(&self) -> &Vec<*const c_char> {
-        &self.argv.0
+    pub fn get_argv(&self) -> &CStringArray {
+        &self.args
     }
 
     pub fn get_program_cstr(&self) -> &CStr {
-        &*self.program
+        &self.program
     }
 
     #[allow(dead_code)]
@@ -405,32 +364,6 @@ fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString {
     })
 }
 
-// Helper type to manage ownership of the strings within a C-style array.
-pub struct CStringArray {
-    items: Vec<CString>,
-    ptrs: Vec<*const c_char>,
-}
-
-impl CStringArray {
-    pub fn with_capacity(capacity: usize) -> Self {
-        let mut result = CStringArray {
-            items: Vec::with_capacity(capacity),
-            ptrs: Vec::with_capacity(capacity + 1),
-        };
-        result.ptrs.push(ptr::null());
-        result
-    }
-    pub fn push(&mut self, item: CString) {
-        let l = self.ptrs.len();
-        self.ptrs[l - 1] = item.as_ptr();
-        self.ptrs.push(ptr::null());
-        self.items.push(item);
-    }
-    pub fn as_ptr(&self) -> *const *const c_char {
-        self.ptrs.as_ptr()
-    }
-}
-
 fn construct_envp(env: BTreeMap<OsString, OsString>, saw_nul: &mut bool) -> CStringArray {
     let mut result = CStringArray::with_capacity(env.len());
     for (mut k, v) in env {
@@ -619,14 +552,16 @@ impl fmt::Debug for Command {
                     write!(f, "{}={value:?} ", key.to_string_lossy())?;
                 }
             }
-            if self.program != self.args[0] {
+
+            if *self.program != self.args[0] {
                 write!(f, "[{:?}] ", self.program)?;
             }
-            write!(f, "{:?}", self.args[0])?;
+            write!(f, "{:?}", &self.args[0])?;
 
-            for arg in &self.args[1..] {
+            for arg in self.get_args() {
                 write!(f, " {:?}", arg)?;
             }
+
             Ok(())
         }
     }
@@ -658,14 +593,16 @@ impl From<u8> for ExitCode {
 }
 
 pub struct CommandArgs<'a> {
-    iter: crate::slice::Iter<'a, CString>,
+    iter: CStringIter<'a>,
 }
 
 impl<'a> Iterator for CommandArgs<'a> {
     type Item = &'a OsStr;
+
     fn next(&mut self) -> Option<&'a OsStr> {
-        self.iter.next().map(|cs| OsStr::from_bytes(cs.as_bytes()))
+        self.iter.next().map(|cs| OsStr::from_bytes(cs.to_bytes()))
     }
+
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
@@ -675,6 +612,7 @@ impl<'a> ExactSizeIterator for CommandArgs<'a> {
     fn len(&self) -> usize {
         self.iter.len()
     }
+
     fn is_empty(&self) -> bool {
         self.iter.is_empty()
     }
diff --git a/library/std/src/sys/process/unix/common/cstring_array.rs b/library/std/src/sys/process/unix/common/cstring_array.rs
new file mode 100644
index 00000000000..1c840a85df9
--- /dev/null
+++ b/library/std/src/sys/process/unix/common/cstring_array.rs
@@ -0,0 +1,115 @@
+use crate::ffi::{CStr, CString, c_char};
+use crate::ops::Index;
+use crate::{fmt, mem, ptr};
+
+/// Helper type to manage ownership of the strings within a C-style array.
+///
+/// This type manages an array of C-string pointers terminated by a null
+/// pointer. The pointer to the array (as returned by `as_ptr`) can be used as
+/// a value of `argv` or `environ`.
+pub struct CStringArray {
+    ptrs: Vec<*const c_char>,
+}
+
+impl CStringArray {
+    /// Creates a new `CStringArray` with enough capacity to hold `capacity`
+    /// strings.
+    pub fn with_capacity(capacity: usize) -> Self {
+        let mut result = CStringArray { ptrs: Vec::with_capacity(capacity + 1) };
+        result.ptrs.push(ptr::null());
+        result
+    }
+
+    /// Replace the string at position `index`.
+    pub fn write(&mut self, index: usize, item: CString) {
+        let argc = self.ptrs.len() - 1;
+        let ptr = &mut self.ptrs[..argc][index];
+        let old = mem::replace(ptr, item.into_raw());
+        // SAFETY:
+        // `CStringArray` owns all of its strings, and they were all transformed
+        // into pointers using `CString::into_raw`. Also, this is not the null
+        // pointer since the indexing above would have failed.
+        drop(unsafe { CString::from_raw(old.cast_mut()) });
+    }
+
+    /// Push an additional string to the array.
+    pub fn push(&mut self, item: CString) {
+        let argc = self.ptrs.len() - 1;
+        // Replace the null pointer at the end of the array...
+        self.ptrs[argc] = item.into_raw();
+        // ... and recreate it to restore the data structure invariant.
+        self.ptrs.push(ptr::null());
+    }
+
+    /// Returns a pointer to the C-string array managed by this type.
+    pub fn as_ptr(&self) -> *const *const c_char {
+        self.ptrs.as_ptr()
+    }
+
+    /// Returns an iterator over all `CStr`s contained in this array.
+    pub fn iter(&self) -> CStringIter<'_> {
+        CStringIter { iter: self.ptrs[..self.ptrs.len() - 1].iter() }
+    }
+}
+
+impl Index<usize> for CStringArray {
+    type Output = CStr;
+    fn index(&self, index: usize) -> &CStr {
+        let ptr = self.ptrs[..self.ptrs.len() - 1][index];
+        // SAFETY:
+        // `CStringArray` owns all of its strings. Also, this is not the null
+        // pointer since the indexing above would have failed.
+        unsafe { CStr::from_ptr(ptr) }
+    }
+}
+
+impl fmt::Debug for CStringArray {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
+    }
+}
+
+// SAFETY: `CStringArray` is basically just a `Vec<CString>`
+unsafe impl Send for CStringArray {}
+// SAFETY: `CStringArray` is basically just a `Vec<CString>`
+unsafe impl Sync for CStringArray {}
+
+impl Drop for CStringArray {
+    fn drop(&mut self) {
+        // SAFETY:
+        // `CStringArray` owns all of its strings, and they were all transformed
+        // into pointers using `CString::into_raw`.
+        self.ptrs[..self.ptrs.len() - 1]
+            .iter()
+            .for_each(|&p| drop(unsafe { CString::from_raw(p.cast_mut()) }))
+    }
+}
+
+/// An iterator over all `CStr`s contained in a `CStringArray`.
+#[derive(Clone)]
+pub struct CStringIter<'a> {
+    iter: crate::slice::Iter<'a, *const c_char>,
+}
+
+impl<'a> Iterator for CStringIter<'a> {
+    type Item = &'a CStr;
+    fn next(&mut self) -> Option<&'a CStr> {
+        // SAFETY:
+        // `CStringArray` owns all of its strings. Also, this is not the null
+        // pointer since the last element is excluded when creating `iter`.
+        self.iter.next().map(|&p| unsafe { CStr::from_ptr(p) })
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'a> ExactSizeIterator for CStringIter<'a> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
diff --git a/library/std/src/sys/thread_local/guard/key.rs b/library/std/src/sys/thread_local/guard/key.rs
index 59581e6f281..f91471419c1 100644
--- a/library/std/src/sys/thread_local/guard/key.rs
+++ b/library/std/src/sys/thread_local/guard/key.rs
@@ -32,7 +32,7 @@ pub fn enable() {
 
 /// On platforms with key-based TLS, the system runs the destructors for us.
 /// We still have to make sure that [`crate::rt::thread_cleanup`] is called,
-/// however. This is done by defering the execution of a TLS destructor to
+/// however. This is done by deferring the execution of a TLS destructor to
 /// the next round of destruction inside the TLS destructors.
 #[cfg(not(target_thread_local))]
 pub fn enable() {
@@ -46,7 +46,7 @@ pub fn enable() {
     unsafe extern "C" fn run(state: *mut u8) {
         if state == DEFER {
             // Make sure that this function is run again in the next round of
-            // TLS destruction. If there is no futher round, there will be leaks,
+            // TLS destruction. If there is no further round, there will be leaks,
             // but that's okay, `thread_cleanup` is not guaranteed to be called.
             unsafe { set(CLEANUP.force(), RUN) }
         } else {
diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs
index 978402b6fda..87e0d226cbd 100644
--- a/library/std/tests/path.rs
+++ b/library/std/tests/path.rs
@@ -1976,3 +1976,34 @@ fn clone_to_uninit() {
     unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b).cast()) };
     assert_eq!(a, &*b);
 }
+
+// Test: Only separators (e.g., "/" or "\\")
+// This test checks how Path handles a string that consists only of path separators.
+// It should recognize the root and not treat it as a normal component.
+#[test]
+fn test_only_separators() {
+    let path = Path::new("/////");
+    assert!(path.has_root());
+    assert_eq!(path.iter().count(), 1);
+    assert_eq!(path.parent(), None);
+}
+
+// Test: Non-ASCII/Unicode
+// This test verifies that Path can handle Unicode and non-ASCII characters in the path.
+// It ensures that such paths are not rejected or misinterpreted.
+#[test]
+fn test_non_ascii_unicode() {
+    let path = Path::new("/tmp/❤/🚀/file.txt");
+    assert!(path.to_str().is_some());
+    assert_eq!(path.file_name(), Some(OsStr::new("file.txt")));
+}
+
+// Test: Embedded newlines
+// This test verifies that newlines within path components are preserved and do not break path parsing.
+// It ensures that Path treats newlines as normal characters.
+#[test]
+fn test_embedded_newline() {
+    let path = Path::new("foo\nbar");
+    assert_eq!(path.file_name(), Some(OsStr::new("foo\nbar")));
+    assert_eq!(path.to_str(), Some("foo\nbar"));
+}
diff --git a/src/bootstrap/src/utils/shared_helpers.rs b/src/bootstrap/src/utils/shared_helpers.rs
index 08e1c21e58e..561af34a447 100644
--- a/src/bootstrap/src/utils/shared_helpers.rs
+++ b/src/bootstrap/src/utils/shared_helpers.rs
@@ -46,7 +46,16 @@ pub fn dylib_path() -> Vec<std::path::PathBuf> {
 /// Given an executable called `name`, return the filename for the
 /// executable for a particular target.
 pub fn exe(name: &str, target: &str) -> String {
-    if target.contains("windows") {
+    // On Cygwin, the decision to append .exe or not is not as straightforward.
+    // Executable files do actually have .exe extensions so on hosts other than
+    // Cygwin it is necessary.  But on a Cygwin host there is magic happening
+    // that redirects requests for file X to file X.exe if it exists, and
+    // furthermore /proc/self/exe (and thus std::env::current_exe) always
+    // returns the name *without* the .exe extension.  For comparisons against
+    // that to match, we therefore do not append .exe for Cygwin targets on
+    // a Cygwin host.
+    if target.contains("windows") || (cfg!(not(target_os = "cygwin")) && target.contains("cygwin"))
+    {
         format!("{name}.exe")
     } else if target.contains("uefi") {
         format!("{name}.efi")
diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock
index 43321d12caf..571f18e7cf1 100644
--- a/src/ci/citool/Cargo.lock
+++ b/src/ci/citool/Cargo.lock
@@ -66,9 +66,9 @@ checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
 
 [[package]]
 name = "askama"
-version = "0.13.1"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7"
+checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
 dependencies = [
  "askama_derive",
  "itoa",
@@ -79,9 +79,9 @@ dependencies = [
 
 [[package]]
 name = "askama_derive"
-version = "0.13.1"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac"
+checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
 dependencies = [
  "askama_parser",
  "basic-toml",
@@ -96,9 +96,9 @@ dependencies = [
 
 [[package]]
 name = "askama_parser"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f"
+checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
 dependencies = [
  "memchr",
  "serde",
diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml
index 0e2aba3b9e3..f61243a4d71 100644
--- a/src/ci/citool/Cargo.toml
+++ b/src/ci/citool/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 anyhow = "1"
-askama = "0.13"
+askama = "0.14"
 clap = { version = "4.5", features = ["derive"] }
 csv = "1"
 diff = "0.1"
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index 1d280948ebe..fa18f67583f 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -2,7 +2,8 @@
 
 set -euo pipefail
 
-LINUX_VERSION=v6.15-rc4
+# https://github.com/Rust-for-Linux/linux/issues/1163
+LINUX_VERSION=3ca02fc80cc4fdac63aaa6796642f1e07be591d6
 
 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt
 ../x.py build --stage 2 library rustdoc clippy rustfmt
diff --git a/src/doc/rustc/src/platform-support/solaris.md b/src/doc/rustc/src/platform-support/solaris.md
index 0452d76f6c2..c22b5c24c12 100644
--- a/src/doc/rustc/src/platform-support/solaris.md
+++ b/src/doc/rustc/src/platform-support/solaris.md
@@ -8,6 +8,7 @@ Rust for Solaris operating system.
 ## Target maintainers
 
 [@psumbera](https://github.com/psumbera)
+[@kulikjak](https://github.com/kulikjak)
 
 ## Requirements
 
diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
index 45146993371..6ec93d1746c 100644
--- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
+++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
@@ -88,8 +88,10 @@ on your documentation examples make requests to.
 ```
 
 Now, when you press "run", the button will make a request to this domain. The request
-URL will contain 2 query parameters: `code` and `edition` for the code in the documentation
-and the Rust edition respectively.
+URL will contain 3 query parameters:
+1. `code` for the code in the documentation
+2. `version` for the Rust channel, e.g. nightly, which is decided by whether `code` contain unstable features
+3. `edition` for the Rust edition, e.g. 2024
 
 If you don't use this attribute, there will be no run buttons.
 
diff --git a/src/doc/unstable-book/src/compiler-flags/eagerly-emit-delayed-bugs.md b/src/doc/unstable-book/src/compiler-flags/eagerly-emit-delayed-bugs.md
new file mode 100644
index 00000000000..39f0c04a1b5
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/eagerly-emit-delayed-bugs.md
@@ -0,0 +1,12 @@
+# `eagerly-emit-delayed-bugs`
+
+This feature is perma-unstable and has no tracking issue.
+
+------------------------
+
+This flag converts all [`span_delayed_bug()`] calls to [`bug!`] calls, exiting the compiler immediately and allowing you to generate a backtrace of where the delayed bug occurred.
+For full documentation, see [the rustc-dev-guide][dev-guide-delayed].
+
+[`bug!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/macro.bug.html
+[`span_delayed_bug()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxtHandle.html#method.span_delayed_bug
+[dev-guide-delayed]: https://rustc-dev-guide.rust-lang.org/compiler-debugging.html#debugging-delayed-bugs
diff --git a/src/doc/unstable-book/src/compiler-flags/track-diagnostics.md b/src/doc/unstable-book/src/compiler-flags/track-diagnostics.md
new file mode 100644
index 00000000000..48620214407
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/track-diagnostics.md
@@ -0,0 +1,11 @@
+# `track-diagnostics`
+
+This feature is perma-unstable and has no tracking issue.
+
+------------------------
+
+This flag prints the source code span in the compiler where a diagnostic was generated, respecting [`#[track_caller]`][track_caller]. Note that this may be different from the place it was emitted.
+For full documentation, see [the rustc-dev-guide][dev-guide-track-diagnostics].
+
+[track_caller]: https://doc.rust-lang.org/reference/attributes/codegen.html#the-track_caller-attribute
+[dev-guide-track-diagnostics]: https://rustc-dev-guide.rust-lang.org/compiler-debugging.html#getting-the-error-creation-location
diff --git a/src/doc/unstable-book/src/compiler-flags/treat-err-as-bug.md b/src/doc/unstable-book/src/compiler-flags/treat-err-as-bug.md
new file mode 100644
index 00000000000..df7c380a50b
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/treat-err-as-bug.md
@@ -0,0 +1,13 @@
+# `treat-err-as-bug`
+
+This feature is perma-unstable and has no tracking issue.
+
+------------------------
+
+This flag converts the selected error to a [`bug!`] call, exiting the compiler immediately and allowing you to generate a backtrace of where the error occurred.
+For full documentation, see [the rustc-dev-guide][dev-guide-backtrace].
+
+Note that the compiler automatically sets `RUST_BACKTRACE=1` for itself, and so you do not need to set it yourself when using this flag.
+
+[`bug!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/macro.bug.html
+[dev-guide-backtrace]: https://rustc-dev-guide.rust-lang.org/compiler-debugging.html#getting-a-backtrace-for-errors
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index dbfdd8ebd16..bba8e630bcc 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -9,7 +9,7 @@ path = "lib.rs"
 
 [dependencies]
 arrayvec = { version = "0.7", default-features = false }
-askama = { version = "0.13", default-features = false, features = ["alloc", "config", "derive"] }
+askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] }
 base64 = "0.21.7"
 itertools = "0.12"
 indexmap = "2"
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index af7986d030e..2e38b6cdc65 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -1,7 +1,7 @@
 use std::assert_matches::debug_assert_matches;
 use std::fmt::{self, Display, Write as _};
-use std::mem;
 use std::sync::LazyLock as Lazy;
+use std::{ascii, mem};
 
 use rustc_ast::tokenstream::TokenTree;
 use rustc_hir::def::{DefKind, Res};
@@ -24,7 +24,7 @@ use crate::clean::{
     clean_middle_ty, inline,
 };
 use crate::core::DocContext;
-use crate::display::Joined as _;
+use crate::display::{Joined as _, MaybeDisplay as _};
 
 #[cfg(test)]
 mod tests;
@@ -254,14 +254,7 @@ pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String {
     fmt::from_fn(|f| {
         segments
             .iter()
-            .map(|seg| {
-                fmt::from_fn(|f| {
-                    if seg.ident.name != kw::PathRoot {
-                        write!(f, "{}", seg.ident)?;
-                    }
-                    Ok(())
-                })
-            })
+            .map(|seg| (seg.ident.name != kw::PathRoot).then_some(seg.ident).maybe_display())
             .joined("::", f)
     })
     .to_string()
@@ -391,30 +384,12 @@ pub(crate) fn print_evaluated_const(
     })
 }
 
-fn format_integer_with_underscore_sep(num: &str) -> String {
-    let num_chars: Vec<_> = num.chars().collect();
-    let mut num_start_index = if num_chars.first() == Some(&'-') { 1 } else { 0 };
-    let chunk_size = match &num.as_bytes()[num_start_index..] {
-        [b'0', b'b' | b'x', ..] => {
-            num_start_index += 2;
-            4
-        }
-        [b'0', b'o', ..] => {
-            num_start_index += 2;
-            let remaining_chars = num_chars.len() - num_start_index;
-            if remaining_chars <= 6 {
-                // don't add underscores to Unix permissions like 0755 or 100755
-                return num.to_string();
-            }
-            3
-        }
-        _ => 3,
-    };
-
-    num_chars[..num_start_index]
-        .iter()
-        .chain(num_chars[num_start_index..].rchunks(chunk_size).rev().intersperse(&['_']).flatten())
-        .collect()
+fn format_integer_with_underscore_sep(num: u128, is_negative: bool) -> String {
+    let num = num.to_string();
+    let chars = num.as_ascii().unwrap();
+    let mut result = if is_negative { "-".to_string() } else { String::new() };
+    result.extend(chars.rchunks(3).rev().intersperse(&[ascii::Char::LowLine]).flatten());
+    result
 }
 
 fn print_const_with_custom_print_scalar<'tcx>(
@@ -428,7 +403,10 @@ fn print_const_with_custom_print_scalar<'tcx>(
     match (ct, ct.ty().kind()) {
         (mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => {
             let mut output = if with_underscores {
-                format_integer_with_underscore_sep(&int.to_string())
+                format_integer_with_underscore_sep(
+                    int.assert_scalar_int().to_bits_unchecked(),
+                    false,
+                )
             } else {
                 int.to_string()
             };
@@ -445,7 +423,10 @@ fn print_const_with_custom_print_scalar<'tcx>(
                 .size;
             let sign_extended_data = int.assert_scalar_int().to_int(size);
             let mut output = if with_underscores {
-                format_integer_with_underscore_sep(&sign_extended_data.to_string())
+                format_integer_with_underscore_sep(
+                    sign_extended_data.unsigned_abs(),
+                    sign_extended_data.is_negative(),
+                )
             } else {
                 sign_extended_data.to_string()
             };
diff --git a/src/librustdoc/clean/utils/tests.rs b/src/librustdoc/clean/utils/tests.rs
index ebf4b495483..65c8255b2f2 100644
--- a/src/librustdoc/clean/utils/tests.rs
+++ b/src/librustdoc/clean/utils/tests.rs
@@ -2,40 +2,10 @@ use super::*;
 
 #[test]
 fn int_format_decimal() {
-    assert_eq!(format_integer_with_underscore_sep("12345678"), "12_345_678");
-    assert_eq!(format_integer_with_underscore_sep("123"), "123");
-    assert_eq!(format_integer_with_underscore_sep("123459"), "123_459");
-    assert_eq!(format_integer_with_underscore_sep("-12345678"), "-12_345_678");
-    assert_eq!(format_integer_with_underscore_sep("-123"), "-123");
-    assert_eq!(format_integer_with_underscore_sep("-123459"), "-123_459");
-}
-
-#[test]
-fn int_format_hex() {
-    assert_eq!(format_integer_with_underscore_sep("0xab3"), "0xab3");
-    assert_eq!(format_integer_with_underscore_sep("0xa2345b"), "0xa2_345b");
-    assert_eq!(format_integer_with_underscore_sep("0xa2e6345b"), "0xa2e6_345b");
-    assert_eq!(format_integer_with_underscore_sep("-0xab3"), "-0xab3");
-    assert_eq!(format_integer_with_underscore_sep("-0xa2345b"), "-0xa2_345b");
-    assert_eq!(format_integer_with_underscore_sep("-0xa2e6345b"), "-0xa2e6_345b");
-}
-
-#[test]
-fn int_format_binary() {
-    assert_eq!(format_integer_with_underscore_sep("0o12345671"), "0o12_345_671");
-    assert_eq!(format_integer_with_underscore_sep("0o123"), "0o123");
-    assert_eq!(format_integer_with_underscore_sep("0o123451"), "0o123451");
-    assert_eq!(format_integer_with_underscore_sep("-0o12345671"), "-0o12_345_671");
-    assert_eq!(format_integer_with_underscore_sep("-0o123"), "-0o123");
-    assert_eq!(format_integer_with_underscore_sep("-0o123451"), "-0o123451");
-}
-
-#[test]
-fn int_format_octal() {
-    assert_eq!(format_integer_with_underscore_sep("0b101"), "0b101");
-    assert_eq!(format_integer_with_underscore_sep("0b101101011"), "0b1_0110_1011");
-    assert_eq!(format_integer_with_underscore_sep("0b01101011"), "0b0110_1011");
-    assert_eq!(format_integer_with_underscore_sep("-0b101"), "-0b101");
-    assert_eq!(format_integer_with_underscore_sep("-0b101101011"), "-0b1_0110_1011");
-    assert_eq!(format_integer_with_underscore_sep("-0b01101011"), "-0b0110_1011");
+    assert_eq!(format_integer_with_underscore_sep(12345678, false), "12_345_678");
+    assert_eq!(format_integer_with_underscore_sep(123, false), "123");
+    assert_eq!(format_integer_with_underscore_sep(123459, false), "123_459");
+    assert_eq!(format_integer_with_underscore_sep(12345678, true), "-12_345_678");
+    assert_eq!(format_integer_with_underscore_sep(123, true), "-123");
+    assert_eq!(format_integer_with_underscore_sep(123459, true), "-123_459");
 }
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index a9029972d96..361966325fb 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -127,7 +127,7 @@ pub(crate) mod filters {
     use askama::filters::Safe;
 
     use crate::html::escape::EscapeBodyTextWithWbr;
-    pub(crate) fn wrapped<T>(v: T) -> askama::Result<Safe<impl Display>>
+    pub(crate) fn wrapped<T, V: askama::Values>(v: T, _: V) -> askama::Result<Safe<impl Display>>
     where
         T: Display,
     {
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index b2bbf4614bf..4f6e9abdbca 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -611,7 +611,7 @@ impl TypeAliasPart {
                 .impl_
                 .values()
                 .flat_map(|AliasedTypeImpl { impl_, type_aliases }| {
-                    let mut ret = Vec::new();
+                    let mut ret: Vec<AliasSerializableImpl> = Vec::new();
                     let trait_ = impl_
                         .inner_impl()
                         .trait_
@@ -623,42 +623,43 @@ impl TypeAliasPart {
                     for &(type_alias_fqp, type_alias_item) in type_aliases {
                         cx.id_map.borrow_mut().clear();
                         cx.deref_id_map.borrow_mut().clear();
-                        let target_did = impl_
-                            .inner_impl()
-                            .trait_
-                            .as_ref()
-                            .map(|trait_| trait_.def_id())
-                            .or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache));
-                        let provided_methods;
-                        let assoc_link = if let Some(target_did) = target_did {
-                            provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx());
-                            AssocItemLink::GotoSource(ItemId::DefId(target_did), &provided_methods)
-                        } else {
-                            AssocItemLink::Anchor(None)
-                        };
-                        let text = super::render_impl(
-                            cx,
-                            impl_,
-                            type_alias_item,
-                            assoc_link,
-                            RenderMode::Normal,
-                            None,
-                            &[],
-                            ImplRenderingParameters {
-                                show_def_docs: true,
-                                show_default_items: true,
-                                show_non_assoc_items: true,
-                                toggle_open_by_default: true,
-                            },
-                        )
-                        .to_string();
                         let type_alias_fqp = (*type_alias_fqp).iter().join("::");
-                        if Some(&text) == ret.last().map(|s: &AliasSerializableImpl| &s.text) {
-                            ret.last_mut()
-                                .expect("already established that ret.last() is Some()")
-                                .aliases
-                                .push(type_alias_fqp);
+                        if let Some(last) = ret.last_mut() {
+                            last.aliases.push(type_alias_fqp);
                         } else {
+                            let target_did = impl_
+                                .inner_impl()
+                                .trait_
+                                .as_ref()
+                                .map(|trait_| trait_.def_id())
+                                .or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache));
+                            let provided_methods;
+                            let assoc_link = if let Some(target_did) = target_did {
+                                provided_methods =
+                                    impl_.inner_impl().provided_trait_methods(cx.tcx());
+                                AssocItemLink::GotoSource(
+                                    ItemId::DefId(target_did),
+                                    &provided_methods,
+                                )
+                            } else {
+                                AssocItemLink::Anchor(None)
+                            };
+                            let text = super::render_impl(
+                                cx,
+                                impl_,
+                                type_alias_item,
+                                assoc_link,
+                                RenderMode::Normal,
+                                None,
+                                &[],
+                                ImplRenderingParameters {
+                                    show_def_docs: true,
+                                    show_default_items: true,
+                                    show_non_assoc_items: true,
+                                    toggle_open_by_default: true,
+                                },
+                            )
+                            .to_string();
                             ret.push(AliasSerializableImpl {
                                 text,
                                 trait_: trait_.clone(),
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 001668c54a7..025c135aff2 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -3,6 +3,8 @@
     html_playground_url = "https://play.rust-lang.org/"
 )]
 #![feature(rustc_private)]
+#![feature(ascii_char)]
+#![feature(ascii_char_variants)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(debug_closure_helpers)]
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 47c911e9e6f6461f90ce19142031fe16876a3b9
+Subproject 68db37499f2de8acef704c73d9031be6fbcbaee
diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml
index ab76d0fc01e..e420a450d42 100644
--- a/src/tools/generate-copyright/Cargo.toml
+++ b/src/tools/generate-copyright/Cargo.toml
@@ -8,7 +8,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust
 
 [dependencies]
 anyhow = "1.0.65"
-askama = "0.13.0"
+askama = "0.14.0"
 cargo_metadata = "0.18.1"
 serde = { version = "1.0.147", features = ["derive"] }
 serde_json = "1.0.85"
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index b5ed5ea837b..549d859a6e1 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -56,7 +56,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         interp_ok(())
     }
 
-    /// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`.
+    /// Handles the `catch_unwind` intrinsic.
     fn handle_catch_unwind(
         &mut self,
         args: &[OpTy<'tcx>],
@@ -66,7 +66,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let this = self.eval_context_mut();
 
         // Signature:
-        //   fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32
+        //   fn catch_unwind(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32
         // Calls `try_fn` with `data` as argument. If that executes normally, returns 0.
         // If that unwinds, calls `catch_fn` with the first argument being `data` and
         // then second argument being a target-dependent `payload` (i.e. it is up to us to define
@@ -120,14 +120,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         // We only care about `catch_panic` if we're unwinding - if we're doing a normal
         // return, then we don't need to do anything special.
         if let (true, Some(catch_unwind)) = (unwinding, extra.catch_unwind.take()) {
-            // We've just popped a frame that was pushed by `try`,
+            // We've just popped a frame that was pushed by `catch_unwind`,
             // and we are unwinding, so we should catch that.
             trace!(
                 "unwinding: found catch_panic frame during unwinding: {:?}",
                 this.frame().instance()
             );
 
-            // We set the return value of `try` to 1, since there was a panic.
+            // We set the return value of `catch_unwind` to 1, since there was a panic.
             this.write_scalar(Scalar::from_i32(1), &catch_unwind.dest)?;
 
             // The Thread's `panic_payload` holds what was passed to `miri_start_unwind`.
@@ -142,7 +142,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 ExternAbi::Rust,
                 &[catch_unwind.data, payload],
                 None,
-                // Directly return to caller of `try`.
+                // Directly return to caller of `catch_unwind`.
                 StackPopCleanup::Goto {
                     ret: catch_unwind.ret,
                     // `catch_fn` must not unwind.
diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs
index 0cbabc52d2a..a7c26d601e5 100644
--- a/src/tools/miri/src/shims/windows/env.rs
+++ b/src/tools/miri/src/shims/windows/env.rs
@@ -230,7 +230,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         interp_ok(match directories::UserDirs::new() {
             Some(dirs) => {
                 let home = dirs.home_dir();
-                let size_avail = if this.ptr_is_null(size.ptr())? {
+                let size_avail = if this.ptr_is_null(buf)? {
                     0 // if the buf pointer is null, we can't write to it; `size` will be updated to the required length
                 } else {
                     this.read_scalar(&size)?.to_u32()?
@@ -238,8 +238,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // Of course we cannot use `windows_check_buffer_size` here since this uses
                 // a different method for dealing with a too-small buffer than the other functions...
                 let (success, len) = this.write_path_to_wide_str(home, buf, size_avail.into())?;
-                // The Windows docs just say that this is written on failure, but std relies on it
-                // always being written. Also see <https://github.com/rust-lang/rust/issues/141254>.
+                // As per <https://github.com/MicrosoftDocs/sdk-api/pull/1810>, the size is always
+                // written, not just on failure.
                 this.write_scalar(Scalar::from_u32(len.try_into().unwrap()), &size)?;
                 if success {
                     Scalar::from_i32(1) // return TRUE
diff --git a/src/tools/miri/tests/fail/panic/bad_unwind.stderr b/src/tools/miri/tests/fail/panic/bad_unwind.stderr
index 6ba39e8f7e2..8c269eae62a 100644
--- a/src/tools/miri/tests/fail/panic/bad_unwind.stderr
+++ b/src/tools/miri/tests/fail/panic/bad_unwind.stderr
@@ -13,8 +13,8 @@ LL |     std::panic::catch_unwind(|| unwind()).unwrap_err();
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside closure at tests/fail/panic/bad_unwind.rs:LL:CC
-   = note: inside `std::panicking::r#try::do_call::<{closure@tests/fail/panic/bad_unwind.rs:LL:CC}, ()>` at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::panicking::r#try::<(), {closure@tests/fail/panic/bad_unwind.rs:LL:CC}>` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::panicking::catch_unwind::do_call::<{closure@tests/fail/panic/bad_unwind.rs:LL:CC}, ()>` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::panicking::catch_unwind::<(), {closure@tests/fail/panic/bad_unwind.rs:LL:CC}>` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panic::catch_unwind::<{closure@tests/fail/panic/bad_unwind.rs:LL:CC}, ()>` at RUSTLIB/std/src/panic.rs:LL:CC
 note: inside `main`
   --> tests/fail/panic/bad_unwind.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr b/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
index 61ddea64472..589e30d632e 100644
--- a/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
+++ b/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
@@ -11,12 +11,12 @@ LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
    = note: inside `std::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/rt.rs:LL:CC
    = note: inside `std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once` at RUSTLIB/core/src/ops/function.rs:LL:CC
-   = note: inside `std::panicking::r#try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::panicking::catch_unwind::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::panicking::catch_unwind::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at RUSTLIB/std/src/panic.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/rt.rs:LL:CC
-   = note: inside `std::panicking::r#try::do_call::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `std::panicking::r#try::<isize, {closure@std::rt::lang_start_internal::{closure#0}}>` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::panicking::catch_unwind::do_call::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::panicking::catch_unwind::<isize, {closure@std::rt::lang_start_internal::{closure#0}}>` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panic.rs:LL:CC
    = note: inside `std::rt::lang_start_internal` at RUSTLIB/std/src/rt.rs:LL:CC
    = note: inside `std::rt::lang_start::<()>` at RUSTLIB/std/src/rt.rs:LL:CC
diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr
index 1ee5298f17d..8e167dbadef 100644
--- a/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr
+++ b/src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr
@@ -7,12 +7,12 @@ RUSTLIB/core/src/ops/function.rs:LL:CC (<fn() as std::ops::FnOnce<()>>::call_onc
 RUSTLIB/std/src/sys/backtrace.rs:LL:CC (std::sys::backtrace::__rust_begin_short_backtrace)
 RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start::{closure#0})
 RUSTLIB/core/src/ops/function.rs:LL:CC (std::ops::function::impls::call_once)
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
+RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::catch_unwind::do_call)
+RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::catch_unwind)
 RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)
 RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#0})
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
-RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
+RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::catch_unwind::do_call)
+RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::catch_unwind)
 RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)
 RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal)
 RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start)
diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-global-alloc.stderr b/src/tools/miri/tests/pass/backtrace/backtrace-global-alloc.stderr
index 26cdee18e3c..588bb85f35a 100644
--- a/src/tools/miri/tests/pass/backtrace/backtrace-global-alloc.stderr
+++ b/src/tools/miri/tests/pass/backtrace/backtrace-global-alloc.stderr
@@ -8,17 +8,17 @@
  at RUSTLIB/std/src/rt.rs:LL:CC
    4: std::ops::function::impls::call_once
  at RUSTLIB/core/src/ops/function.rs:LL:CC
-   5: std::panicking::r#try::do_call
+   5: std::panicking::catch_unwind::do_call
  at RUSTLIB/std/src/panicking.rs:LL:CC
-   6: std::panicking::r#try
+   6: std::panicking::catch_unwind
  at RUSTLIB/std/src/panicking.rs:LL:CC
    7: std::panic::catch_unwind
  at RUSTLIB/std/src/panic.rs:LL:CC
    8: std::rt::lang_start_internal::{closure#0}
  at RUSTLIB/std/src/rt.rs:LL:CC
-   9: std::panicking::r#try::do_call
+   9: std::panicking::catch_unwind::do_call
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  10: std::panicking::r#try
+  10: std::panicking::catch_unwind
  at RUSTLIB/std/src/panicking.rs:LL:CC
   11: std::panic::catch_unwind
  at RUSTLIB/std/src/panic.rs:LL:CC
diff --git a/src/tools/miri/tests/pass/backtrace/backtrace-std.stderr b/src/tools/miri/tests/pass/backtrace/backtrace-std.stderr
index d89ae3837b9..9c952755957 100644
--- a/src/tools/miri/tests/pass/backtrace/backtrace-std.stderr
+++ b/src/tools/miri/tests/pass/backtrace/backtrace-std.stderr
@@ -16,17 +16,17 @@
  at RUSTLIB/std/src/rt.rs:LL:CC
    8: std::ops::function::impls::call_once
  at RUSTLIB/core/src/ops/function.rs:LL:CC
-   9: std::panicking::r#try::do_call
+   9: std::panicking::catch_unwind::do_call
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  10: std::panicking::r#try
+  10: std::panicking::catch_unwind
  at RUSTLIB/std/src/panicking.rs:LL:CC
   11: std::panic::catch_unwind
  at RUSTLIB/std/src/panic.rs:LL:CC
   12: std::rt::lang_start_internal::{closure#0}
  at RUSTLIB/std/src/rt.rs:LL:CC
-  13: std::panicking::r#try::do_call
+  13: std::panicking::catch_unwind::do_call
  at RUSTLIB/std/src/panicking.rs:LL:CC
-  14: std::panicking::r#try
+  14: std::panicking::catch_unwind
  at RUSTLIB/std/src/panicking.rs:LL:CC
   15: std::panic::catch_unwind
  at RUSTLIB/std/src/panic.rs:LL:CC
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 0b389377011..5c862e95400 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -344,17 +344,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "dbus"
-version = "0.9.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b"
-dependencies = [
- "libc",
- "libdbus-sys",
- "winapi",
-]
-
-[[package]]
 name = "derive_builder"
 version = "0.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -824,16 +813,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
 
 [[package]]
-name = "libdbus-sys"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72"
-dependencies = [
- "cc",
- "pkg-config",
-]
-
-[[package]]
 name = "linereader"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -906,9 +885,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.49"
+version = "0.4.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1daacee059634081dee4250d2814763a365b92dfe14bfdef964bc27835209d4"
+checksum = "f72bc08f096e1fb15cfc382babe218317c2897d2040f967c4db40d156ca28e21"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -921,7 +900,6 @@ dependencies = [
  "hex",
  "log",
  "memchr",
- "once_cell",
  "opener",
  "pulldown-cmark 0.10.3",
  "regex",
@@ -1070,12 +1048,11 @@ dependencies = [
 
 [[package]]
 name = "opener"
-version = "0.7.2"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681"
+checksum = "de96cad6ee771be7f68df884d3767460b4684012308d8342ed5623fe62b2628c"
 dependencies = [
  "bstr",
- "dbus",
  "normpath",
  "windows-sys",
 ]
@@ -1906,22 +1883,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
 name = "winapi-util"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1931,12 +1892,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
 name = "windows-core"
 version = "0.61.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 10fde31306d..ee2ada5aa2b 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3"
 mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
 
 [dependencies.mdbook]
-version = "0.4.49"
+version = "0.4.50"
 default-features = false
 features = ["search"]
diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs
index ad2770d43e3..b7abeb02298 100644
--- a/tests/assembly/asm/aarch64-types.rs
+++ b/tests/assembly/asm/aarch64-types.rs
@@ -86,12 +86,11 @@ pub unsafe fn sym_static() {
 
 // Regression test for #75761
 // CHECK-LABEL: {{("#)?}}issue_75761{{"?}}
-// aarch64: str {{.*}}x30
-// arm64ec: stp {{.*}}x30
+// x29 holds the frame pointer, right next to x30, so ldp/stp happens sometimes
+// CHECK: st[[MAY_PAIR:(r|p).*]]x30
 // CHECK: //APP
 // CHECK: //NO_APP
-// aarch64: ldr {{.*}}x30
-// arm64ec: ldp {{.*}}x30
+// CHECK: ld[[MAY_PAIR]]x30
 #[no_mangle]
 pub unsafe fn issue_75761() {
     asm!("", out("v0") _, out("x30") _);
diff --git a/tests/codegen/frame-pointer.rs b/tests/codegen/frame-pointer.rs
index 1f7c9a59c98..23989653fa8 100644
--- a/tests/codegen/frame-pointer.rs
+++ b/tests/codegen/frame-pointer.rs
@@ -26,8 +26,10 @@ pub fn peach(x: u32) -> u32 {
 
 // CHECK: attributes [[PEACH_ATTRS]] = {
 // x64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
-// aarch64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
 // x64-apple-SAME: {{.*}}"frame-pointer"="all"
 // force-SAME: {{.*}}"frame-pointer"="all"
+//
+// AAPCS64 demands frame pointers:
+// aarch64-linux-SAME: {{.*}}"frame-pointer"="non-leaf"
 // aarch64-apple-SAME: {{.*}}"frame-pointer"="non-leaf"
 // CHECK-SAME: }
diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
index 5fc77f95eaf..8afb6ad250e 100644
--- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
@@ -1,34 +1,34 @@
 // MIR for `address_of_reborrow` after SimplifyCfg-initial
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
-| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send
-| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
-| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
+| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
+| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send
+| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
+| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
 | 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
 | 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
-| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
-| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
+| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
+| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
 | 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
 | 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
-| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
-| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send
-| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
-| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
+| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
+| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send
+| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
+| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
 | 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
 | 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
-| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
-| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
+| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
+| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
 | 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
 | 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
-| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
-| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send
-| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
-| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
+| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
+| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send
+| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
+| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
 | 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
 | 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
-| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
-| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
+| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
+| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
 | 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
 | 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
 |
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
index 6e349a2a24f..744553c7cd2 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
+++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
@@ -3,8 +3,8 @@
 | User Type Annotations
 | 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
 | 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
-| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/rustdoc-js/auxiliary/interner.rs b/tests/rustdoc-js/auxiliary/interner.rs
index e4e4ff6276d..8af3b732ef7 100644
--- a/tests/rustdoc-js/auxiliary/interner.rs
+++ b/tests/rustdoc-js/auxiliary/interner.rs
@@ -18,7 +18,7 @@ pub trait Interner: Sized {
     type Binder<T: TypeVisitable<Self>>: BoundVars<Self> + TypeSuperVisitable<Self>;
     type BoundVars: IntoIterator<Item = Self::BoundVar>;
     type BoundVar;
-    type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
+    type CanonicalVarKinds: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarKind<Self>>;
     type Ty: Copy
         + DebugWithInfcx<Self>
         + Hash
@@ -77,7 +77,7 @@ pub trait Interner: Sized {
     type ClosureKind: Copy + Debug + Hash + Eq;
 
     // Required method
-    fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
+    fn mk_canonical_var_kinds(self, kinds: &[CanonicalVarKind<Self>]) -> Self::CanonicalVarKinds;
 }
 
 pub trait DebugWithInfcx<I: Interner>: Debug {
@@ -104,10 +104,6 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
     fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
 }
 
-pub struct CanonicalVarInfo<I: Interner> {
-    pub kind: CanonicalVarKind<I>,
-}
-
 pub struct CanonicalVarKind<I>(std::marker::PhantomData<I>);
 
 pub struct TyKind<I>(std::marker::PhantomData<I>);
diff --git a/tests/rustdoc-js/looks-like-rustc-interner.js b/tests/rustdoc-js/looks-like-rustc-interner.js
index d6d2764c3ae..7d051194454 100644
--- a/tests/rustdoc-js/looks-like-rustc-interner.js
+++ b/tests/rustdoc-js/looks-like-rustc-interner.js
@@ -3,13 +3,13 @@
 
 const EXPECTED = [
     {
-        'query': 'canonicalvarinfo, intoiterator -> intoiterator',
+        'query': 'CanonicalVarKind, intoiterator -> intoiterator',
         'others': [],
     },
     {
-        'query': '[canonicalvarinfo], interner<tys=intoiterator> -> intoiterator',
+        'query': '[CanonicalVarKind], interner<tys=intoiterator> -> intoiterator',
         'others': [
-            { 'path': 'looks_like_rustc_interner::Interner', 'name': 'mk_canonical_var_infos' },
+            { 'path': 'looks_like_rustc_interner::Interner', 'name': 'mk_canonical_var_kinds' },
         ],
     },
 ];
diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
index bf20473924b..07c3fd3527f 100644
--- a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
+++ b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
@@ -42,30 +42,6 @@ LL |     async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
    = help: consider moving `async_dispatch` to another trait
    = note: required for the cast from `Pin<&mut {async block@$DIR/mut-is-pointer-like.rs:32:32: 32:37}>` to `Pin<&mut dyn AsyncTrait<Output = ()>>`
 
-error[E0277]: the trait bound `dyn AsyncTrait<Output = ()>: AsyncTrait` is not satisfied
-  --> $DIR/mut-is-pointer-like.rs:36:11
-   |
-LL |         x.async_dispatch().await;
-   |           ^^^^^^^^^^^^^^ the trait `AsyncTrait` is not implemented for `dyn AsyncTrait<Output = ()>`
-
-error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/mut-is-pointer-like.rs:36:9
-   |
-LL |         x.async_dispatch().await;
-   |         ^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/mut-is-pointer-like.rs:16:14
-   |
-LL | trait AsyncTrait {
-   |       ---------- this trait is not dyn compatible...
-...
-LL |     async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
-   |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
-   = help: consider moving `async_dispatch` to another trait
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0038, E0277.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/dyn/works.stderr b/tests/ui/async-await/dyn/works.stderr
index 47abeab5aac..1fe2b28eca8 100644
--- a/tests/ui/async-await/dyn/works.stderr
+++ b/tests/ui/async-await/dyn/works.stderr
@@ -42,40 +42,6 @@ LL |     async fn async_dispatch(&self);
    = help: consider moving `async_dispatch` to another trait
    = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
 
-error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/works.rs:28:11
-   |
-LL |         x.async_dispatch().await;
-   |           ^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/works.rs:14:14
-   |
-LL | trait AsyncTrait {
-   |       ---------- this trait is not dyn compatible...
-LL |     async fn async_dispatch(&self);
-   |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
-   = help: consider moving `async_dispatch` to another trait
-   = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
-
-error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/works.rs:28:9
-   |
-LL |         x.async_dispatch().await;
-   |         ^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/works.rs:14:14
-   |
-LL | trait AsyncTrait {
-   |       ---------- this trait is not dyn compatible...
-LL |     async fn async_dispatch(&self);
-   |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
-   = help: consider moving `async_dispatch` to another trait
-   = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/check-cfg/wrong-version-syntax.fixed b/tests/ui/check-cfg/wrong-version-syntax.fixed
new file mode 100644
index 00000000000..efbe2ed1bd8
--- /dev/null
+++ b/tests/ui/check-cfg/wrong-version-syntax.fixed
@@ -0,0 +1,14 @@
+// Check warning for wrong `cfg(version("1.27"))` syntax
+//
+//@ check-pass
+//@ no-auto-check-cfg
+//@ compile-flags: --check-cfg=cfg()
+//@ run-rustfix
+
+#![feature(cfg_version)]
+
+#[cfg(not(version("1.48.0")))]
+//~^ WARNING unexpected `cfg` condition name: `version`
+pub fn g() {}
+
+pub fn main() {}
diff --git a/tests/ui/check-cfg/wrong-version-syntax.rs b/tests/ui/check-cfg/wrong-version-syntax.rs
new file mode 100644
index 00000000000..221ecf4cae8
--- /dev/null
+++ b/tests/ui/check-cfg/wrong-version-syntax.rs
@@ -0,0 +1,14 @@
+// Check warning for wrong `cfg(version("1.27"))` syntax
+//
+//@ check-pass
+//@ no-auto-check-cfg
+//@ compile-flags: --check-cfg=cfg()
+//@ run-rustfix
+
+#![feature(cfg_version)]
+
+#[cfg(not(version = "1.48.0"))]
+//~^ WARNING unexpected `cfg` condition name: `version`
+pub fn g() {}
+
+pub fn main() {}
diff --git a/tests/ui/check-cfg/wrong-version-syntax.stderr b/tests/ui/check-cfg/wrong-version-syntax.stderr
new file mode 100644
index 00000000000..97157a0c02b
--- /dev/null
+++ b/tests/ui/check-cfg/wrong-version-syntax.stderr
@@ -0,0 +1,17 @@
+warning: unexpected `cfg` condition name: `version`
+  --> $DIR/wrong-version-syntax.rs:10:11
+   |
+LL | #[cfg(not(version = "1.48.0"))]
+   |           ^^^^^^^^^^^^^^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(version, values("1.48.0"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+help: there is a similar config predicate: `version("..")`
+   |
+LL - #[cfg(not(version = "1.48.0"))]
+LL + #[cfg(not(version("1.48.0")))]
+   |
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs
index 9ab715d01f7..da9a75b50ef 100644
--- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs
+++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs
@@ -15,7 +15,7 @@ impl Foo for () {
 }
 
 fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` is not dyn compatible
-    v.test(); //~ERROR the trait `Foo` is not dyn compatible
+    v.test();
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr
index 8bc6ef093d0..120ee435e25 100644
--- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr
@@ -17,25 +17,6 @@ LL |     fn test(&self) -> [u8; bar::<Self>()];
    = help: consider moving `test` to another trait
    = help: only type `()` implements `Foo`; consider using it directly instead.
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/dyn-compatibility-err-ret.rs:18:5
-   |
-LL |     v.test();
-   |     ^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/dyn-compatibility-err-ret.rs:8:8
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     fn test(&self) -> [u8; bar::<Self>()];
-   |        ^^^^           ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type
-   |        |
-   |        ...because method `test` references the `Self` type in its `where` clause
-   = help: consider moving `test` to another trait
-   = help: only type `()` implements `Foo`; consider using it directly instead.
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs
index a7b771cd4f8..8b735188f32 100644
--- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs
+++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs
@@ -15,7 +15,6 @@ impl Foo for () {
 fn use_dyn(v: &dyn Foo) {
     //~^ ERROR the trait `Foo` is not dyn compatible
     v.test();
-    //~^ ERROR the trait `Foo` is not dyn compatible
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr
index f5eaaa37916..c2ad4d14988 100644
--- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr
@@ -15,23 +15,6 @@ LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
    = help: consider moving `test` to another trait
    = help: only type `()` implements `Foo`; consider using it directly instead.
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/dyn-compatibility-err-where-bounds.rs:17:5
-   |
-LL |     v.test();
-   |     ^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
-   |        ^^^^ ...because method `test` references the `Self` type in its `where` clause
-   = help: consider moving `test` to another trait
-   = help: only type `()` implements `Foo`; consider using it directly instead.
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs
index ec32bec7785..ac3c2aadf29 100644
--- a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs
+++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs
@@ -25,5 +25,4 @@ pub fn foo() {
     let fetcher = fetcher();
     //~^ ERROR the trait `Fetcher` is not dyn compatible
     let _ = fetcher.get();
-    //~^ ERROR the trait `Fetcher` is not dyn compatible
 }
diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
index 1299167159e..867a719e2eb 100644
--- a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
+++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr
@@ -34,24 +34,6 @@ LL | pub trait Fetcher: Send + Sync {
 LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
    |                      ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on
 
-error[E0038]: the trait `Fetcher` is not dyn compatible
-  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:27:13
-   |
-LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
-   |                      ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self`
-...
-LL |     let _ = fetcher.get();
-   |             ^^^^^^^^^^^^^ `Fetcher` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22
-   |
-LL | pub trait Fetcher: Send + Sync {
-   |           ------- this trait is not dyn compatible...
-LL |     fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
-   |                      ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/error-codes/E0038.rs b/tests/ui/error-codes/E0038.rs
index a467767c3fa..9757e2ab10c 100644
--- a/tests/ui/error-codes/E0038.rs
+++ b/tests/ui/error-codes/E0038.rs
@@ -5,8 +5,6 @@ trait Trait {
 fn call_foo(x: Box<dyn Trait>) {
     //~^ ERROR E0038
     let y = x.foo();
-    //~^ ERROR E0038
-    //~| ERROR E0277
 }
 
 fn main() {
diff --git a/tests/ui/error-codes/E0038.stderr b/tests/ui/error-codes/E0038.stderr
index 63a5249a386..e09aefaa0dd 100644
--- a/tests/ui/error-codes/E0038.stderr
+++ b/tests/ui/error-codes/E0038.stderr
@@ -14,33 +14,6 @@ LL |     fn foo(&self) -> Self;
    |                      ^^^^ ...because method `foo` references the `Self` type in its return type
    = help: consider moving `foo` to another trait
 
-error[E0038]: the trait `Trait` is not dyn compatible
-  --> $DIR/E0038.rs:7:13
-   |
-LL |     let y = x.foo();
-   |             ^^^^^^^ `Trait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/E0038.rs:2:22
-   |
-LL | trait Trait {
-   |       ----- this trait is not dyn compatible...
-LL |     fn foo(&self) -> Self;
-   |                      ^^^^ ...because method `foo` references the `Self` type in its return type
-   = help: consider moving `foo` to another trait
-
-error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
-  --> $DIR/E0038.rs:7:9
-   |
-LL |     let y = x.foo();
-   |         ^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `dyn Trait`
-   = note: all local variables must have a statically known size
-   = help: unsized locals are gated as an unstable feature
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0038, E0277.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs
index 278a5451e84..50e5fd1ab7a 100644
--- a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs
+++ b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs
@@ -7,8 +7,6 @@ trait Foo {
 async fn takes_dyn_trait(x: &dyn Foo) {
     //~^ ERROR the trait `Foo` is not dyn compatible
     x.bar().await;
-    //~^ ERROR the trait `Foo` is not dyn compatible
-    //~| ERROR the trait `Foo` is not dyn compatible
 }
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
index ab8c092a826..fd94b0babdb 100644
--- a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
+++ b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr
@@ -14,38 +14,6 @@ LL |     async fn bar(&self);
    |              ^^^ ...because method `bar` is `async`
    = help: consider moving `bar` to another trait
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:9:7
-   |
-LL |     x.bar().await;
-   |       ^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     async fn bar(&self);
-   |              ^^^ ...because method `bar` is `async`
-   = help: consider moving `bar` to another trait
-
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:9:5
-   |
-LL |     x.bar().await;
-   |     ^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     async fn bar(&self);
-   |              ^^^ ...because method `bar` is `async`
-   = help: consider moving `bar` to another trait
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs
index 256cfee4c80..87817111b54 100644
--- a/tests/ui/generic-associated-types/trait-objects.rs
+++ b/tests/ui/generic-associated-types/trait-objects.rs
@@ -8,8 +8,6 @@ trait StreamingIterator {
 fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
     //~^ ERROR the trait `StreamingIterator` is not dyn compatible
     x.size_hint().0
-    //~^ ERROR the trait `StreamingIterator` is not dyn compatible
-    //~| ERROR the trait `StreamingIterator` is not dyn compatible
 }
 
 fn main() {}
diff --git a/tests/ui/generic-associated-types/trait-objects.stderr b/tests/ui/generic-associated-types/trait-objects.stderr
index 7d95718ec87..8c3af6b654a 100644
--- a/tests/ui/generic-associated-types/trait-objects.stderr
+++ b/tests/ui/generic-associated-types/trait-objects.stderr
@@ -14,38 +14,6 @@ LL |     type Item<'a> where Self: 'a;
    |          ^^^^ ...because it contains the generic associated type `Item`
    = help: consider moving `Item` to another trait
 
-error[E0038]: the trait `StreamingIterator` is not dyn compatible
-  --> $DIR/trait-objects.rs:10:7
-   |
-LL |     x.size_hint().0
-   |       ^^^^^^^^^ `StreamingIterator` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/trait-objects.rs:2:10
-   |
-LL | trait StreamingIterator {
-   |       ----------------- this trait is not dyn compatible...
-LL |     type Item<'a> where Self: 'a;
-   |          ^^^^ ...because it contains the generic associated type `Item`
-   = help: consider moving `Item` to another trait
-
-error[E0038]: the trait `StreamingIterator` is not dyn compatible
-  --> $DIR/trait-objects.rs:10:5
-   |
-LL |     x.size_hint().0
-   |     ^^^^^^^^^^^^^ `StreamingIterator` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/trait-objects.rs:2:10
-   |
-LL | trait StreamingIterator {
-   |       ----------------- this trait is not dyn compatible...
-LL |     type Item<'a> where Self: 'a;
-   |          ^^^^ ...because it contains the generic associated type `Item`
-   = help: consider moving `Item` to another trait
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs
index 85b1ba269fc..92203c470bb 100644
--- a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs
+++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs
@@ -15,6 +15,4 @@ fn main() {
     //~^ ERROR the trait `Foo` is not dyn compatible
     //~| ERROR the trait `Foo` is not dyn compatible
     let s = i.baz();
-    //~^ ERROR the trait `Foo` is not dyn compatible
-    //~| ERROR the trait `Foo` is not dyn compatible
 }
diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
index 840c27e183f..5c498548aff 100644
--- a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
+++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
@@ -16,40 +16,6 @@ LL |     fn baz(&self) -> impl Debug;
    = help: only type `u32` implements `Foo`; consider using it directly instead.
 
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/dyn-compatibility.rs:17:15
-   |
-LL |     let s = i.baz();
-   |               ^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/dyn-compatibility.rs:4:22
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     fn baz(&self) -> impl Debug;
-   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
-   = help: consider moving `baz` to another trait
-   = help: only type `u32` implements `Foo`; consider using it directly instead.
-
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/dyn-compatibility.rs:17:13
-   |
-LL |     let s = i.baz();
-   |             ^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/dyn-compatibility.rs:4:22
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     fn baz(&self) -> impl Debug;
-   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
-   = help: consider moving `baz` to another trait
-   = help: only type `u32` implements `Foo`; consider using it directly instead.
-
-error[E0038]: the trait `Foo` is not dyn compatible
   --> $DIR/dyn-compatibility.rs:14:13
    |
 LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
@@ -67,6 +33,6 @@ LL |     fn baz(&self) -> impl Debug;
    = help: only type `u32` implements `Foo`; consider using it directly instead.
    = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/issues/issue-18959.rs b/tests/ui/issues/issue-18959.rs
index 6aeb34879ea..dbc73bafce9 100644
--- a/tests/ui/issues/issue-18959.rs
+++ b/tests/ui/issues/issue-18959.rs
@@ -11,7 +11,6 @@ impl Foo for Thing {
 fn foo(b: &dyn Bar) {
     //~^ ERROR E0038
     b.foo(&0)
-    //~^ ERROR E0038
 }
 
 fn main() {
diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr
index 1e050b115e5..7ddfdb49d95 100644
--- a/tests/ui/issues/issue-18959.stderr
+++ b/tests/ui/issues/issue-18959.stderr
@@ -15,23 +15,7 @@ LL | pub trait Bar: Foo { }
    = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/issue-18959.rs:13:5
-   |
-LL |     b.foo(&0)
-   |     ^^^^^^^^^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-18959.rs:1:20
-   |
-LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
-   |                    ^^^ ...because method `foo` has generic type parameters
-LL | pub trait Bar: Foo { }
-   |           --- this trait is not dyn compatible...
-   = help: consider moving `foo` to another trait
-
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/issue-18959.rs:19:26
+  --> $DIR/issue-18959.rs:18:26
    |
 LL |     let test: &dyn Bar = &mut thing;
    |                          ^^^^^^^^^^ `Bar` is not dyn compatible
@@ -48,7 +32,7 @@ LL | pub trait Bar: Foo { }
    = note: required for the cast from `&mut Thing` to `&dyn Bar`
 
 error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/issue-18959.rs:19:15
+  --> $DIR/issue-18959.rs:18:15
    |
 LL |     let test: &dyn Bar = &mut thing;
    |               ^^^^^^^^ `Bar` is not dyn compatible
@@ -63,6 +47,6 @@ LL | pub trait Bar: Foo { }
    |           --- this trait is not dyn compatible...
    = help: consider moving `foo` to another trait
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs
new file mode 100644
index 00000000000..af35d1e0359
--- /dev/null
+++ b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs
@@ -0,0 +1,18 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/141419>.
+
+use std::ops::Deref;
+
+struct W;
+
+trait Foo: Deref<Target = W> {
+    fn method(self: &W) {}
+    //~^ ERROR invalid `self` parameter type: `&W`
+}
+
+fn test(x: &dyn Foo) {
+    //~^ ERROR the trait `Foo` is not dyn compatible
+    x.method();
+    //~^ ERROR the trait `Foo` is not dyn compatible
+}
+
+fn main() {}
diff --git a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr
new file mode 100644
index 00000000000..237bbc56715
--- /dev/null
+++ b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr
@@ -0,0 +1,49 @@
+error[E0038]: the trait `Foo` is not dyn compatible
+  --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:12:13
+   |
+LL |     fn method(self: &W) {}
+   |                     -- help: consider changing method `method`'s `self` parameter to be `&self`: `&Self`
+...
+LL | fn test(x: &dyn Foo) {
+   |             ^^^^^^^ `Foo` is not dyn compatible
+   |
+note: for a trait to be dyn compatible it needs to allow building a vtable
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
+  --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:8:21
+   |
+LL | trait Foo: Deref<Target = W> {
+   |       --- this trait is not dyn compatible...
+LL |     fn method(self: &W) {}
+   |                     ^^ ...because method `method`'s `self` parameter cannot be dispatched on
+
+error[E0307]: invalid `self` parameter type: `&W`
+  --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:8:21
+   |
+LL |     fn method(self: &W) {}
+   |                     ^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0038]: the trait `Foo` is not dyn compatible
+  --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:14:5
+   |
+LL |     fn method(self: &W) {}
+   |                     -- help: consider changing method `method`'s `self` parameter to be `&self`: `&Self`
+...
+LL |     x.method();
+   |     ^^^^^^^^^^ `Foo` is not dyn compatible
+   |
+note: for a trait to be dyn compatible it needs to allow building a vtable
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
+  --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:8:21
+   |
+LL | trait Foo: Deref<Target = W> {
+   |       --- this trait is not dyn compatible...
+LL |     fn method(self: &W) {}
+   |                     ^^ ...because method `method`'s `self` parameter cannot be dispatched on
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0307.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs
index ffb778a0141..4ee880da87a 100644
--- a/tests/ui/traits/test-2.rs
+++ b/tests/ui/traits/test-2.rs
@@ -13,5 +13,4 @@ fn main() {
     (Box::new(10) as Box<dyn bar>).dup();
     //~^ ERROR E0038
     //~| ERROR E0038
-    //~| ERROR E0038
 }
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
index 6a6cb503aa4..b52839c300e 100644
--- a/tests/ui/traits/test-2.stderr
+++ b/tests/ui/traits/test-2.stderr
@@ -50,29 +50,6 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
            implementing `bar` for this new enum and using it instead
 
 error[E0038]: the trait `bar` is not dyn compatible
-  --> $DIR/test-2.rs:13:5
-   |
-LL |     (Box::new(10) as Box<dyn bar>).dup();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/test-2.rs:4:30
-   |
-LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
-   |       ---                    ^^^^     ^^^^ ...because method `blah` has generic type parameters
-   |       |                      |
-   |       |                      ...because method `dup` references the `Self` type in its return type
-   |       this trait is not dyn compatible...
-   = help: consider moving `dup` to another trait
-   = help: consider moving `blah` to another trait
-   = help: the following types implement `bar`:
-             i32
-             u32
-           consider defining an enum where each variant holds one of these types,
-           implementing `bar` for this new enum and using it instead
-
-error[E0038]: the trait `bar` is not dyn compatible
   --> $DIR/test-2.rs:13:6
    |
 LL |     (Box::new(10) as Box<dyn bar>).dup();
@@ -96,7 +73,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
            implementing `bar` for this new enum and using it instead
    = note: required for the cast from `Box<{integer}>` to `Box<dyn bar>`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/unsafe-binders/non-strucutral-type-diag.rs b/tests/ui/unsafe-binders/non-strucutral-type-diag.rs
new file mode 100644
index 00000000000..e021e9567e5
--- /dev/null
+++ b/tests/ui/unsafe-binders/non-strucutral-type-diag.rs
@@ -0,0 +1,17 @@
+// regression test for <https://github.com/rust-lang/rust/issues/141422>.
+
+#![feature(unsafe_binders)]
+#![allow(incomplete_features)]
+
+#[derive(Copy, Clone)]
+struct Adt<'a>(&'a ());
+
+const C: Option<(unsafe<'a> Adt<'a>, Box<dyn Send>)> = None;
+
+fn main() {
+    match None {
+        C => {}
+        //~^ ERROR constant of non-structural type
+        _ => {}
+    }
+}
diff --git a/tests/ui/unsafe-binders/non-strucutral-type-diag.stderr b/tests/ui/unsafe-binders/non-strucutral-type-diag.stderr
new file mode 100644
index 00000000000..ab23210b2e5
--- /dev/null
+++ b/tests/ui/unsafe-binders/non-strucutral-type-diag.stderr
@@ -0,0 +1,13 @@
+error: constant of non-structural type `Option<(unsafe<'a> Adt<'a>, Box<dyn Send>)>` in a pattern
+  --> $DIR/non-strucutral-type-diag.rs:13:9
+   |
+LL | const C: Option<(unsafe<'a> Adt<'a>, Box<dyn Send>)> = None;
+   | ---------------------------------------------------- constant defined here
+...
+LL |         C => {}
+   |         ^ constant of non-structural type
+   |
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+
+error: aborting due to 1 previous error
+
diff --git a/triagebot.toml b/triagebot.toml
index fd7a861bc92..9d7a0ef5aec 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -44,8 +44,6 @@ remove_labels = ["S-waiting-on-author"]
 # Those labels are added when PR author requests a review from an assignee
 add_labels = ["S-waiting-on-review"]
 
-[glacier]
-
 [ping.icebreakers-llvm]
 message = """\
 Hey LLVM ICE-breakers! This bug has been identified as a good
@@ -1425,3 +1423,12 @@ compiletest = [
 
 [behind-upstream]
 days-threshold = 14
+
+# Canonicalize issue numbers to avoid closing the wrong issue
+# when commits are included in subtrees, as well as warning links in commits.
+# Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html
+[issue-links]
+
+# Prevents mentions in commits to avoid users being spammed
+# Documentation at: https://forge.rust-lang.org/triagebot/no-mentions.html
+[no-mentions]