about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-04-26 15:59:32 +0000
committerbors <bors@rust-lang.org>2025-04-26 15:59:32 +0000
commit10fa3c449f6b1613b352a6cbf78d3d91fd9a1d81 (patch)
tree8a7822df3f57929510160713ec757a27d42fad04
parent5ae50d3b2182f81eea4e4d90e8da3653547215b5 (diff)
parent153eeb0e24471a4733878c611cf60e8ba827d6cd (diff)
Auto merge of #140336 - matthiaskrgr:rollup-kxo6ljw, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #140215 (transmutability: Support char, NonZeroXxx)
 - #140226 (Update wasm-component-ld to 0.5.13)
 - #140317 (Remove redundant check)
 - #140318 (Simply try to unpeel AsyncFnKindHelper goal in `emit_specialized_closure_kind_error`)
 - #140320 (replace `GenericArg` with `Term` where applicable)
 - #140325 (Grammar fixes for BufRead::has_data_left docs)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock87
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs43
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs16
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs17
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs15
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs8
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs4
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs35
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs37
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs41
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs14
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs80
-rw-r--r--compiler/rustc_transmute/src/layout/mod.rs7
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs146
-rw-r--r--compiler/rustc_transmute/src/layout/tree/tests.rs24
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/tests.rs82
-rw-r--r--compiler/rustc_type_ir/src/flags.rs6
-rw-r--r--compiler/rustc_type_ir/src/predicate_kind.rs2
-rw-r--r--library/std/src/io/mod.rs4
-rw-r--r--src/tools/wasm-component-ld/Cargo.toml2
-rw-r--r--tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.rs22
-rw-r--r--tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.stderr21
-rw-r--r--tests/ui/transmutability/char.rs41
-rw-r--r--tests/ui/transmutability/char.stderr48
40 files changed, 573 insertions, 316 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4fc3cbcfd3a..be704e84a50 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4919,15 +4919,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "spdx"
-version = "0.10.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58b69356da67e2fc1f542c71ea7e654a361a79c938e4424392ecf4fa065d2193"
-dependencies = [
- "smallvec",
-]
-
-[[package]]
 name = "spdx-expression"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5746,9 +5737,9 @@ dependencies = [
 
 [[package]]
 name = "wasi-preview1-component-adapter-provider"
-version = "29.0.1"
+version = "31.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcd9f21bbde82ba59e415a8725e6ad0d0d7e9e460b1a3ccbca5bdee952c1a324"
+checksum = "86fabda09a0d89ffd1615b297b4a5d4b4d99df9598aeb24685837e63019e927b"
 
 [[package]]
 name = "wasm-bindgen"
@@ -5810,9 +5801,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-component-ld"
-version = "0.5.12"
+version = "0.5.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "580305a8e3f1b7a79859a8db897de643533b2851c5eb080fe5800233f16dec88"
+checksum = "a60a07a994a3538b57d8c5f8caba19f4793fb4c7156276e5e90e90acbb829e20"
 dependencies = [
  "anyhow",
  "clap",
@@ -5820,7 +5811,7 @@ dependencies = [
  "libc",
  "tempfile",
  "wasi-preview1-component-adapter-provider",
- "wasmparser 0.223.1",
+ "wasmparser 0.229.0",
  "wat",
  "windows-sys 0.59.0",
  "winsplit",
@@ -5847,39 +5838,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.223.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a0a96fdeaee8fbeb4bd917fb8157d48c0d61c3b1f4ee4c363c8e8d68b2f4fe8"
-dependencies = [
- "leb128",
- "wasmparser 0.223.1",
-]
-
-[[package]]
-name = "wasm-encoder"
-version = "0.228.0"
+version = "0.229.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05d30290541f2d4242a162bbda76b8f2d8b1ac59eab3568ed6f2327d52c9b2c4"
+checksum = "38ba1d491ecacb085a2552025c10a675a6fddcbd03b1fc9b36c536010ce265d2"
 dependencies = [
  "leb128fmt",
- "wasmparser 0.228.0",
+ "wasmparser 0.229.0",
 ]
 
 [[package]]
 name = "wasm-metadata"
-version = "0.223.1"
+version = "0.229.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7e37883181704d96b89dbd8f1291be13694c71cd0663aebb94b46d235a377"
+checksum = "78fdb7d29a79191ab363dc90c1ddd3a1e880ffd5348d92d48482393a9e6c5f4d"
 dependencies = [
  "anyhow",
  "indexmap",
- "serde",
- "serde_derive",
- "serde_json",
- "spdx",
- "url",
- "wasm-encoder 0.223.1",
- "wasmparser 0.223.1",
+ "wasm-encoder 0.229.0",
+ "wasmparser 0.229.0",
 ]
 
 [[package]]
@@ -5903,9 +5879,9 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.223.1"
+version = "0.229.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "664b980991ed9a8c834eb528a8979ab1109edcf52dc05dd5751e2cc3fb31035d"
+checksum = "0cc3b1f053f5d41aa55640a1fa9b6d1b8a9e4418d118ce308d20e24ff3575a8c"
 dependencies = [
  "bitflags",
  "hashbrown",
@@ -5915,34 +5891,23 @@ dependencies = [
 ]
 
 [[package]]
-name = "wasmparser"
-version = "0.228.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4abf1132c1fdf747d56bbc1bb52152400c70f336870f968b85e89ea422198ae3"
-dependencies = [
- "bitflags",
- "indexmap",
- "semver",
-]
-
-[[package]]
 name = "wast"
-version = "228.0.0"
+version = "229.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5aae124478cb51439f6587f074a3a5e835afd22751c59a87b2e2a882727c97"
+checksum = "63fcaff613c12225696bb163f79ca38ffb40e9300eff0ff4b8aa8b2f7eadf0d9"
 dependencies = [
  "bumpalo",
  "leb128fmt",
  "memchr",
  "unicode-width 0.2.0",
- "wasm-encoder 0.228.0",
+ "wasm-encoder 0.229.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.228.0"
+version = "1.229.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ec29c89a8d055df988de7236483bf569988ac3d6905899f6af5ef920f9385ad"
+checksum = "4189bad08b70455a9e9e67dc126d2dcf91fac143a80f1046747a5dde6d4c33e0"
 dependencies = [
  "wast",
 ]
@@ -6401,9 +6366,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.223.1"
+version = "0.229.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fc2fcc52a79f6f010a89c867e53e06d4227f86c58984add3e37f32b8e7af5f0"
+checksum = "7f550067740e223bfe6c4878998e81cdbe2529dd9a793dc49248dd6613394e8b"
 dependencies = [
  "anyhow",
  "bitflags",
@@ -6412,17 +6377,17 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.223.1",
+ "wasm-encoder 0.229.0",
  "wasm-metadata",
- "wasmparser 0.223.1",
+ "wasmparser 0.229.0",
  "wit-parser",
 ]
 
 [[package]]
 name = "wit-parser"
-version = "0.223.1"
+version = "0.229.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "263fde17f1fbe55a413f16eb59094bf751795c6da469a05c3d45ea6c77df6b40"
+checksum = "459c6ba62bf511d6b5f2a845a2a736822e38059c1cfa0b644b467bbbfae4efa6"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -6433,7 +6398,7 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser 0.223.1",
+ "wasmparser 0.229.0",
 ]
 
 [[package]]
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 4f338c6a19e..f92b2aea160 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -730,7 +730,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                     .is_ok()
                 {
                     check_impl_items_against_trait(tcx, def_id, impl_trait_header);
-                    check_on_unimplemented(tcx, def_id);
                 }
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 06a7b1f6c29..bbf36fef1dd 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -379,13 +379,13 @@ fn compare_method_predicate_entailment<'tcx>(
         // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
         // will give back the well-formed predicate of the same array.
         let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect();
-        while let Some(arg) = wf_args.pop() {
+        while let Some(term) = wf_args.pop() {
             let Some(obligations) = rustc_trait_selection::traits::wf::obligations(
                 infcx,
                 param_env,
                 impl_m_def_id,
                 0,
-                arg,
+                term,
                 impl_m_span,
             ) else {
                 continue;
@@ -402,9 +402,9 @@ fn compare_method_predicate_entailment<'tcx>(
                         | ty::ClauseKind::TypeOutlives(..)
                         | ty::ClauseKind::Projection(..),
                     ) => ocx.register_obligation(obligation),
-                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                        if wf_args_seen.insert(arg) {
-                            wf_args.push(arg)
+                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
+                        if wf_args_seen.insert(term) {
+                            wf_args.push(term)
                         }
                     }
                     _ => {}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 33d5a86beb3..26111e2a1ac 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -76,12 +76,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
         )
     }
 
-    fn register_wf_obligation(
-        &self,
-        span: Span,
-        loc: Option<WellFormedLoc>,
-        arg: ty::GenericArg<'tcx>,
-    ) {
+    fn register_wf_obligation(&self, span: Span, loc: Option<WellFormedLoc>, term: ty::Term<'tcx>) {
         let cause = traits::ObligationCause::new(
             span,
             self.body_def_id,
@@ -91,7 +86,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
             self.tcx(),
             cause,
             self.param_env,
-            ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
+            ty::ClauseKind::WellFormed(term),
         ));
     }
 }
@@ -1486,7 +1481,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
                     tcx.def_span(param.def_id),
                     matches!(param.kind, GenericParamDefKind::Type { .. })
                         .then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
-                    default,
+                    default.as_term().unwrap(),
                 );
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index af1107b499f..309221f9a12 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -374,9 +374,12 @@ fn check_predicates<'tcx>(
 
     // Include the well-formed predicates of the type parameters of the impl.
     for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
+        let Some(term) = arg.as_term() else {
+            continue;
+        };
         let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
         let obligations =
-            wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
+            wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, term, span)
                 .unwrap();
 
         assert!(!obligations.has_infer());
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index cac8237f8f6..362c7d8efac 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -22,8 +22,8 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
 use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{
-    self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind,
-    IsIdentity, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy,
+    self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity, Ty, TyCtxt,
+    TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
@@ -573,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Registers an obligation for checking later, during regionck, that `arg` is well-formed.
     pub(crate) fn register_wf_obligation(
         &self,
-        arg: ty::GenericArg<'tcx>,
+        term: ty::Term<'tcx>,
         span: Span,
         code: traits::ObligationCauseCode<'tcx>,
     ) {
@@ -583,16 +583,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.tcx,
             cause,
             self.param_env,
-            ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
+            ty::ClauseKind::WellFormed(term),
         ));
     }
 
     /// Registers obligations that all `args` are well-formed.
     pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, span: Span) {
-        for arg in args.iter().filter(|arg| {
-            matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
-        }) {
-            self.register_wf_obligation(arg, span, ObligationCauseCode::WellFormed(None));
+        for term in args.iter().filter_map(ty::GenericArg::as_term) {
+            self.register_wf_obligation(term, span, ObligationCauseCode::WellFormed(None));
         }
     }
 
@@ -1320,27 +1318,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 infer_args: bool,
             ) -> ty::GenericArg<'tcx> {
                 let tcx = self.fcx.tcx();
-                match param.kind {
-                    GenericParamDefKind::Lifetime => self
-                        .fcx
-                        .re_infer(
-                            self.span,
-                            rustc_hir_analysis::hir_ty_lowering::RegionInferReason::Param(param),
-                        )
-                        .into(),
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        if !infer_args && let Some(default) = param.default_value(tcx) {
-                            // If we have a default, then it doesn't matter that we're not inferring
-                            // the type/const arguments: We provide the default where any is missing.
-                            return default.instantiate(tcx, preceding_args);
-                        }
-                        // If no type/const arguments were provided, we have to infer them.
-                        // This case also occurs as a result of some malformed input, e.g.,
-                        // a lifetime argument being given instead of a type/const parameter.
-                        // Using inference instead of `Error` gives better error messages.
-                        self.fcx.var_for_def(self.span, param)
-                    }
+                if !infer_args && let Some(default) = param.default_value(tcx) {
+                    // If we have a default, then it doesn't matter that we're not inferring
+                    // the type/const arguments: We provide the default where any is missing.
+                    return default.instantiate(tcx, preceding_args);
                 }
+                // If no type/const arguments were provided, we have to infer them.
+                // This case also occurs as a result of some malformed input, e.g.,
+                // a lifetime argument being given instead of a type/const parameter.
+                // Using inference instead of `Error` gives better error messages.
+                self.fcx.var_for_def(self.span, param)
             }
         }
 
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 3caaa7f9a9d..c5000171ad7 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -863,7 +863,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         Resolver { fcx, span, body, nested_goals, should_normalize }
     }
 
-    fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
+    fn report_error(&self, p: impl Into<ty::Term<'tcx>>) -> ErrorGuaranteed {
         if let Some(guar) = self.fcx.tainted_by_errors() {
             guar
         } else {
@@ -887,7 +887,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         new_err: impl Fn(TyCtxt<'tcx>, ErrorGuaranteed) -> T,
     ) -> T
     where
-        T: Into<ty::GenericArg<'tcx>> + TypeSuperFoldable<TyCtxt<'tcx>> + Copy,
+        T: Into<ty::Term<'tcx>> + TypeSuperFoldable<TyCtxt<'tcx>> + Copy,
     {
         let tcx = self.fcx.tcx;
         // We must deeply normalize in the new solver, since later lints expect
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c4698e5cbb4..d25542dadd5 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -31,9 +31,9 @@ use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{
     self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
-    GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt,
-    TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv,
-    TypingMode, fold_regions,
+    GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Term, TermKind,
+    Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+    TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
 };
 use rustc_span::{Span, Symbol};
 use snapshot::undo_log::InferCtxtUndoLogs;
@@ -1401,6 +1401,16 @@ impl<'tcx> TyOrConstInferVar {
         }
     }
 
+    /// Tries to extract an inference variable from a type or a constant, returns `None`
+    /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
+    /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
+    pub fn maybe_from_term(term: Term<'tcx>) -> Option<Self> {
+        match term.unpack() {
+            TermKind::Ty(ty) => Self::maybe_from_ty(ty),
+            TermKind::Const(ct) => Self::maybe_from_const(ct),
+        }
+    }
+
     /// Tries to extract an inference variable from a type, returns `None`
     /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`).
     fn maybe_from_ty(ty: Ty<'tcx>) -> Option<Self> {
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 8de64b3bfac..542c0b3e6eb 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -250,17 +250,17 @@ impl<'tcx> GenericArg<'tcx> {
     }
 
     #[inline]
-    pub fn as_type(self) -> Option<Ty<'tcx>> {
+    pub fn as_region(self) -> Option<ty::Region<'tcx>> {
         match self.unpack() {
-            GenericArgKind::Type(ty) => Some(ty),
+            GenericArgKind::Lifetime(re) => Some(re),
             _ => None,
         }
     }
 
     #[inline]
-    pub fn as_region(self) -> Option<ty::Region<'tcx>> {
+    pub fn as_type(self) -> Option<Ty<'tcx>> {
         match self.unpack() {
-            GenericArgKind::Lifetime(re) => Some(re),
+            GenericArgKind::Type(ty) => Some(ty),
             _ => None,
         }
     }
@@ -273,6 +273,15 @@ impl<'tcx> GenericArg<'tcx> {
         }
     }
 
+    #[inline]
+    pub fn as_term(self) -> Option<ty::Term<'tcx>> {
+        match self.unpack() {
+            GenericArgKind::Lifetime(_) => None,
+            GenericArgKind::Type(ty) => Some(ty.into()),
+            GenericArgKind::Const(ct) => Some(ct.into()),
+        }
+    }
+
     /// Unpack the `GenericArg` as a region when it is known certainly to be a region.
     pub fn expect_region(self) -> ty::Region<'tcx> {
         self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind"))
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3698cfb9870..be00c0e116d 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -110,6 +110,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder};
 pub use crate::ty::diagnostics::*;
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::util::Discr;
+use crate::ty::walk::TypeWalker;
 
 pub mod abstract_const;
 pub mod adjustment;
@@ -631,6 +632,20 @@ impl<'tcx> Term<'tcx> {
             TermKind::Const(ct) => ct.is_ct_infer(),
         }
     }
+
+    /// Iterator that walks `self` and any types reachable from
+    /// `self`, in depth-first order. Note that just walks the types
+    /// that appear in `self`, it does not descend into the fields of
+    /// structs or variants. For example:
+    ///
+    /// ```text
+    /// isize => { isize }
+    /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+    /// [isize] => { [isize], isize }
+    /// ```
+    pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
+        TypeWalker::new(self.into())
+    }
 }
 
 const TAG_MASK: usize = 0b11;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index d739218af5e..1df3bff5244 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3247,7 +3247,7 @@ define_print! {
             ty::ClauseKind::ConstArgHasType(ct, ty) => {
                 p!("the constant `", print(ct), "` has type `", print(ty), "`")
             },
-            ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"),
+            ty::ClauseKind::WellFormed(term) => p!(print(term), " well-formed"),
             ty::ClauseKind::ConstEvaluatable(ct) => {
                 p!("the constant `", print(ct), "` can be evaluated")
             }
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index c4b6b18c45d..25493970a0c 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -36,7 +36,7 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
     fn well_formed_goals(
         &self,
         param_env: <Self::Interner as Interner>::ParamEnv,
-        arg: <Self::Interner as Interner>::GenericArg,
+        term: <Self::Interner as Interner>::Term,
     ) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>;
 
     fn clone_opaque_types_for_query_response(
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 19fb2b00fcb..6dd554299a6 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
@@ -529,8 +529,8 @@ where
                 ty::PredicateKind::DynCompatible(trait_def_id) => {
                     self.compute_dyn_compatible_goal(trait_def_id)
                 }
-                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                    self.compute_well_formed_goal(Goal { param_env, predicate: arg })
+                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
+                    self.compute_well_formed_goal(Goal { param_env, predicate: term })
                 }
                 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
                     self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
@@ -1008,9 +1008,9 @@ where
     pub(super) fn well_formed_goals(
         &self,
         param_env: I::ParamEnv,
-        arg: I::GenericArg,
+        term: I::Term,
     ) -> Option<Vec<Goal<I, I::Predicate>>> {
-        self.delegate.well_formed_goals(param_env, arg)
+        self.delegate.well_formed_goals(param_env, term)
     }
 
     pub(super) fn trait_ref_is_knowable(
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index d9cf84787a0..c9f4fc649b5 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -137,7 +137,7 @@ where
     }
 
     #[instrument(level = "trace", skip(self))]
-    fn compute_well_formed_goal(&mut self, goal: Goal<I, I::GenericArg>) -> QueryResult<I> {
+    fn compute_well_formed_goal(&mut self, goal: Goal<I, I::Term>) -> QueryResult<I> {
         match self.well_formed_goals(goal.param_env, goal.predicate) {
             Some(goals) => {
                 self.add_goals(GoalSource::Misc, goals);
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 0bde289c85f..b56f3e1971c 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -157,7 +157,7 @@ where
                 ty.visit_with(self)
             }
             ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
-            ty::ClauseKind::WellFormed(arg) => arg.visit_with(self),
+            ty::ClauseKind::WellFormed(term) => term.visit_with(self),
         }
     }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index a757329bcf2..c0ed3b90eb4 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -638,8 +638,8 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
                 const_.stable(tables),
                 ty.stable(tables),
             ),
-            ClauseKind::WellFormed(generic_arg) => {
-                stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables))
+            ClauseKind::WellFormed(term) => {
+                stable_mir::ty::ClauseKind::WellFormed(term.unpack().stable(tables))
             }
             ClauseKind::ConstEvaluatable(const_) => {
                 stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 4b153007bd8..0ac9a0fb647 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1462,7 +1462,7 @@ pub enum ClauseKind {
     TypeOutlives(TypeOutlivesPredicate),
     Projection(ProjectionPredicate),
     ConstArgHasType(TyConst, Ty),
-    WellFormed(GenericArgKind),
+    WellFormed(TermKind),
     ConstEvaluatable(TyConst),
 }
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index f45e3904212..eba195cb99c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -14,8 +14,8 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{
-    self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt,
-    TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
+    self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind,
+    Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
 };
 use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym};
 use rustc_type_ir::TypeVisitableExt;
@@ -344,12 +344,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// which were stuck during inference.
     pub fn extract_inference_diagnostics_data(
         &self,
-        arg: GenericArg<'tcx>,
+        term: Term<'tcx>,
         highlight: ty::print::RegionHighlightMode<'tcx>,
     ) -> InferenceDiagnosticsData {
         let tcx = self.tcx;
-        match arg.unpack() {
-            GenericArgKind::Type(ty) => {
+        match term.unpack() {
+            TermKind::Ty(ty) => {
                 if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
                     let var_origin = self.infcx.type_var_origin(ty_vid);
                     if let Some(def_id) = var_origin.param_def_id
@@ -375,7 +375,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     parent: None,
                 }
             }
-            GenericArgKind::Const(ct) => {
+            TermKind::Const(ct) => {
                 if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
                     let origin = self.const_var_origin(vid).expect("expected unresolved const var");
                     if let Some(def_id) = origin.param_def_id {
@@ -411,7 +411,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     }
                 }
             }
-            GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
         }
     }
 
@@ -472,13 +471,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         &self,
         body_def_id: LocalDefId,
         failure_span: Span,
-        arg: GenericArg<'tcx>,
+        term: Term<'tcx>,
         error_code: TypeAnnotationNeeded,
         should_label_span: bool,
     ) -> Diag<'a> {
-        let arg = self.resolve_vars_if_possible(arg);
-        let arg_data =
-            self.extract_inference_diagnostics_data(arg, ty::print::RegionHighlightMode::default());
+        let term = self.resolve_vars_if_possible(term);
+        let arg_data = self
+            .extract_inference_diagnostics_data(term, ty::print::RegionHighlightMode::default());
 
         let Some(typeck_results) = &self.typeck_results else {
             // If we don't have any typeck results we're outside
@@ -487,7 +486,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
-        let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
+        let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term);
         if let Some(body) = self.tcx.hir_maybe_body_owned_by(
             self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
         ) {
@@ -542,7 +541,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 have_turbofish,
             } => {
                 let generics = self.tcx.generics_of(generics_def_id);
-                let is_type = matches!(arg.unpack(), GenericArgKind::Type(_));
+                let is_type = term.as_type().is_some();
 
                 let (parent_exists, parent_prefix, parent_name) =
                     InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id)
@@ -811,7 +810,7 @@ struct FindInferSourceVisitor<'a, 'tcx> {
     tecx: &'a TypeErrCtxt<'a, 'tcx>,
     typeck_results: &'a TypeckResults<'tcx>,
 
-    target: GenericArg<'tcx>,
+    target: Term<'tcx>,
 
     attempt: usize,
     infer_source_cost: usize,
@@ -822,7 +821,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
     fn new(
         tecx: &'a TypeErrCtxt<'a, 'tcx>,
         typeck_results: &'a TypeckResults<'tcx>,
-        target: GenericArg<'tcx>,
+        target: Term<'tcx>,
     ) -> Self {
         FindInferSourceVisitor {
             tecx,
@@ -938,12 +937,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
     // Check whether this generic argument is the inference variable we
     // are looking for.
     fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool {
-        if arg == self.target {
+        if arg == self.target.into() {
             return true;
         }
 
         match (arg.unpack(), self.target.unpack()) {
-            (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
+            (GenericArgKind::Type(inner_ty), TermKind::Ty(target_ty)) => {
                 use ty::{Infer, TyVar};
                 match (inner_ty.kind(), target_ty.kind()) {
                     (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
@@ -952,7 +951,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                     _ => false,
                 }
             }
-            (GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => {
+            (GenericArgKind::Const(inner_ct), TermKind::Const(target_ct)) => {
                 use ty::InferConst::*;
                 match (inner_ct.kind(), target_ct.kind()) {
                     (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index 54b50851b74..275b580d794 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -228,13 +228,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 // Pick the first generic parameter that still contains inference variables as the one
                 // we're going to emit an error for. If there are none (see above), fall back to
                 // a more general error.
-                let arg = data.trait_ref.args.iter().find(|s| s.has_non_region_infer());
+                let term = data
+                    .trait_ref
+                    .args
+                    .iter()
+                    .filter_map(ty::GenericArg::as_term)
+                    .find(|s| s.has_non_region_infer());
 
-                let mut err = if let Some(arg) = arg {
+                let mut err = if let Some(term) = term {
                     self.emit_inference_failure_err(
                         obligation.cause.body_id,
                         span,
-                        arg,
+                        term,
                         TypeAnnotationNeeded::E0283,
                         true,
                     )
@@ -276,7 +281,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
                 if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
                     if let Some(e) = self.tainted_by_errors()
-                        && arg.is_none()
+                        && term.is_none()
                     {
                         // If `arg.is_none()`, then this is probably two param-env
                         // candidates or impl candidates that are equal modulo lifetimes.
@@ -313,7 +318,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id());
                 }
 
-                if let Some(ty::GenericArgKind::Type(_)) = arg.map(|arg| arg.unpack())
+                if term.is_some_and(|term| term.as_type().is_some())
                     && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id)
                 {
                     let mut expr_finder = FindExprBySpan::new(span, self.tcx);
@@ -464,11 +469,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 err
             }
 
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
 
-                if let Err(e) = arg.error_reported() {
+                if let Err(e) = term.error_reported() {
                     return e;
                 }
                 if let Some(e) = self.tainted_by_errors() {
@@ -478,7 +483,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 self.emit_inference_failure_err(
                     obligation.cause.body_id,
                     span,
-                    arg,
+                    term,
                     TypeAnnotationNeeded::E0282,
                     false,
                 )
@@ -519,18 +524,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     // other `Foo` impls are incoherent.
                     return guar;
                 }
-                let arg = data
+                let term = data
                     .projection_term
                     .args
                     .iter()
-                    .chain(Some(data.term.into_arg()))
+                    .filter_map(ty::GenericArg::as_term)
+                    .chain([data.term])
                     .find(|g| g.has_non_region_infer());
                 let predicate = self.tcx.short_string(predicate, &mut file);
-                if let Some(arg) = arg {
+                if let Some(term) = term {
                     self.emit_inference_failure_err(
                         obligation.cause.body_id,
                         span,
-                        arg,
+                        term,
                         TypeAnnotationNeeded::E0284,
                         true,
                     )
@@ -554,12 +560,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
                 }
-                let arg = data.walk().find(|g| g.is_non_region_infer());
-                if let Some(arg) = arg {
+                let term =
+                    data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
+                if let Some(term) = term {
                     let err = self.emit_inference_failure_err(
                         obligation.cause.body_id,
                         span,
-                        arg,
+                        term,
                         TypeAnnotationNeeded::E0284,
                         true,
                     );
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 4330f1f2292..d8e05d9ad97 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -813,38 +813,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
         mut trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Option<ErrorGuaranteed> {
-        // If `AsyncFnKindHelper` is not implemented, that means that the closure kind
-        // doesn't extend the goal kind. This is worth reporting, but we can only do so
-        // if we actually know which closure this goal comes from, so look at the cause
-        // to see if we can extract that information.
-        if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::AsyncFnKindHelper)
-            && let Some(found_kind) =
-                trait_pred.skip_binder().trait_ref.args.type_at(0).to_opt_closure_kind()
-            && let Some(expected_kind) =
-                trait_pred.skip_binder().trait_ref.args.type_at(1).to_opt_closure_kind()
-            && !found_kind.extends(expected_kind)
-        {
-            if let Some((_, Some(parent))) = obligation.cause.code().parent_with_predicate() {
-                // If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
+        // If we end up on an `AsyncFnKindHelper` goal, try to unwrap the parent
+        // `AsyncFn*` goal.
+        if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::AsyncFnKindHelper) {
+            let mut code = obligation.cause.code();
+            // Unwrap a `FunctionArg` cause, which has been refined from a derived obligation.
+            if let ObligationCauseCode::FunctionArg { parent_code, .. } = code {
+                code = &**parent_code;
+            }
+            // If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
+            if let Some((_, Some(parent))) = code.parent_with_predicate() {
                 trait_pred = parent;
-            } else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } =
-                obligation.cause.code()
-                && let Some(typeck_results) = &self.typeck_results
-                && let ty::Closure(closure_def_id, _) | ty::CoroutineClosure(closure_def_id, _) =
-                    *typeck_results.node_type(arg_hir_id).kind()
-            {
-                // Otherwise, extract the closure kind from the obligation,
-                // but only if we actually have an argument to deduce the
-                // closure type from...
-                let mut err = self.report_closure_error(
-                    &obligation,
-                    closure_def_id,
-                    found_kind,
-                    expected_kind,
-                    "Async",
-                );
-                self.note_obligation_cause(&mut err, &obligation);
-                return Some(err.emit());
             }
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index e0b425fa739..a87c5ad6db9 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -92,12 +92,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
     fn well_formed_goals(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        arg: ty::GenericArg<'tcx>,
+        term: ty::Term<'tcx>,
     ) -> Option<Vec<Goal<'tcx, ty::Predicate<'tcx>>>> {
-        crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID)
-            .map(|obligations| {
-                obligations.into_iter().map(|obligation| obligation.as_goal()).collect()
-            })
+        crate::traits::wf::unnormalized_obligations(
+            &self.0,
+            param_env,
+            term,
+            DUMMY_SP,
+            CRATE_DEF_ID,
+        )
+        .map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect())
     }
 
     fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index f6c650c68c0..a024f432450 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -241,13 +241,13 @@ impl<'tcx> BestObligation<'tcx> {
     fn visit_well_formed_goal(
         &mut self,
         candidate: &inspect::InspectCandidate<'_, 'tcx>,
-        arg: ty::GenericArg<'tcx>,
+        term: ty::Term<'tcx>,
     ) -> ControlFlow<PredicateObligation<'tcx>> {
         let infcx = candidate.goal().infcx();
         let param_env = candidate.goal().goal().param_env;
         let body_id = self.obligation.cause.body_id;
 
-        for obligation in wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id)
+        for obligation in wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_id)
             .into_iter()
             .flatten()
         {
@@ -443,8 +443,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                     polarity: ty::PredicatePolarity::Positive,
                 }))
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                return self.visit_well_formed_goal(candidate, arg);
+            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
+                return self.visit_well_formed_goal(candidate, term);
             }
             _ => ChildMode::PassThrough,
         };
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index a11f8d3a9ec..34c3c905bd9 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -540,18 +540,18 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation, false);
                 }
 
-                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
                     match wf::obligations(
                         self.selcx.infcx,
                         obligation.param_env,
                         obligation.cause.body_id,
                         obligation.recursion_depth + 1,
-                        arg,
+                        term,
                         obligation.cause.span,
                     ) {
                         None => {
                             pending_obligation.stalled_on =
-                                vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()];
+                                vec![TyOrConstInferVar::maybe_from_term(term).unwrap()];
                             ProcessResult::Unchanged
                         }
                         Some(os) => ProcessResult::Changed(mk_pending(obligation, os)),
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index f059bd00768..81b5a131a32 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -131,12 +131,12 @@ fn relate_mir_and_user_args<'tcx>(
     //     const CONST: () = { /* arbitrary code that depends on T being WF */ };
     // }
     // ```
-    for arg in args {
+    for term in args.iter().filter_map(ty::GenericArg::as_term) {
         ocx.register_obligation(Obligation::new(
             tcx,
             cause.clone(),
             param_env,
-            ty::ClauseKind::WellFormed(arg),
+            ty::ClauseKind::WellFormed(term),
         ));
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index f98529860ff..1df69932c64 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -113,8 +113,8 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
                 | ty::PredicateKind::AliasRelate(..) => {}
 
                 // We need to search through *all* WellFormed predicates
-                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                    wf_args.push(arg);
+                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
+                    wf_args.push(term);
                 }
 
                 // We need to register region relationships
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 87fc532adaf..18971c47831 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -19,10 +19,10 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
             return Some(());
         }
 
-        if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) =
+        if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) =
             key.value.predicate.kind().skip_binder()
         {
-            match arg.as_type()?.kind() {
+            match term.as_type()?.kind() {
                 ty::Param(_)
                 | ty::Bool
                 | ty::Char
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index c7ce13c8014..89febd6ce3d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -658,7 +658,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
                 }
 
-                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
                     // So, there is a bit going on here. First, `WellFormed` predicates
                     // are coinductive, like trait predicates with auto traits.
                     // This means that we need to detect if we have recursively
@@ -682,11 +682,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let cache = previous_stack.cache;
                     let dfn = cache.next_dfn();
 
-                    for stack_arg in previous_stack.cache.wf_args.borrow().iter().rev() {
-                        if stack_arg.0 != arg {
+                    for stack_term in previous_stack.cache.wf_args.borrow().iter().rev() {
+                        if stack_term.0 != term {
                             continue;
                         }
-                        debug!("WellFormed({:?}) on stack", arg);
+                        debug!("WellFormed({:?}) on stack", term);
                         if let Some(stack) = previous_stack.head {
                             // Okay, let's imagine we have two different stacks:
                             //   `T: NonAutoTrait -> WF(T) -> T: NonAutoTrait`
@@ -702,11 +702,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             // would contain `(T, 1)`. We want to check all
                             // trait predicates greater than `1`. The previous
                             // stack would be `T: Auto`.
-                            let cycle = stack.iter().take_while(|s| s.depth > stack_arg.1);
+                            let cycle = stack.iter().take_while(|s| s.depth > stack_term.1);
                             let tcx = self.tcx();
                             let cycle = cycle.map(|stack| stack.obligation.predicate.upcast(tcx));
                             if self.coinductive_match(cycle) {
-                                stack.update_reached_depth(stack_arg.1);
+                                stack.update_reached_depth(stack_term.1);
                                 return Ok(EvaluatedToOk);
                             } else {
                                 return Ok(EvaluatedToAmbigStackDependent);
@@ -720,11 +720,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         obligation.param_env,
                         obligation.cause.body_id,
                         obligation.recursion_depth + 1,
-                        arg,
+                        term,
                         obligation.cause.span,
                     ) {
                         Some(obligations) => {
-                            cache.wf_args.borrow_mut().push((arg, previous_stack.depth()));
+                            cache.wf_args.borrow_mut().push((term, previous_stack.depth()));
                             let result =
                                 self.evaluate_predicates_recursively(previous_stack, obligations);
                             cache.wf_args.borrow_mut().pop();
@@ -2969,14 +2969,14 @@ struct ProvisionalEvaluationCache<'tcx> {
     ///   means the cached value for `F`.
     map: RefCell<FxIndexMap<ty::PolyTraitPredicate<'tcx>, ProvisionalEvaluation>>,
 
-    /// The stack of args that we assume to be true because a `WF(arg)` predicate
+    /// The stack of terms that we assume to be well-formed because a `WF(term)` predicate
     /// is on the stack above (and because of wellformedness is coinductive).
     /// In an "ideal" world, this would share a stack with trait predicates in
     /// `TraitObligationStack`. However, trait predicates are *much* hotter than
     /// `WellFormed` predicates, and it's very likely that the additional matches
     /// will have a perf effect. The value here is the well-formed `GenericArg`
     /// and the depth of the trait predicate *above* that well-formed predicate.
-    wf_args: RefCell<Vec<(ty::GenericArg<'tcx>, usize)>>,
+    wf_args: RefCell<Vec<(ty::Term<'tcx>, usize)>>,
 }
 
 /// A cache value for the provisional cache: contains the depth-first
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index cad7e42fd82..62bd8e1af05 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -10,8 +10,8 @@ use rustc_hir::lang_items::LangItem;
 use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
 use rustc_middle::bug;
 use rustc_middle::ty::{
-    self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self, GenericArgsRef, Term, TermKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+    TypeVisitableExt, TypeVisitor,
 };
 use rustc_session::parse::feature_err;
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -32,12 +32,12 @@ pub fn obligations<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     body_id: LocalDefId,
     recursion_depth: usize,
-    arg: GenericArg<'tcx>,
+    term: Term<'tcx>,
     span: Span,
 ) -> Option<PredicateObligations<'tcx>> {
     // Handle the "cycle" case (see comment above) by bailing out if necessary.
-    let arg = match arg.unpack() {
-        GenericArgKind::Type(ty) => {
+    let term = match term.unpack() {
+        TermKind::Ty(ty) => {
             match ty.kind() {
                 ty::Infer(ty::TyVar(_)) => {
                     let resolved_ty = infcx.shallow_resolve(ty);
@@ -52,7 +52,7 @@ pub fn obligations<'tcx>(
             }
             .into()
         }
-        GenericArgKind::Const(ct) => {
+        TermKind::Const(ct) => {
             match ct.kind() {
                 ty::ConstKind::Infer(_) => {
                     let resolved = infcx.shallow_resolve_const(ct);
@@ -67,8 +67,6 @@ pub fn obligations<'tcx>(
             }
             .into()
         }
-        // There is nothing we have to do for lifetimes.
-        GenericArgKind::Lifetime(..) => return Some(PredicateObligations::new()),
     };
 
     let mut wf = WfPredicates {
@@ -80,11 +78,11 @@ pub fn obligations<'tcx>(
         recursion_depth,
         item: None,
     };
-    wf.add_wf_preds_for_generic_arg(arg);
-    debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
+    wf.add_wf_preds_for_term(term);
+    debug!("wf::obligations({:?}, body_id={:?}) = {:?}", term, body_id, wf.out);
 
     let result = wf.normalize(infcx);
-    debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", arg, body_id, result);
+    debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", term, body_id, result);
     Some(result)
 }
 
@@ -95,23 +93,19 @@ pub fn obligations<'tcx>(
 pub fn unnormalized_obligations<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    arg: GenericArg<'tcx>,
+    term: Term<'tcx>,
     span: Span,
     body_id: LocalDefId,
 ) -> Option<PredicateObligations<'tcx>> {
-    debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
+    debug_assert_eq!(term, infcx.resolve_vars_if_possible(term));
 
     // However, if `arg` IS an unresolved inference variable, returns `None`,
     // because we are not able to make any progress at all. This is to prevent
     // cycles where we say "?0 is WF if ?0 is WF".
-    if arg.is_non_region_infer() {
+    if term.is_infer() {
         return None;
     }
 
-    if let ty::GenericArgKind::Lifetime(..) = arg.unpack() {
-        return Some(PredicateObligations::new());
-    }
-
     let mut wf = WfPredicates {
         infcx,
         param_env,
@@ -121,7 +115,7 @@ pub fn unnormalized_obligations<'tcx>(
         recursion_depth: 0,
         item: None,
     };
-    wf.add_wf_preds_for_generic_arg(arg);
+    wf.add_wf_preds_for_term(term);
     Some(wf.out)
 }
 
@@ -185,22 +179,22 @@ pub fn clause_obligations<'tcx>(
         }
         ty::ClauseKind::RegionOutlives(..) => {}
         ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
-            wf.add_wf_preds_for_generic_arg(ty.into());
+            wf.add_wf_preds_for_term(ty.into());
         }
         ty::ClauseKind::Projection(t) => {
             wf.add_wf_preds_for_alias_term(t.projection_term);
-            wf.add_wf_preds_for_generic_arg(t.term.into_arg());
+            wf.add_wf_preds_for_term(t.term);
         }
         ty::ClauseKind::ConstArgHasType(ct, ty) => {
-            wf.add_wf_preds_for_generic_arg(ct.into());
-            wf.add_wf_preds_for_generic_arg(ty.into());
+            wf.add_wf_preds_for_term(ct.into());
+            wf.add_wf_preds_for_term(ty.into());
         }
-        ty::ClauseKind::WellFormed(arg) => {
-            wf.add_wf_preds_for_generic_arg(arg);
+        ty::ClauseKind::WellFormed(term) => {
+            wf.add_wf_preds_for_term(term);
         }
 
         ty::ClauseKind::ConstEvaluatable(ct) => {
-            wf.add_wf_preds_for_generic_arg(ct.into());
+            wf.add_wf_preds_for_term(ct.into());
         }
     }
 
@@ -426,11 +420,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 .args
                 .iter()
                 .enumerate()
-                .filter(|(_, arg)| {
-                    matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
-                })
-                .filter(|(_, arg)| !arg.has_escaping_bound_vars())
-                .map(|(i, arg)| {
+                .filter_map(|(i, arg)| arg.as_term().map(|t| (i, t)))
+                .filter(|(_, term)| !term.has_escaping_bound_vars())
+                .map(|(i, term)| {
                     let mut cause = traits::ObligationCause::misc(self.span, self.body_id);
                     // The first arg is the self ty - use the correct span for it.
                     if i == 0 {
@@ -445,9 +437,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                         cause,
                         depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
-                            arg,
-                        ))),
+                        ty::ClauseKind::WellFormed(term),
                     )
                 }),
         );
@@ -457,7 +447,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     // given that it is a *negative* trait predicate.
     fn add_wf_preds_for_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
         for arg in trait_ref.args {
-            self.add_wf_preds_for_generic_arg(arg);
+            if let Some(term) = arg.as_term() {
+                self.add_wf_preds_for_term(term);
+            }
         }
     }
 
@@ -529,19 +521,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
         self.out.extend(
             args.iter()
-                .filter(|arg| {
-                    matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
-                })
-                .filter(|arg| !arg.has_escaping_bound_vars())
-                .map(|arg| {
+                .filter_map(|arg| arg.as_term())
+                .filter(|term| !term.has_escaping_bound_vars())
+                .map(|term| {
                     traits::Obligation::with_depth(
                         tcx,
                         cause.clone(),
                         depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
-                            arg,
-                        ))),
+                        ty::ClauseKind::WellFormed(term),
                     )
                 }),
         );
@@ -565,10 +553,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         }
     }
 
-    /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
+    /// Pushes all the predicates needed to validate that `term` is WF into `out`.
     #[instrument(level = "debug", skip(self))]
-    fn add_wf_preds_for_generic_arg(&mut self, arg: GenericArg<'tcx>) {
-        arg.visit_with(self);
+    fn add_wf_preds_for_term(&mut self, term: Term<'tcx>) {
+        term.visit_with(self);
         debug!(?self.out);
     }
 
diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs
index d555ea702a9..4d5f630ae22 100644
--- a/compiler/rustc_transmute/src/layout/mod.rs
+++ b/compiler/rustc_transmute/src/layout/mod.rs
@@ -65,7 +65,12 @@ impl fmt::Debug for Byte {
     }
 }
 
-#[cfg(test)]
+impl From<RangeInclusive<u8>> for Byte {
+    fn from(src: RangeInclusive<u8>) -> Self {
+        Self::new(src)
+    }
+}
+
 impl From<u8> for Byte {
     fn from(src: u8) -> Self {
         Self::from_val(src)
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 6a09be18ef9..7cf712ce9e9 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -1,4 +1,4 @@
-use std::ops::ControlFlow;
+use std::ops::{ControlFlow, RangeInclusive};
 
 use super::{Byte, Def, Ref};
 
@@ -32,6 +32,22 @@ where
     Byte(Byte),
 }
 
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub(crate) enum Endian {
+    Little,
+    Big,
+}
+
+#[cfg(feature = "rustc")]
+impl From<rustc_abi::Endian> for Endian {
+    fn from(order: rustc_abi::Endian) -> Endian {
+        match order {
+            rustc_abi::Endian::Little => Endian::Little,
+            rustc_abi::Endian::Big => Endian::Big,
+        }
+    }
+}
+
 impl<D, R> Tree<D, R>
 where
     D: Def,
@@ -59,22 +75,60 @@ where
 
     /// A `Tree` representing the layout of `bool`.
     pub(crate) fn bool() -> Self {
-        Self::Byte(Byte::new(0x00..=0x01))
+        Self::byte(0x00..=0x01)
     }
 
     /// A `Tree` whose layout matches that of a `u8`.
     pub(crate) fn u8() -> Self {
-        Self::Byte(Byte::new(0x00..=0xFF))
+        Self::byte(0x00..=0xFF)
+    }
+
+    /// A `Tree` whose layout matches that of a `char`.
+    pub(crate) fn char(order: Endian) -> Self {
+        // `char`s can be in the following ranges:
+        // - [0, 0xD7FF]
+        // - [0xE000, 10FFFF]
+        //
+        // All other `char` values are illegal. We can thus represent a `char`
+        // as a union of three possible layouts:
+        // - 00 00 [00, D7] XX
+        // - 00 00 [E0, FF] XX
+        // - 00 [01, 10] XX XX
+
+        const _0: RangeInclusive<u8> = 0..=0;
+        const BYTE: RangeInclusive<u8> = 0x00..=0xFF;
+        let x = Self::from_big_endian(order, [_0, _0, 0x00..=0xD7, BYTE]);
+        let y = Self::from_big_endian(order, [_0, _0, 0xE0..=0xFF, BYTE]);
+        let z = Self::from_big_endian(order, [_0, 0x01..=0x10, BYTE, BYTE]);
+        Self::alt([x, y, z])
     }
 
-    /// A `Tree` whose layout accepts exactly the given bit pattern.
-    pub(crate) fn from_bits(bits: u8) -> Self {
-        Self::Byte(Byte::from_val(bits))
+    /// A `Tree` whose layout matches `std::num::NonZeroXxx`.
+    #[allow(dead_code)]
+    pub(crate) fn nonzero(width_in_bytes: u64) -> Self {
+        const BYTE: RangeInclusive<u8> = 0x00..=0xFF;
+        const NONZERO: RangeInclusive<u8> = 0x01..=0xFF;
+
+        (0..width_in_bytes)
+            .map(|nz_idx| {
+                (0..width_in_bytes)
+                    .map(|pos| Self::byte(if pos == nz_idx { NONZERO } else { BYTE }))
+                    .fold(Self::unit(), Self::then)
+            })
+            .fold(Self::uninhabited(), Self::or)
+    }
+
+    pub(crate) fn bytes<const N: usize, B: Into<Byte>>(bytes: [B; N]) -> Self {
+        Self::seq(bytes.map(B::into).map(Self::Byte))
+    }
+
+    pub(crate) fn byte(byte: impl Into<Byte>) -> Self {
+        Self::Byte(byte.into())
     }
 
     /// A `Tree` whose layout is a number of the given width.
-    pub(crate) fn number(width_in_bytes: usize) -> Self {
-        Self::Seq(vec![Self::u8(); width_in_bytes])
+    pub(crate) fn number(width_in_bytes: u64) -> Self {
+        Self::Seq(vec![Self::u8(); width_in_bytes.try_into().unwrap()])
     }
 
     /// A `Tree` whose layout is entirely padding of the given width.
@@ -125,13 +179,35 @@ where
             Self::Byte(..) | Self::Ref(..) | Self::Def(..) => true,
         }
     }
-}
 
-impl<D, R> Tree<D, R>
-where
-    D: Def,
-    R: Ref,
-{
+    /// Produces a `Tree` which represents a sequence of bytes stored in
+    /// `order`.
+    ///
+    /// `bytes` is taken to be in big-endian byte order, and its order will be
+    /// swapped if `order == Endian::Little`.
+    pub(crate) fn from_big_endian<const N: usize, B: Into<Byte>>(
+        order: Endian,
+        mut bytes: [B; N],
+    ) -> Self {
+        if order == Endian::Little {
+            (&mut bytes[..]).reverse();
+        }
+
+        Self::bytes(bytes)
+    }
+
+    /// Produces a `Tree` where each of the trees in `trees` are sequenced one
+    /// after another.
+    pub(crate) fn seq<const N: usize>(trees: [Tree<D, R>; N]) -> Self {
+        trees.into_iter().fold(Tree::unit(), Self::then)
+    }
+
+    /// Produces a `Tree` where each of the trees in `trees` are accepted as
+    /// alternative layouts.
+    pub(crate) fn alt<const N: usize>(trees: [Tree<D, R>; N]) -> Self {
+        trees.into_iter().fold(Tree::uninhabited(), Self::or)
+    }
+
     /// Produces a new `Tree` where `other` is sequenced after `self`.
     pub(crate) fn then(self, other: Self) -> Self {
         match (self, other) {
@@ -222,17 +298,17 @@ pub(crate) mod rustc {
 
                 ty::Float(nty) => {
                     let width = nty.bit_width() / 8;
-                    Ok(Self::number(width as _))
+                    Ok(Self::number(width.try_into().unwrap()))
                 }
 
                 ty::Int(nty) => {
                     let width = nty.normalize(pointer_size.bits() as _).bit_width().unwrap() / 8;
-                    Ok(Self::number(width as _))
+                    Ok(Self::number(width.try_into().unwrap()))
                 }
 
                 ty::Uint(nty) => {
                     let width = nty.normalize(pointer_size.bits() as _).bit_width().unwrap() / 8;
-                    Ok(Self::number(width as _))
+                    Ok(Self::number(width.try_into().unwrap()))
                 }
 
                 ty::Tuple(members) => Self::from_tuple((ty, layout), members, cx),
@@ -249,11 +325,33 @@ pub(crate) mod rustc {
                         .fold(Tree::unit(), |tree, elt| tree.then(elt)))
                 }
 
-                ty::Adt(adt_def, _args_ref) if !ty.is_box() => match adt_def.adt_kind() {
-                    AdtKind::Struct => Self::from_struct((ty, layout), *adt_def, cx),
-                    AdtKind::Enum => Self::from_enum((ty, layout), *adt_def, cx),
-                    AdtKind::Union => Self::from_union((ty, layout), *adt_def, cx),
-                },
+                ty::Adt(adt_def, _args_ref) if !ty.is_box() => {
+                    let (lo, hi) = cx.tcx().layout_scalar_valid_range(adt_def.did());
+
+                    use core::ops::Bound::*;
+                    let is_transparent = adt_def.repr().transparent();
+                    match (adt_def.adt_kind(), lo, hi) {
+                        (AdtKind::Struct, Unbounded, Unbounded) => {
+                            Self::from_struct((ty, layout), *adt_def, cx)
+                        }
+                        (AdtKind::Struct, Included(1), Included(_hi)) if is_transparent => {
+                            // FIXME(@joshlf): Support `NonZero` types:
+                            // - Check to make sure that the first field is
+                            //   numerical
+                            // - Check to make sure that the upper bound is the
+                            //   maximum value for the field's type
+                            // - Construct `Self::nonzero`
+                            Err(Err::NotYetSupported)
+                        }
+                        (AdtKind::Enum, Unbounded, Unbounded) => {
+                            Self::from_enum((ty, layout), *adt_def, cx)
+                        }
+                        (AdtKind::Union, Unbounded, Unbounded) => {
+                            Self::from_union((ty, layout), *adt_def, cx)
+                        }
+                        _ => Err(Err::NotYetSupported),
+                    }
+                }
 
                 ty::Ref(lifetime, ty, mutability) => {
                     let layout = layout_of(cx, *ty)?;
@@ -268,6 +366,8 @@ pub(crate) mod rustc {
                     }))
                 }
 
+                ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
+
                 _ => Err(Err::NotYetSupported),
             }
         }
@@ -450,7 +550,7 @@ pub(crate) mod rustc {
                     &bytes[bytes.len() - size.bytes_usize()..]
                 }
             };
-            Self::Seq(bytes.iter().map(|&b| Self::from_bits(b)).collect())
+            Self::Seq(bytes.iter().map(|&b| Self::byte(b)).collect())
         }
 
         /// Constructs a `Tree` from a union.
diff --git a/compiler/rustc_transmute/src/layout/tree/tests.rs b/compiler/rustc_transmute/src/layout/tree/tests.rs
index 44f50a25c93..8c3dbbe37ab 100644
--- a/compiler/rustc_transmute/src/layout/tree/tests.rs
+++ b/compiler/rustc_transmute/src/layout/tree/tests.rs
@@ -20,23 +20,18 @@ mod prune {
 
         #[test]
         fn seq_1() {
-            let layout: Tree<Def, !> =
-                Tree::def(Def::NoSafetyInvariants).then(Tree::from_bits(0x00));
-            assert_eq!(
-                layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
-                Tree::from_bits(0x00)
-            );
+            let layout: Tree<Def, !> = Tree::def(Def::NoSafetyInvariants).then(Tree::byte(0x00));
+            assert_eq!(layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)), Tree::byte(0x00));
         }
 
         #[test]
         fn seq_2() {
-            let layout: Tree<Def, !> = Tree::from_bits(0x00)
-                .then(Tree::def(Def::NoSafetyInvariants))
-                .then(Tree::from_bits(0x01));
+            let layout: Tree<Def, !> =
+                Tree::byte(0x00).then(Tree::def(Def::NoSafetyInvariants)).then(Tree::byte(0x01));
 
             assert_eq!(
                 layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
-                Tree::from_bits(0x00).then(Tree::from_bits(0x01))
+                Tree::byte(0x00).then(Tree::byte(0x01))
             );
         }
     }
@@ -66,7 +61,7 @@ mod prune {
         #[test]
         fn invisible_def_in_seq_len_3() {
             let layout: Tree<Def, !> = Tree::def(Def::NoSafetyInvariants)
-                .then(Tree::from_bits(0x00))
+                .then(Tree::byte(0x00))
                 .then(Tree::def(Def::HasSafetyInvariants));
             assert_eq!(
                 layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
@@ -94,12 +89,9 @@ mod prune {
         #[test]
         fn visible_def_in_seq_len_3() {
             let layout: Tree<Def, !> = Tree::def(Def::NoSafetyInvariants)
-                .then(Tree::from_bits(0x00))
+                .then(Tree::byte(0x00))
                 .then(Tree::def(Def::NoSafetyInvariants));
-            assert_eq!(
-                layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
-                Tree::from_bits(0x00)
-            );
+            assert_eq!(layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)), Tree::byte(0x00));
         }
     }
 }
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
index 24e2a1acadd..992fcb7cc4c 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
@@ -177,9 +177,9 @@ mod bool {
 
     #[test]
     fn should_permit_validity_expansion_and_reject_contraction() {
-        let b0 = layout::Tree::<Def, !>::from_bits(0);
-        let b1 = layout::Tree::<Def, !>::from_bits(1);
-        let b2 = layout::Tree::<Def, !>::from_bits(2);
+        let b0 = layout::Tree::<Def, !>::byte(0);
+        let b1 = layout::Tree::<Def, !>::byte(1);
+        let b2 = layout::Tree::<Def, !>::byte(2);
 
         let alts = [b0, b1, b2];
 
@@ -279,8 +279,8 @@ mod alt {
     fn should_permit_identity_transmutation() {
         type Tree = layout::Tree<Def, !>;
 
-        let x = Tree::Seq(vec![Tree::from_bits(0), Tree::from_bits(0)]);
-        let y = Tree::Seq(vec![Tree::bool(), Tree::from_bits(1)]);
+        let x = Tree::Seq(vec![Tree::byte(0), Tree::byte(0)]);
+        let y = Tree::Seq(vec![Tree::bool(), Tree::byte(1)]);
         let layout = Tree::Alt(vec![x, y]);
 
         let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
@@ -323,6 +323,76 @@ mod union {
     }
 }
 
+mod char {
+    use super::*;
+    use crate::layout::tree::Endian;
+
+    #[test]
+    fn should_permit_valid_transmutation() {
+        for order in [Endian::Big, Endian::Little] {
+            use Answer::*;
+            let char_layout = layout::Tree::<Def, !>::char(order);
+
+            // `char`s can be in the following ranges:
+            // - [0, 0xD7FF]
+            // - [0xE000, 10FFFF]
+            //
+            // This loop synthesizes a singleton-validity type for the extremes
+            // of each range, and for one past the end of the extremes of each
+            // range.
+            let no = No(Reason::DstIsBitIncompatible);
+            for (src, answer) in [
+                (0u32, Yes),
+                (0xD7FF, Yes),
+                (0xD800, no.clone()),
+                (0xDFFF, no.clone()),
+                (0xE000, Yes),
+                (0x10FFFF, Yes),
+                (0x110000, no.clone()),
+                (0xFFFF0000, no.clone()),
+                (0xFFFFFFFF, no),
+            ] {
+                let src_layout =
+                    layout::tree::Tree::<Def, !>::from_big_endian(order, src.to_be_bytes());
+
+                let a = is_transmutable(&src_layout, &char_layout, Assume::default());
+                assert_eq!(a, answer, "endian:{order:?},\nsrc:{src:x}");
+            }
+        }
+    }
+}
+
+mod nonzero {
+    use super::*;
+    use crate::{Answer, Reason};
+
+    const NONZERO_BYTE_WIDTHS: [u64; 5] = [1, 2, 4, 8, 16];
+
+    #[test]
+    fn should_permit_identity_transmutation() {
+        for width in NONZERO_BYTE_WIDTHS {
+            let layout = layout::Tree::<Def, !>::nonzero(width);
+            assert_eq!(is_transmutable(&layout, &layout, Assume::default()), Answer::Yes);
+        }
+    }
+
+    #[test]
+    fn should_permit_valid_transmutation() {
+        for width in NONZERO_BYTE_WIDTHS {
+            use Answer::*;
+
+            let num = layout::Tree::<Def, !>::number(width);
+            let nz = layout::Tree::<Def, !>::nonzero(width);
+
+            let a = is_transmutable(&num, &nz, Assume::default());
+            assert_eq!(a, No(Reason::DstIsBitIncompatible), "width:{width}");
+
+            let a = is_transmutable(&nz, &num, Assume::default());
+            assert_eq!(a, Yes, "width:{width}");
+        }
+    }
+}
+
 mod r#ref {
     use super::*;
 
@@ -330,7 +400,7 @@ mod r#ref {
     fn should_permit_identity_transmutation() {
         type Tree = crate::layout::Tree<Def, [(); 1]>;
 
-        let layout = Tree::Seq(vec![Tree::from_bits(0), Tree::Ref([()])]);
+        let layout = Tree::Seq(vec![Tree::byte(0x00), Tree::Ref([()])]);
 
         let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
             layout.clone(),
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index e9d3a149a73..74fb148a7cc 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -1,5 +1,3 @@
-use std::slice;
-
 use crate::inherent::*;
 use crate::visit::Flags;
 use crate::{self as ty, Interner};
@@ -388,8 +386,8 @@ impl<I: Interner> FlagComputation<I> {
                 self.add_alias_term(projection_term);
                 self.add_term(term);
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                self.add_args(slice::from_ref(&arg));
+            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
+                self.add_term(term);
             }
             ty::PredicateKind::DynCompatible(_def_id) => {}
             ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 847dff156fe..4e41fd16ffd 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -36,7 +36,7 @@ pub enum ClauseKind<I: Interner> {
     ConstArgHasType(I::Const, I::Ty),
 
     /// No syntax: `T` well-formed.
-    WellFormed(I::GenericArg),
+    WellFormed(I::Term),
 
     /// Constant initializer must evaluate successfully.
     ConstEvaluatable(I::Const),
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 5242261cf93..96fac4f6bde 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2319,9 +2319,9 @@ pub trait BufRead: Read {
     /// Checks if there is any data left to be `read`.
     ///
     /// This function may fill the buffer to check for data,
-    /// so this functions returns `Result<bool>`, not `bool`.
+    /// so this function returns `Result<bool>`, not `bool`.
     ///
-    /// Default implementation calls `fill_buf` and checks that
+    /// The default implementation calls `fill_buf` and checks that the
     /// returned slice is empty (which means that there is no data left,
     /// since EOF is reached).
     ///
diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml
index f8ae91f9e6f..642d48b9952 100644
--- a/src/tools/wasm-component-ld/Cargo.toml
+++ b/src/tools/wasm-component-ld/Cargo.toml
@@ -10,4 +10,4 @@ name = "wasm-component-ld"
 path = "src/main.rs"
 
 [dependencies]
-wasm-component-ld = "0.5.12"
+wasm-component-ld = "0.5.13"
diff --git a/tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.rs b/tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.rs
new file mode 100644
index 00000000000..650fb10d94b
--- /dev/null
+++ b/tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.rs
@@ -0,0 +1,22 @@
+//@ edition: 2024
+
+// Regression test for <https://github.com/rust-lang/rust/issues/140292>.
+
+struct Test;
+
+impl Test {
+    async fn an_async_fn(&mut self) {
+        todo!()
+    }
+
+    pub async fn uses_takes_asyncfn(&mut self) {
+        takes_asyncfn(Box::new(async || self.an_async_fn().await));
+        //~^ ERROR expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnMut`
+    }
+}
+
+async fn takes_asyncfn(_: impl AsyncFn()) {
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.stderr b/tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.stderr
new file mode 100644
index 00000000000..e79f95c197b
--- /dev/null
+++ b/tests/ui/async-await/async-closures/kind-due-to-arg-with-box-wrap.stderr
@@ -0,0 +1,21 @@
+error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnMut`
+  --> $DIR/kind-due-to-arg-with-box-wrap.rs:13:32
+   |
+LL |         takes_asyncfn(Box::new(async || self.an_async_fn().await));
+   |         ------------- ---------^^^^^^^^--------------------------
+   |         |             |        |        |
+   |         |             |        |        closure is `AsyncFnMut` because it mutates the variable `*self` here
+   |         |             |        this closure implements `AsyncFnMut`, not `AsyncFn`
+   |         |             the requirement to implement `AsyncFn` derives from here
+   |         required by a bound introduced by this call
+   |
+   = note: required for `Box<{async closure@$DIR/kind-due-to-arg-with-box-wrap.rs:13:32: 13:40}>` to implement `AsyncFn()`
+note: required by a bound in `takes_asyncfn`
+  --> $DIR/kind-due-to-arg-with-box-wrap.rs:18:32
+   |
+LL | async fn takes_asyncfn(_: impl AsyncFn()) {
+   |                                ^^^^^^^^^ required by this bound in `takes_asyncfn`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/tests/ui/transmutability/char.rs b/tests/ui/transmutability/char.rs
new file mode 100644
index 00000000000..55a61537329
--- /dev/null
+++ b/tests/ui/transmutability/char.rs
@@ -0,0 +1,41 @@
+#![feature(never_type)]
+#![feature(transmutability)]
+
+use std::mem::{Assume, TransmuteFrom};
+
+pub fn is_transmutable<Src, Dst>()
+where
+    Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+{
+}
+
+fn main() {
+    is_transmutable::<char, u32>();
+
+    // `char`s can be in the following ranges:
+    // - [0, 0xD7FF]
+    // - [0xE000, 10FFFF]
+    //
+    // `Char` has variants whose tags are in the top and bottom of each range.
+    // It also has generic variants which are out of bounds of these ranges, but
+    // are generic on types which may be set to `!` to "disable" them in the
+    // transmutability analysis.
+    #[repr(u32)]
+    enum Char<B, C, D> {
+        A = 0,
+        B = 0xD7FF,
+        OverB(B) = 0xD800,
+        UnderC(C) = 0xDFFF,
+        C = 0xE000,
+        D = 0x10FFFF,
+        OverD(D) = 0x110000,
+    }
+
+    is_transmutable::<Char<!, !, !>, char>();
+    is_transmutable::<Char<(), !, !>, char>();
+    //~^ ERROR cannot be safely transmuted into `char`
+    is_transmutable::<Char<!, (), !>, char>();
+    //~^ ERROR cannot be safely transmuted into `char`
+    is_transmutable::<Char<!, !, ()>, char>();
+    //~^ ERROR cannot be safely transmuted into `char`
+}
diff --git a/tests/ui/transmutability/char.stderr b/tests/ui/transmutability/char.stderr
new file mode 100644
index 00000000000..98e7ae9c0d4
--- /dev/null
+++ b/tests/ui/transmutability/char.stderr
@@ -0,0 +1,48 @@
+error[E0277]: `main::Char<(), !, !>` cannot be safely transmuted into `char`
+  --> $DIR/char.rs:35:39
+   |
+LL |     is_transmutable::<Char<(), !, !>, char>();
+   |                                       ^^^^ at least one value of `main::Char<(), !, !>` isn't a bit-valid value of `char`
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/char.rs:8:10
+   |
+LL | pub fn is_transmutable<Src, Dst>()
+   |        --------------- required by a bound in this function
+LL | where
+LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `main::Char<!, (), !>` cannot be safely transmuted into `char`
+  --> $DIR/char.rs:37:39
+   |
+LL |     is_transmutable::<Char<!, (), !>, char>();
+   |                                       ^^^^ at least one value of `main::Char<!, (), !>` isn't a bit-valid value of `char`
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/char.rs:8:10
+   |
+LL | pub fn is_transmutable<Src, Dst>()
+   |        --------------- required by a bound in this function
+LL | where
+LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `main::Char<!, !, ()>` cannot be safely transmuted into `char`
+  --> $DIR/char.rs:39:39
+   |
+LL |     is_transmutable::<Char<!, !, ()>, char>();
+   |                                       ^^^^ at least one value of `main::Char<!, !, ()>` isn't a bit-valid value of `char`
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/char.rs:8:10
+   |
+LL | pub fn is_transmutable<Src, Dst>()
+   |        --------------- required by a bound in this function
+LL | where
+LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.