about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_abi/src/layout.rs8
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs15
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs13
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs10
-rw-r--r--compiler/rustc_error_messages/src/lib.rs3
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs3
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs3
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs2
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs7
-rw-r--r--compiler/rustc_middle/src/query/keys.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs23
-rw-r--r--compiler/rustc_middle/src/ty/util.rs4
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs6
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs49
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs53
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs2
-rw-r--r--compiler/rustc_traits/src/codegen.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs101
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs152
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/incorrect_impls.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.fixed7
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.stderr8
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed9
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string_hashes.rs9
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr20
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/tests/pass/portable-simd-ptrs.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs6
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait.rs23
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait.stderr22
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait2.rs46
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait2.stderr12
-rw-r--r--tests/ui/impl-trait/deduce-signature-from-supertrait.rs4
-rw-r--r--tests/ui/impl-trait/in-assoc-type.rs3
-rw-r--r--tests/ui/impl-trait/in-assoc-type.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-70877.rs4
-rw-r--r--tests/ui/impl-trait/issues/issue-70877.stderr6
-rw-r--r--tests/ui/impl-trait/issues/issue-74282.rs9
-rw-r--r--tests/ui/impl-trait/issues/issue-74282.stderr18
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.rs22
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.stderr32
-rw-r--r--tests/ui/impl-trait/issues/issue-78722.rs3
-rw-r--r--tests/ui/impl-trait/issues/issue-78722.stderr6
-rw-r--r--tests/ui/lint/issue-99387.rs4
-rw-r--r--tests/ui/lint/issue-99387.stderr15
-rw-r--r--tests/ui/traits/new-solver/dont-remap-tait-substs.rs2
-rw-r--r--tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs6
-rw-r--r--tests/ui/traits/new-solver/tait-eq-proj-2.rs6
-rw-r--r--tests/ui/traits/new-solver/tait-eq-proj.rs2
-rw-r--r--tests/ui/traits/new-solver/tait-eq-tait.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/bound_reduction2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bound_reduction2.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/closure_args.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/closure_args2.rs23
-rw-r--r--tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr5
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr50
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr44
-rw-r--r--tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params.rs28
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params2.rs35
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/inference-cycle.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs21
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/issue-57961.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60564.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60564.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs7
-rw-r--r--tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/issue-70121.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/issue-70121.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/issue-77179.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/nested_in_closure.rs17
-rw-r--r--tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/reveal_local.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/reveal_local.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.rs8
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.stderr6
116 files changed, 1049 insertions, 405 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 73f9deb3143..f6875d895d3 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -134,7 +134,7 @@ pub trait LayoutCalculator {
         scalar_valid_range: (Bound<u128>, Bound<u128>),
         discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
         discriminants: impl Iterator<Item = (VariantIdx, i128)>,
-        niche_optimize_enum: bool,
+        dont_niche_optimize_enum: bool,
         always_sized: bool,
     ) -> Option<LayoutS> {
         let dl = self.current_data_layout();
@@ -183,10 +183,10 @@ pub trait LayoutCalculator {
             // (Typechecking will reject discriminant-sizing attrs.)
 
             let v = present_first;
-            let kind = if is_enum || variants[v].is_empty() {
+            let kind = if is_enum || variants[v].is_empty() || always_sized {
                 StructKind::AlwaysSized
             } else {
-                if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized }
+                StructKind::MaybeUnsized
             };
 
             let mut st = self.univariant(dl, &variants[v], repr, kind)?;
@@ -280,7 +280,7 @@ pub trait LayoutCalculator {
         }
 
         let calculate_niche_filling_layout = || -> Option<TmpLayout> {
-            if niche_optimize_enum {
+            if dont_niche_optimize_enum {
                 return None;
             }
 
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index db296aa44db..ca4a739abd7 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -25,7 +25,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_span::{Span, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
 
-use std::{fmt, iter};
+use std::{fmt, iter, mem};
 
 /// When the main Rust parser encounters a syntax-extension invocation, it
 /// parses the arguments to the invocation as a token tree. This is a very
@@ -410,8 +410,17 @@ impl TokenStream {
         t1.next().is_none() && t2.next().is_none()
     }
 
-    pub fn map_enumerated<F: FnMut(usize, &TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        TokenStream(Lrc::new(self.0.iter().enumerate().map(|(i, tree)| f(i, tree)).collect()))
+    /// Applies the supplied function to each `TokenTree` and its index in `self`, returning a new `TokenStream`
+    ///
+    /// It is equivalent to `TokenStream::new(self.trees().cloned().enumerate().map(|(i, tt)| f(i, tt)).collect())`.
+    pub fn map_enumerated_owned(
+        mut self,
+        mut f: impl FnMut(usize, TokenTree) -> TokenTree,
+    ) -> TokenStream {
+        let owned = Lrc::make_mut(&mut self.0); // clone if necessary
+        // rely on vec's in-place optimizations to avoid another allocation
+        *owned = mem::take(owned).into_iter().enumerate().map(|(i, tree)| f(i, tree)).collect();
+        self
     }
 
     /// Create a token stream containing a single token with alone spacing.
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 28cf9daf1c1..b4f2ae5ca77 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
-use rustc_middle::ty::{Binder, TraitRef, TypeVisitableExt};
+use rustc_middle::ty::{TraitRef, TypeVisitableExt};
 use rustc_mir_dataflow::{self, Analysis};
 use rustc_span::{sym, Span, Symbol};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -755,10 +755,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     }
 
                     let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
-                    let poly_trait_pred =
-                        Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst);
+                    let trait_ref = trait_ref.with_constness(ty::BoundConstness::ConstIfConst);
                     let obligation =
-                        Obligation::new(tcx, ObligationCause::dummy(), param_env, poly_trait_pred);
+                        Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
 
                     let implsrc = {
                         let infcx = tcx.infer_ctxt().build();
@@ -776,11 +775,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         }
                         // Closure: Fn{Once|Mut}
                         Ok(Some(ImplSource::Builtin(_)))
-                            if poly_trait_pred.self_ty().skip_binder().is_closure()
+                            if trait_ref.self_ty().is_closure()
                                 && tcx.fn_trait_kind_from_def_id(trait_id).is_some() =>
                         {
                             let ty::Closure(closure_def_id, substs) =
-                                *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind()
+                                *trait_ref.self_ty().kind()
                             else {
                                 unreachable!()
                             };
@@ -840,7 +839,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                     tcx,
                                     ObligationCause::dummy_with_span(*fn_span),
                                     param_env,
-                                    poly_trait_pred,
+                                    trait_ref,
                                 );
 
                                 // improve diagnostics by showing what failed. Our requirements are stricter this time
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 32bd9cda6f2..4eb278252c1 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -10,8 +10,8 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::{self, CallSource};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
+use rustc_middle::ty::TraitRef;
 use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
-use rustc_middle::ty::{Binder, TraitRef};
 use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
@@ -137,12 +137,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     }
                 }
                 Adt(..) => {
-                    let obligation = Obligation::new(
-                        tcx,
-                        ObligationCause::dummy(),
-                        param_env,
-                        Binder::dummy(trait_ref),
-                    );
+                    let obligation =
+                        Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
 
                     let infcx = tcx.infer_ctxt().build();
                     let mut selcx = SelectionContext::new(&infcx);
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index f3ee83fd4d2..51e1fe531dd 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -226,7 +226,7 @@ fn register_functions(bundle: &mut FluentBundle) {
 pub type LazyFallbackBundle = Lrc<Lazy<FluentBundle, impl FnOnce() -> FluentBundle>>;
 
 /// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
-#[instrument(level = "trace")]
+#[instrument(level = "trace", skip(resources))]
 pub fn fallback_fluent_bundle(
     resources: Vec<&'static str>,
     with_directionality_markers: bool,
@@ -242,7 +242,6 @@ pub fn fallback_fluent_bundle(
         for resource in resources {
             let resource = FluentResource::try_new(resource.to_string())
                 .expect("failed to parse fallback fluent resource");
-            trace!(?resource);
             fallback_bundle.add_resource_overriding(resource);
         }
 
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 4a8a14994ff..42cc0a6b143 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -223,8 +223,7 @@ fn expand_macro<'cx>(
             // Replace all the tokens for the corresponding positions in the macro, to maintain
             // proper positions in error reporting, while maintaining the macro_backtrace.
             if tts.len() == rhs.tts.len() {
-                tts = tts.map_enumerated(|i, tt| {
-                    let mut tt = tt.clone();
+                tts = tts.map_enumerated_owned(|i, mut tt| {
                     let rhs_tt = &rhs.tts[i];
                     let ctxt = tt.span().ctxt();
                     match (&mut tt, rhs_tt) {
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 0738961d6ce..166760166c1 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -248,6 +248,9 @@ hir_analysis_static_specialize = cannot specialize on `'static` lifetime
 
 hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
 
+hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
+    .note = this item must mention the opaque type in its signature in order to be able to register hidden types
+
 hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
 
 hir_analysis_too_large_static = extern static is too large for the current architecture
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 7a625dd5932..d4748b7ef0b 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -981,7 +981,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
             // intermediate types must be sized.
             let needs_drop_copy = || {
                 packed && {
-                    let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity();
+                    let ty = tcx.type_of(variant.tail().did).subst_identity();
                     let ty = tcx.erase_regions(ty);
                     if ty.has_infer() {
                         tcx.sess
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index f4779a3f265..957a6bb3481 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -6,7 +6,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::DUMMY_SP;
 
-use crate::errors::UnconstrainedOpaqueType;
+use crate::errors::{TaitForwardCompat, UnconstrainedOpaqueType};
 
 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
 /// laid for "higher-order pattern unification".
@@ -139,6 +139,15 @@ impl TaitConstraintLocator<'_> {
                 continue;
             }
             constrained = true;
+            if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) {
+                self.tcx.sess.emit_err(TaitForwardCompat {
+                    span: hidden_type.span,
+                    item_span: self
+                        .tcx
+                        .def_ident_span(item_def_id)
+                        .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
+                });
+            }
             let concrete_type =
                 self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
                     opaque_type_key,
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 205e26d0eda..c2d2e5f7e50 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -184,6 +184,16 @@ pub struct UnconstrainedOpaqueType {
     pub what: &'static str,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_tait_forward_compat)]
+#[note]
+pub struct TaitForwardCompat {
+    #[primary_span]
+    pub span: Span,
+    #[note]
+    pub item_span: Span,
+}
+
 pub struct MissingTypeParams {
     pub span: Span,
     pub def_span: Span,
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 71799387458..633933317c0 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -103,15 +103,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Ok(match *t.kind() {
             ty::Slice(_) | ty::Str => Some(PointerKind::Length),
             ty::Dynamic(ref tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())),
-            ty::Adt(def, substs) if def.is_struct() => {
-                match def.non_enum_variant().fields.raw.last() {
-                    None => Some(PointerKind::Thin),
-                    Some(f) => {
-                        let field_ty = self.field_ty(span, f, substs);
-                        self.pointer_kind(field_ty, span)?
-                    }
+            ty::Adt(def, substs) if def.is_struct() => match def.non_enum_variant().tail_opt() {
+                None => Some(PointerKind::Thin),
+                Some(f) => {
+                    let field_ty = self.field_ty(span, f, substs);
+                    self.pointer_kind(field_ty, span)?
                 }
-            }
+            },
             ty::Tuple(fields) => match fields.last() {
                 None => Some(PointerKind::Thin),
                 Some(&f) => self.pointer_kind(f, span)?,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index ea6ae094f09..108e20ed145 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -632,9 +632,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         while !queue.is_empty() {
             let obligation = queue.remove(0);
             debug!("coerce_unsized resolve step: {:?}", obligation);
-            let bound_predicate = obligation.predicate.kind();
-            let trait_pred = match bound_predicate.skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))
+            let trait_pred = match obligation.predicate.kind().no_bound_vars() {
+                Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
                     if traits.contains(&trait_pred.def_id()) =>
                 {
                     if unsize_did == trait_pred.def_id() {
@@ -652,7 +651,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                             has_unsized_tuple_coercion = true;
                         }
                     }
-                    bound_predicate.rebind(trait_pred)
+                    trait_pred
                 }
                 _ => {
                     coercion.obligations.push(obligation);
@@ -664,8 +663,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 Ok(None) => {
                     if trait_pred.def_id() == unsize_did {
                         let trait_pred = self.resolve_vars_if_possible(trait_pred);
-                        let self_ty = trait_pred.skip_binder().self_ty();
-                        let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty();
+                        let self_ty = trait_pred.self_ty();
+                        let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
                         debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
                         match (self_ty.kind(), unsize_ty.kind()) {
                             (&ty::Infer(ty::TyVar(v)), ty::Dynamic(..))
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 4bd4f2d7e9c..41f5fafe72f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1982,7 +1982,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.tcx,
                             traits::ObligationCause::dummy(),
                             self.param_env,
-                            ty::Binder::dummy(trait_ref),
+                            trait_ref,
                         );
                         match SelectionContext::new(&self).select(&obligation) {
                             Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index 05e5db9f0f3..d5619af2aae 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -80,7 +80,7 @@ impl<'tcx> Inherited<'tcx> {
         let infcx = tcx
             .infer_ctxt()
             .ignoring_regions()
-            .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id))
+            .with_opaque_type_inference(DefiningAnchor::Bind(def_id))
             .build();
         let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 52e62837f35..03a3eebbdf5 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1441,8 +1441,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         trait_ref: ty::TraitRef<'tcx>,
     ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> {
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
-        let predicate = ty::Binder::dummy(trait_ref);
-        let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, predicate);
+        let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, trait_ref);
         traits::SelectionContext::new(self).select(&obligation)
     }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index c9a8f8131df..63613b59020 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -257,7 +257,7 @@ impl<T> Trait<T> for X {
                             );
                         }
                     }
-                    (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
+                    (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::Fn | DefKind::Static(_) | DefKind::Const | DefKind::AssocFn | DefKind::AssocConst) => {
                         if tcx.is_type_alias_impl_trait(alias.def_id) {
                             if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
                                 let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id));
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 6da490a90ee..626dd9359a1 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -62,7 +62,8 @@ impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
 }
 
 pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
-pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
+pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
+pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
 
 impl<'tcx> PredicateObligation<'tcx> {
     /// Flips the polarity of the inner predicate.
@@ -86,7 +87,7 @@ impl<'tcx> PredicateObligation<'tcx> {
     }
 }
 
-impl<'tcx> TraitObligation<'tcx> {
+impl<'tcx> PolyTraitObligation<'tcx> {
     /// Returns `true` if the trait predicate is considered `const` in its ParamEnv.
     pub fn is_const(&self) -> bool {
         matches!(
@@ -193,7 +194,7 @@ impl<'tcx> FulfillmentError<'tcx> {
     }
 }
 
-impl<'tcx> TraitObligation<'tcx> {
+impl<'tcx> PolyTraitObligation<'tcx> {
     pub fn polarity(&self) -> ty::ImplPolarity {
         self.predicate.skip_binder().polarity
     }
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 0119e07a44e..28e699cd269 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -318,11 +318,11 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
     }
 }
 
-impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
+impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) {
     type CacheSelector = DefaultCacheSelector<Self>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
-        tcx.def_span(self.1.def_id())
+        tcx.def_span(self.1.def_id)
     }
 }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d58a1a65533..a059590e6ad 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1278,7 +1278,7 @@ rustc_queries! {
     }
 
     query codegen_select_candidate(
-        key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
+        key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>)
     ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
         cache_on_disk_if { true }
         desc { |tcx| "computing candidate for `{}`", key.1 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c100c45b61a..aa8bfd3178c 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1306,6 +1306,13 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
     }
 }
 
+impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
+    #[inline(always)]
+    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
+        self.without_const()
+    }
+}
+
 impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
@@ -2028,6 +2035,22 @@ impl VariantDef {
 
         &self.fields[FieldIdx::from_u32(0)]
     }
+
+    /// Returns the last field in this variant, if present.
+    #[inline]
+    pub fn tail_opt(&self) -> Option<&FieldDef> {
+        self.fields.raw.last()
+    }
+
+    /// Returns the last field in this variant.
+    ///
+    /// # Panics
+    ///
+    /// Panics, if the variant has no fields.
+    #[inline]
+    pub fn tail(&self) -> &FieldDef {
+        self.tail_opt().expect("expected unsized ADT to have a tail field")
+    }
 }
 
 impl PartialEq for VariantDef {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 720d770eed4..e2e4a2dbdc8 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -230,7 +230,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     if !def.is_struct() {
                         break;
                     }
-                    match def.non_enum_variant().fields.raw.last() {
+                    match def.non_enum_variant().tail_opt() {
                         Some(field) => {
                             f();
                             ty = field.ty(self, substs);
@@ -304,7 +304,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
                     if a_def == b_def && a_def.is_struct() =>
                 {
-                    if let Some(f) = a_def.non_enum_variant().fields.raw.last() {
+                    if let Some(f) = a_def.non_enum_variant().tail_opt() {
                         a = f.ty(self, a_substs);
                         b = f.ty(self, b_substs);
                     } else {
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 89dadc782f2..5f05020acae 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -31,12 +31,12 @@ fn custom_coerce_unsize_info<'tcx>(
     source_ty: Ty<'tcx>,
     target_ty: Ty<'tcx>,
 ) -> CustomCoerceUnsized {
-    let trait_ref = ty::Binder::dummy(ty::TraitRef::from_lang_item(
+    let trait_ref = ty::TraitRef::from_lang_item(
         tcx.tcx,
         LangItem::CoerceUnsized,
         tcx.span,
         [source_ty, target_ty],
-    ));
+    );
 
     match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
         Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 0800738a3f2..bf6cbef8c3b 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_infer::traits::util::supertraits;
 use rustc_infer::traits::{
-    Obligation, PredicateObligation, Selection, SelectionResult, TraitObligation,
+    Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult,
 };
 use rustc_middle::traits::solve::{CanonicalInput, Certainty, Goal};
 use rustc_middle::traits::{
@@ -23,14 +23,14 @@ use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, V
 pub trait InferCtxtSelectExt<'tcx> {
     fn select_in_new_trait_solver(
         &self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, Selection<'tcx>>;
 }
 
 impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
     fn select_in_new_trait_solver(
         &self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, Selection<'tcx>> {
         assert!(self.next_trait_solver());
 
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index aa690719970..e53b784a756 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -366,7 +366,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 }
 
                 ty::Adt(def, substs) if def.is_struct() => {
-                    match def.non_enum_variant().fields.raw.last() {
+                    match def.non_enum_variant().tail_opt() {
                         None => tcx.types.unit,
                         Some(field_def) => {
                             let self_ty = field_def.ty(tcx, substs);
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index cd68626bed1..ef5f25b1f7f 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -425,12 +425,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                         return Err(NoSolution);
                     }
 
-                    let tail_field = a_def
-                        .non_enum_variant()
-                        .fields
-                        .raw
-                        .last()
-                        .expect("expected unsized ADT to have a tail field");
+                    let tail_field = a_def.non_enum_variant().tail();
                     let tail_field_ty = tcx.type_of(tail_field.did);
 
                     let a_tail_ty = tail_field_ty.subst(tcx, a_substs);
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 4296ed64cf0..cb38d0ac847 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -95,7 +95,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 tcx,
                 ObligationCause::dummy(),
                 orig_env,
-                ty::Binder::dummy(ty::TraitPredicate {
+                ty::TraitPredicate {
                     trait_ref,
                     constness: ty::BoundConstness::NotConst,
                     polarity: if polarity {
@@ -103,7 +103,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     } else {
                         ImplPolarity::Negative
                     },
-                }),
+                },
             ));
             if let Ok(Some(ImplSource::UserDefined(_))) = result {
                 debug!(
@@ -292,7 +292,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 new_env,
                 pred,
             ));
-            let result = select.select(&obligation);
+            let result = select.poly_select(&obligation);
 
             match result {
                 Ok(Some(ref impl_source)) => {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index 7b5d4f456ff..f785c4eaf9d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -1,7 +1,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
 use rustc_infer::traits::util::elaborate;
-use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
+use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation};
 use rustc_middle::ty;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -14,7 +14,7 @@ pub enum Ambiguity {
 
 pub fn recompute_applicable_impls<'tcx>(
     infcx: &InferCtxt<'tcx>,
-    obligation: &TraitObligation<'tcx>,
+    obligation: &PolyTraitObligation<'tcx>,
 ) -> Vec<Ambiguity> {
     let tcx = infcx.tcx;
     let param_env = obligation.param_env;
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 2d8c260126d..cf9d9315f60 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}
 use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::ProjectionCacheKey;
-use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation};
+use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -667,7 +667,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
     fn process_trait_obligation(
         &mut self,
         obligation: &PredicateObligation<'tcx>,
-        trait_obligation: TraitObligation<'tcx>,
+        trait_obligation: PolyTraitObligation<'tcx>,
         stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let infcx = self.selcx.infcx;
@@ -683,7 +683,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             }
         }
 
-        match self.selcx.select(&trait_obligation) {
+        match self.selcx.poly_select(&trait_obligation) {
             Ok(Some(impl_source)) => {
                 debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth);
                 ProcessResult::Changed(mk_pending(impl_source.nested_obligations()))
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index e2ee347b639..1af8323b6e9 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -11,7 +11,7 @@ mod fulfill;
 pub mod misc;
 mod object_safety;
 pub mod outlives_bounds;
-mod project;
+pub mod project;
 pub mod query;
 #[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
 mod select;
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 717b35784d8..a10bca31ff1 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1545,7 +1545,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
         let trait_def_id = tcx.parent(trait_fn_def_id);
         let trait_substs =
             obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
-        // FIXME(named-returns): Binders
         let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs);
 
         let _ = selcx.infcx.commit_if_ok(|_| {
@@ -1747,8 +1746,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
-    let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
-    let trait_obligation = obligation.with(selcx.tcx(), poly_trait_ref);
+    let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
+    let trait_obligation = obligation.with(selcx.tcx(), trait_ref);
     let _ = selcx.infcx.commit_if_ok(|_| {
         let impl_source = match selcx.select(&trait_obligation) {
             Ok(Some(impl_source)) => impl_source,
@@ -1802,7 +1801,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     if obligation.param_env.reveal() == Reveal::All {
                         // NOTE(eddyb) inference variables can resolve to parameters, so
                         // assume `poly_trait_ref` isn't monomorphic, if it contains any.
-                        let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(poly_trait_ref);
+                        let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(trait_ref);
                         !poly_trait_ref.still_further_specializable()
                     } else {
                         debug!(
@@ -1821,11 +1820,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
 
                 let lang_items = selcx.tcx().lang_items();
-                if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(poly_trait_ref.def_id()))
-                    || selcx.tcx().fn_trait_kind_from_def_id(poly_trait_ref.def_id()).is_some()
+                if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(trait_ref.def_id))
+                    || selcx.tcx().fn_trait_kind_from_def_id(trait_ref.def_id).is_some()
                 {
                     true
-                } else if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) {
+                } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) {
                     match self_ty.kind() {
                         ty::Bool
                         | ty::Char
@@ -1860,7 +1859,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Infer(..)
                         | ty::Error(_) => false,
                     }
-                } else if lang_items.pointee_trait() == Some(poly_trait_ref.def_id()) {
+                } else if lang_items.pointee_trait() == Some(trait_ref.def_id) {
                     let tail = selcx.tcx().struct_tail_with_normalize(
                         self_ty,
                         |ty| {
@@ -1935,7 +1934,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         }
                     }
                 } else {
-                    bug!("unexpected builtin trait with associated type: {poly_trait_ref:?}")
+                    bug!("unexpected builtin trait with associated type: {trait_ref:?}")
                 }
             }
             super::ImplSource::Param(..) => {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a0329259705..d5f6aaa7fe9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -10,7 +10,7 @@ use hir::def_id::DefId;
 use hir::LangItem;
 use rustc_hir as hir;
 use rustc_infer::traits::ObligationCause;
-use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
+use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
@@ -137,7 +137,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(level = "debug", skip(self, candidates))]
     fn assemble_candidates_from_projected_tys(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // Before we go into the whole placeholder thing, just
@@ -206,7 +206,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn assemble_generator_candidates(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // Okay to skip binder because the substs on generator types never
@@ -231,7 +231,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn assemble_future_candidates(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         let self_ty = obligation.self_ty().skip_binder();
@@ -254,7 +254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// unified during the confirmation step.
     fn assemble_closure_candidates(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
@@ -292,7 +292,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Implements one of the `Fn()` family for a fn pointer.
     fn assemble_fn_pointer_candidates(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // We provide impl of all fn traits for fn pointers.
@@ -334,7 +334,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(level = "debug", skip(self, candidates))]
     fn assemble_candidates_from_impls(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // Essentially any user-written impl will match with an error type,
@@ -390,7 +390,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn reject_fn_ptr_impls(
         &mut self,
         impl_def_id: DefId,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         impl_self_ty: Ty<'tcx>,
     ) -> bool {
         // Let `impl<T: FnPtr> Trait for Vec<T>` go through the normal rejection path.
@@ -475,7 +475,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn assemble_candidates_from_auto_impls(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // Okay to skip binder here because the tests we do below do not involve bound regions.
@@ -544,7 +544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Searches for impls that might apply to `obligation`.
     fn assemble_candidates_from_object_ty(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         debug!(
@@ -668,7 +668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Searches for unsizing that might apply to `obligation`.
     fn assemble_candidates_for_unsizing(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // We currently never consider higher-ranked obligations e.g.
@@ -782,7 +782,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(level = "debug", skip(self, obligation, candidates))]
     fn assemble_candidates_for_transmutability(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         if obligation.predicate.has_non_region_param() {
@@ -800,7 +800,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(level = "debug", skip(self, obligation, candidates))]
     fn assemble_candidates_for_trait_alias(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // Okay to skip binder here because the tests we do below do not involve bound regions.
@@ -837,7 +837,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn assemble_const_destruct_candidates(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // If the predicate is `~const Destruct` in a non-const environment, we don't actually need
@@ -924,7 +924,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn assemble_candidate_for_tuple(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
@@ -966,7 +966,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn assemble_candidate_for_pointer_like(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         // The regions of a type don't affect the size of the type
@@ -991,7 +991,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn assemble_candidates_for_fn_ptr_trait(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 21a223135ed..7adc29bbba4 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -27,8 +27,8 @@ use crate::traits::vtable::{
 use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
     ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
-    Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
+    Obligation, ObligationCause, OutputTypeParameterMismatch, PolyTraitObligation,
+    PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -42,7 +42,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub(super) fn confirm_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         candidate: SelectionCandidate<'tcx>,
     ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
         let mut impl_src = match candidate {
@@ -148,7 +148,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_projection_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         idx: usize,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
@@ -215,7 +215,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_param_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         param: ty::PolyTraitRef<'tcx>,
     ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?obligation, ?param, "confirm_param_candidate");
@@ -238,7 +238,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_builtin_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         has_nested: bool,
     ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?obligation, ?has_nested, "confirm_builtin_candidate");
@@ -279,13 +279,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn confirm_transmutability_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         use rustc_transmute::{Answer, Condition};
         #[instrument(level = "debug", skip(tcx, obligation, predicate))]
         fn flatten_answer_tree<'tcx>(
             tcx: TyCtxt<'tcx>,
-            obligation: &TraitObligation<'tcx>,
+            obligation: &PolyTraitObligation<'tcx>,
             predicate: TraitPredicate<'tcx>,
             cond: Condition<rustc_transmute::layout::rustc::Ref<'tcx>>,
         ) -> Vec<PredicateObligation<'tcx>> {
@@ -375,7 +375,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
     fn confirm_auto_impl_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!(?obligation, "confirm_auto_impl_candidate");
 
@@ -387,7 +387,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// See `confirm_auto_impl_candidate`.
     fn vtable_auto_impl(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         trait_def_id: DefId,
         nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
     ) -> Vec<PredicateObligation<'tcx>> {
@@ -426,7 +426,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_impl_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         impl_def_id: DefId,
     ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
         debug!(?obligation, ?impl_def_id, "confirm_impl_candidate");
@@ -481,7 +481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_object_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         index: usize,
     ) -> Result<ImplSourceObjectData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
@@ -655,7 +655,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_fn_pointer_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         is_const: bool,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!(?obligation, "confirm_fn_pointer_candidate");
@@ -714,7 +714,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_trait_alias_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?obligation, "confirm_trait_alias_candidate");
 
@@ -739,7 +739,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_generator_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
@@ -778,7 +778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_future_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
@@ -809,7 +809,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn confirm_closure_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let kind = self
             .tcx()
@@ -865,7 +865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(skip(self), level = "trace")]
     fn confirm_poly_trait_refs(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let obligation_trait_ref = obligation.predicate.to_poly_trait_ref();
@@ -900,7 +900,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_trait_upcasting_unsize_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         idx: usize,
     ) -> Result<ImplSourceTraitUpcastingData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
@@ -1004,7 +1004,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_builtin_unsize_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
 
@@ -1125,12 +1125,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     return Err(Unimplemented);
                 }
 
-                let tail_field = def
-                    .non_enum_variant()
-                    .fields
-                    .raw
-                    .last()
-                    .expect("expected unsized ADT to have a tail field");
+                let tail_field = def.non_enum_variant().tail();
                 let tail_field_ty = tcx.type_of(tail_field.did);
 
                 // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
@@ -1213,7 +1208,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_const_destruct_candidate(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         impl_def_id: Option<DefId>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4a55ceb20a1..7f31ab75119 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -15,8 +15,8 @@ use super::util::closure_trait_ref_and_return_type;
 use super::wf;
 use super::{
     ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
-    ObligationCause, ObligationCauseCode, Overflow, PredicateObligation, Selection, SelectionError,
-    SelectionResult, TraitObligation, TraitQueryMode,
+    ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation,
+    Selection, SelectionError, SelectionResult, TraitQueryMode,
 };
 
 use crate::infer::{InferCtxt, InferOk, TypeFreshener};
@@ -34,6 +34,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::LateBoundRegionConversionTime;
+use rustc_infer::traits::TraitObligation;
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -122,7 +123,7 @@ pub struct SelectionContext<'cx, 'tcx> {
 
 // A stack that walks back up the stack frame.
 struct TraitObligationStack<'prev, 'tcx> {
-    obligation: &'prev TraitObligation<'tcx>,
+    obligation: &'prev PolyTraitObligation<'tcx>,
 
     /// The trait predicate from `obligation` but "freshened" with the
     /// selection-context's freshener. Used to check for recursion.
@@ -259,9 +260,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
     /// type environment by performing unification.
     #[instrument(level = "debug", skip(self), ret)]
-    pub fn select(
+    pub fn poly_select(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, Selection<'tcx>> {
         if self.infcx.next_trait_solver() {
             return self.infcx.select_in_new_trait_solver(obligation);
@@ -293,9 +294,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
-    fn select_from_obligation(
+    pub fn select(
         &mut self,
         obligation: &TraitObligation<'tcx>,
+    ) -> SelectionResult<'tcx, Selection<'tcx>> {
+        self.poly_select(&Obligation {
+            cause: obligation.cause.clone(),
+            param_env: obligation.param_env,
+            predicate: ty::Binder::dummy(obligation.predicate),
+            recursion_depth: obligation.recursion_depth,
+        })
+    }
+
+    fn select_from_obligation(
+        &mut self,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         debug_assert!(!obligation.predicate.has_escaping_bound_vars());
 
@@ -612,7 +625,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         debug_assert!(!self.infcx.next_trait_solver());
-        // `previous_stack` stores a `TraitObligation`, while `obligation` is
+        // `previous_stack` stores a `PolyTraitObligation`, while `obligation` is
         // a `PredicateObligation`. These are distinct types, so we can't
         // use any `Option` combinator method that would force them to be
         // the same.
@@ -973,7 +986,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn evaluate_trait_predicate_recursively<'o>(
         &mut self,
         previous_stack: TraitObligationStackList<'o, 'tcx>,
-        mut obligation: TraitObligation<'tcx>,
+        mut obligation: PolyTraitObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         if !self.is_intercrate()
             && obligation.is_global()
@@ -1379,7 +1392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn filter_impls(
         &mut self,
         candidates: Vec<SelectionCandidate<'tcx>>,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Vec<SelectionCandidate<'tcx>> {
         trace!("{candidates:#?}");
         let tcx = self.tcx();
@@ -1442,7 +1455,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn filter_reservation_impls(
         &mut self,
         candidate: SelectionCandidate<'tcx>,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         let tcx = self.tcx();
         // Treat reservation impls as ambiguity.
@@ -1614,7 +1627,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[instrument(level = "debug", skip(self), ret)]
     fn match_projection_obligation_against_definition_bounds(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
         let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
         let placeholder_trait_predicate =
@@ -1677,7 +1690,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// variables or placeholders, the normalized bound is returned.
     fn match_normalize_trait_ref(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         trait_bound: ty::PolyTraitRef<'tcx>,
         placeholder_trait_ref: ty::TraitRef<'tcx>,
     ) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> {
@@ -2078,7 +2091,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
 impl<'tcx> SelectionContext<'_, 'tcx> {
     fn sized_conditions(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> BuiltinImplConditions<'tcx> {
         use self::BuiltinImplConditions::{Ambiguous, None, Where};
 
@@ -2138,7 +2151,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
 
     fn copy_clone_conditions(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> BuiltinImplConditions<'tcx> {
         // NOTE: binder moved to (*)
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
@@ -2414,7 +2427,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     fn rematch_impl(
         &mut self,
         impl_def_id: DefId,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Normalized<'tcx, SubstsRef<'tcx>> {
         let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
         match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
@@ -2452,7 +2465,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         &mut self,
         impl_def_id: DefId,
         impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
         let placeholder_obligation =
             self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
@@ -2510,7 +2523,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     /// result from the normalization.
     fn match_where_clause_trait_ref(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
         self.match_poly_trait_ref(obligation, where_clause_trait_ref)
@@ -2521,7 +2534,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn match_poly_trait_ref(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
         self.infcx
@@ -2547,7 +2560,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     fn push_stack<'o>(
         &mut self,
         previous_stack: TraitObligationStackList<'o, 'tcx>,
-        obligation: &'o TraitObligation<'tcx>,
+        obligation: &'o PolyTraitObligation<'tcx>,
     ) -> TraitObligationStack<'o, 'tcx> {
         let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener);
 
@@ -2566,7 +2579,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn closure_trait_ref_unnormalized(
         &mut self,
-        obligation: &TraitObligation<'tcx>,
+        obligation: &PolyTraitObligation<'tcx>,
         substs: SubstsRef<'tcx>,
     ) -> ty::PolyTraitRef<'tcx> {
         let closure_sig = substs.as_closure().sig();
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index c05d557b774..1f83f1f44bc 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -362,7 +362,7 @@ pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
 
     let trait_ref = ty::TraitRef::new(tcx, unsize_trait_did, [source, target]);
 
-    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
+    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
         Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
             implsrc_traitcasting.vtable_vptr_slot
         }
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index ef50fa23caf..2cd1c3b502a 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -22,7 +22,7 @@ use rustc_trait_selection::traits::{
 /// This also expects that `trait_ref` is fully normalized.
 pub fn codegen_select_candidate<'tcx>(
     tcx: TyCtxt<'tcx>,
-    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
+    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>),
 ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
     // We expect the input to be fully normalized.
     debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 2d75862014d..1d93a79e591 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -80,7 +80,7 @@ fn resolve_associated_item<'tcx>(
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
 
-    let vtbl = match tcx.codegen_select_candidate((param_env, ty::Binder::dummy(trait_ref))) {
+    let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) {
         Ok(vtbl) => vtbl,
         Err(CodegenObligationError::Ambiguity) => {
             let reported = tcx.sess.delay_span_bug(
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 9ef9120e294..b67cd96a734 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -463,38 +463,85 @@ fn layout_of_uncached<'tcx>(
                 ));
             }
 
-            tcx.mk_layout(
-                cx.layout_of_struct_or_enum(
+            let get_discriminant_type =
+                |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max);
+
+            let discriminants_iter = || {
+                def.is_enum()
+                    .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128)))
+                    .into_iter()
+                    .flatten()
+            };
+
+            let dont_niche_optimize_enum = def.repr().inhibit_enum_layout_opt()
+                || def
+                    .variants()
+                    .iter_enumerated()
+                    .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32()));
+
+            let maybe_unsized = def.is_struct()
+                && def.non_enum_variant().tail_opt().is_some_and(|last_field| {
+                    let param_env = tcx.param_env(def.did());
+                    !tcx.type_of(last_field.did).subst_identity().is_sized(tcx, param_env)
+                });
+
+            let Some(layout) = cx.layout_of_struct_or_enum(
+                &def.repr(),
+                &variants,
+                def.is_enum(),
+                def.is_unsafe_cell(),
+                tcx.layout_scalar_valid_range(def.did()),
+                get_discriminant_type,
+                discriminants_iter(),
+                dont_niche_optimize_enum,
+                !maybe_unsized,
+            ) else {
+                return Err(error(cx, LayoutError::SizeOverflow(ty)));
+            };
+
+            // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around.
+            if cfg!(debug_assertions)
+                && maybe_unsized
+                && def.non_enum_variant().tail().ty(tcx, substs).is_sized(tcx, cx.param_env)
+            {
+                let mut variants = variants;
+                let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap();
+                *variants[FIRST_VARIANT].raw.last_mut().unwrap() = tail_replacement.layout;
+
+                let Some(unsized_layout) = cx.layout_of_struct_or_enum(
                     &def.repr(),
                     &variants,
                     def.is_enum(),
                     def.is_unsafe_cell(),
                     tcx.layout_scalar_valid_range(def.did()),
-                    |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max),
-                    def.is_enum()
-                        .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128)))
-                        .into_iter()
-                        .flatten(),
-                    def.repr().inhibit_enum_layout_opt()
-                        || def
-                            .variants()
-                            .iter_enumerated()
-                            .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32())),
-                    {
-                        let param_env = tcx.param_env(def.did());
-                        def.is_struct()
-                            && match def.variants().iter().next().and_then(|x| x.fields.raw.last())
-                            {
-                                Some(last_field) => tcx
-                                    .type_of(last_field.did)
-                                    .subst_identity()
-                                    .is_sized(tcx, param_env),
-                                None => false,
-                            }
-                    },
-                )
-                .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?,
-            )
+                    get_discriminant_type,
+                    discriminants_iter(),
+                    dont_niche_optimize_enum,
+                    !maybe_unsized,
+                ) else {
+                    bug!("failed to compute unsized layout of {ty:?}");
+                };
+
+                let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else {
+                    bug!("unexpected FieldsShape for sized layout of {ty:?}: {:?}", layout.fields);
+                };
+                let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } = &unsized_layout.fields else {
+                    bug!("unexpected FieldsShape for unsized layout of {ty:?}: {:?}", unsized_layout.fields);
+                };
+
+                let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap();
+                let (unsized_tail, unsized_fields) = unsized_offsets.raw.split_last().unwrap();
+
+                if sized_fields != unsized_fields {
+                    bug!("unsizing {ty:?} changed field order!\n{layout:?}\n{unsized_layout:?}");
+                }
+
+                if sized_tail < unsized_tail {
+                    bug!("unsizing {ty:?} moved tail backwards!\n{layout:?}\n{unsized_layout:?}");
+                }
+            }
+
+            tcx.mk_layout(layout)
         }
 
         // Types with no meaningful known layout.
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 29de8bf0e53..570c3b245cd 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -1,5 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::{def::DefKind, def_id::LocalDefId};
+use rustc_hir::{intravisit, CRATE_HIR_ID};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -51,7 +53,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
 
     fn parent(&self) -> Option<LocalDefId> {
         match self.tcx.def_kind(self.item) {
-            DefKind::Fn => None,
+            DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias => None,
             DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
                 Some(self.tcx.local_parent(self.item))
             }
@@ -61,6 +63,73 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
             ),
         }
     }
+
+    /// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `self.item`.
+    ///
+    /// Example:
+    /// ```ignore UNSOLVED (is this a bug?)
+    /// # #![feature(type_alias_impl_trait)]
+    /// pub mod foo {
+    ///     pub mod bar {
+    ///         pub trait Bar { /* ... */ }
+    ///         pub type Baz = impl Bar;
+    ///
+    ///         # impl Bar for () {}
+    ///         fn f1() -> Baz { /* ... */ }
+    ///     }
+    ///     fn f2() -> bar::Baz { /* ... */ }
+    /// }
+    /// ```
+    ///
+    /// and `opaque_def_id` is the `DefId` of the definition of the opaque type `Baz`.
+    /// For the above example, this function returns `true` for `f1` and `false` for `f2`.
+    #[instrument(level = "trace", skip(self), ret)]
+    fn check_tait_defining_scope(&self, opaque_def_id: LocalDefId) -> bool {
+        let mut hir_id = self.tcx.hir().local_def_id_to_hir_id(self.item);
+        let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(opaque_def_id);
+
+        // Named opaque types can be defined by any siblings or children of siblings.
+        let scope = self.tcx.hir().get_defining_scope(opaque_hir_id);
+        // We walk up the node tree until we hit the root or the scope of the opaque type.
+        while hir_id != scope && hir_id != CRATE_HIR_ID {
+            hir_id = self.tcx.hir().get_parent_item(hir_id).into();
+        }
+        // Syntactically, we are allowed to define the concrete type if:
+        hir_id == scope
+    }
+
+    fn collect_body_and_predicate_taits(&mut self) {
+        // Look at all where bounds.
+        self.tcx.predicates_of(self.item).instantiate_identity(self.tcx).visit_with(self);
+        // An item is allowed to constrain opaques declared within its own body (but not nested within
+        // nested functions).
+        self.collect_taits_declared_in_body();
+    }
+
+    #[instrument(level = "trace", skip(self))]
+    fn collect_taits_declared_in_body(&mut self) {
+        let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(self.item)).value;
+        struct TaitInBodyFinder<'a, 'tcx> {
+            collector: &'a mut OpaqueTypeCollector<'tcx>,
+        }
+        impl<'v> intravisit::Visitor<'v> for TaitInBodyFinder<'_, '_> {
+            #[instrument(level = "trace", skip(self))]
+            fn visit_nested_item(&mut self, id: rustc_hir::ItemId) {
+                let id = id.owner_id.def_id;
+                if let DefKind::TyAlias = self.collector.tcx.def_kind(id) {
+                    let items = self.collector.tcx.opaque_types_defined_by(id);
+                    self.collector.opaques.extend(items);
+                }
+            }
+            #[instrument(level = "trace", skip(self))]
+            // Recurse into these, as they are type checked with their parent
+            fn visit_nested_body(&mut self, id: rustc_hir::BodyId) {
+                let body = self.collector.tcx.hir().body(id);
+                self.visit_body(body);
+            }
+        }
+        TaitInBodyFinder { collector: self }.visit_expr(body);
+    }
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
@@ -73,6 +142,21 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                     return ControlFlow::Continue(());
                 }
 
+                // TAITs outside their defining scopes are ignored.
+                let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local());
+                trace!(?origin);
+                match origin {
+                    rustc_hir::OpaqueTyOrigin::FnReturn(_)
+                    | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
+                    rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
+                        if !in_assoc_ty {
+                            if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
+                                return ControlFlow::Continue(());
+                            }
+                        }
+                    }
+                }
+
                 self.opaques.push(alias_ty.def_id.expect_local());
 
                 match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
@@ -188,33 +272,36 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
 fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] {
     let kind = tcx.def_kind(item);
     trace!(?kind);
-    // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT and impl trait in assoc types.
+    let mut collector = OpaqueTypeCollector::new(tcx, item);
     match kind {
+        // Walk over the signature of the function-like to find the opaques.
+        DefKind::AssocFn | DefKind::Fn => {
+            let ty_sig = tcx.fn_sig(item).subst_identity();
+            let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
+            // Walk over the inputs and outputs manually in order to get good spans for them.
+            collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
+            for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
+                collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
+            }
+            collector.collect_body_and_predicate_taits();
+        }
+        // Walk over the type of the item to find opaques.
+        DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
+            let span = match tcx.hir().get_by_def_id(item).ty() {
+                Some(ty) => ty.span,
+                _ => tcx.def_span(item),
+            };
+            collector.visit_spanned(span, tcx.type_of(item).subst_identity());
+            collector.collect_body_and_predicate_taits();
+        }
         // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
-        DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
-            let mut collector = OpaqueTypeCollector::new(tcx, item);
-            match kind {
-                // Walk over the signature of the function-like to find the opaques.
-                DefKind::AssocFn | DefKind::Fn => {
-                    let ty_sig = tcx.fn_sig(item).subst_identity();
-                    let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
-                    // Walk over the inputs and outputs manually in order to get good spans for them.
-                    collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
-                    for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
-                        collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
-                    }
-                }
-                // Walk over the type of the item to find opaques.
-                DefKind::AssocTy | DefKind::AssocConst => {
-                    let span = match tcx.hir().get_by_def_id(item).ty() {
-                        Some(ty) => ty.span,
-                        _ => tcx.def_span(item),
-                    };
-                    collector.visit_spanned(span, tcx.type_of(item).subst_identity());
-                }
-                _ => unreachable!(),
+        DefKind::TyAlias | DefKind::AssocTy => {
+            tcx.type_of(item).subst_identity().visit_with(&mut collector);
+        }
+        DefKind::OpaqueTy => {
+            for (pred, span) in tcx.explicit_item_bounds(item).subst_identity_iter_copied() {
+                collector.visit_spanned(span, pred);
             }
-            tcx.arena.alloc_from_iter(collector.opaques)
         }
         DefKind::Mod
         | DefKind::Struct
@@ -222,31 +309,26 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
         | DefKind::Enum
         | DefKind::Variant
         | DefKind::Trait
-        | DefKind::TyAlias
         | DefKind::ForeignTy
         | DefKind::TraitAlias
         | DefKind::TyParam
-        | DefKind::Const
         | DefKind::ConstParam
-        | DefKind::Static(_)
         | DefKind::Ctor(_, _)
         | DefKind::Macro(_)
         | DefKind::ExternCrate
         | DefKind::Use
         | DefKind::ForeignMod
-        | DefKind::AnonConst
-        | DefKind::InlineConst
-        | DefKind::OpaqueTy
         | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
-        | DefKind::Impl { .. }
-        | DefKind::Closure
-        | DefKind::Generator => {
-            span_bug!(tcx.def_span(item), "{kind:?} is type checked as part of its parent")
+        | DefKind::Impl { .. } => {}
+        // Closures and generators are type checked with their parent, so there is no difference here.
+        DefKind::Closure | DefKind::Generator | DefKind::InlineConst => {
+            return tcx.opaque_types_defined_by(tcx.local_parent(item));
         }
     }
+    tcx.arena.alloc_from_iter(collector.opaques)
 }
 
 pub(super) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 466616cd22b..6e5c50492c6 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -103,7 +103,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
     let result = tcx.mk_type_list_from_iter(
         def.variants()
             .iter()
-            .filter_map(|v| v.fields.raw.last())
+            .filter_map(|v| v.tail_opt())
             .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())),
     );
 
diff --git a/src/tools/clippy/clippy_lints/src/incorrect_impls.rs b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs
index 13cc0b23ba3..7b95116ee4e 100644
--- a/src/tools/clippy/clippy_lints/src/incorrect_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs
@@ -82,7 +82,7 @@ impl LateLintPass<'_> for IncorrectImpls {
                     cx,
                     hir_ty_to_ty(cx.tcx, imp.self_ty),
                     copy_def_id,
-                    trait_impl.substs,
+                    &[],
                 )
         {
             if impl_item.ident.name == sym::clone {
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.fixed b/src/tools/clippy/tests/ui/needless_raw_string.fixed
index 6438e46977b..b36912efbb2 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string.fixed
+++ b/src/tools/clippy/tests/ui/needless_raw_string.fixed
@@ -10,7 +10,8 @@ fn main() {
     b"aaa";
     br#""aaa""#;
     br#"\s"#;
-    c"aaa";
-    cr#""aaa""#;
-    cr#"\s"#;
+    // currently disabled: https://github.com/rust-lang/rust/issues/113333
+    // cr#"aaa"#;
+    // cr#""aaa""#;
+    // cr#"\s"#;
 }
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.rs b/src/tools/clippy/tests/ui/needless_raw_string.rs
index f7ddc68265e..8f48e7dab2a 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string.rs
+++ b/src/tools/clippy/tests/ui/needless_raw_string.rs
@@ -10,7 +10,8 @@ fn main() {
     br#"aaa"#;
     br#""aaa""#;
     br#"\s"#;
-    cr#"aaa"#;
-    cr#""aaa""#;
-    cr#"\s"#;
+    // currently disabled: https://github.com/rust-lang/rust/issues/113333
+    // cr#"aaa"#;
+    // cr#""aaa""#;
+    // cr#"\s"#;
 }
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.stderr b/src/tools/clippy/tests/ui/needless_raw_string.stderr
index 0179978b7b0..cfb07b647d7 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string.stderr
+++ b/src/tools/clippy/tests/ui/needless_raw_string.stderr
@@ -12,11 +12,5 @@ error: unnecessary raw string literal
 LL |     br#"aaa"#;
    |     ^^^^^^^^^ help: try: `b"aaa"`
 
-error: unnecessary raw string literal
-  --> $DIR/needless_raw_string.rs:13:5
-   |
-LL |     cr#"aaa"#;
-   |     ^^^^^^^^^ help: try: `c"aaa"`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed
index e4d7d8fb017..c8507c72715 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed
+++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed
@@ -12,8 +12,9 @@ fn main() {
     br#"Hello "world"!"#;
     br####" "### "## "# "####;
     br###" "aa" "# "## "###;
-    cr#"aaa"#;
-    cr#"Hello "world"!"#;
-    cr####" "### "## "# "####;
-    cr###" "aa" "# "## "###;
+    // currently disabled: https://github.com/rust-lang/rust/issues/113333
+    // cr#"aaa"#;
+    // cr##"Hello "world"!"##;
+    // cr######" "### "## "# "######;
+    // cr######" "aa" "# "## "######;
 }
diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs
index e2d85c52e78..912fbde1679 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs
+++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs
@@ -12,8 +12,9 @@ fn main() {
     br##"Hello "world"!"##;
     br######" "### "## "# "######;
     br######" "aa" "# "## "######;
-    cr#"aaa"#;
-    cr##"Hello "world"!"##;
-    cr######" "### "## "# "######;
-    cr######" "aa" "# "## "######;
+    // currently disabled: https://github.com/rust-lang/rust/issues/113333
+    // cr#"aaa"#;
+    // cr##"Hello "world"!"##;
+    // cr######" "### "## "# "######;
+    // cr######" "aa" "# "## "######;
 }
diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
index dff47a2d042..30e6783a38e 100644
--- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
+++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
@@ -36,23 +36,5 @@ error: unnecessary hashes around raw string literal
 LL |     br######" "aa" "# "## "######;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###`
 
-error: unnecessary hashes around raw string literal
-  --> $DIR/needless_raw_string_hashes.rs:16:5
-   |
-LL |     cr##"Hello "world"!"##;
-   |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr#"Hello "world"!"#`
-
-error: unnecessary hashes around raw string literal
-  --> $DIR/needless_raw_string_hashes.rs:17:5
-   |
-LL |     cr######" "### "## "# "######;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr####" "### "## "# "####`
-
-error: unnecessary hashes around raw string literal
-  --> $DIR/needless_raw_string_hashes.rs:18:5
-   |
-LL |     cr######" "aa" "# "## "######;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr###" "aa" "# "## "###`
-
-error: aborting due to 9 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 3a50f60b3a0..02b0dd16f91 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-bb548f964572f7fe652716f5897d9050a31c936e
+d4096e0412ac5de785d739a0aa2b1c1c7b9d3b7d
diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
index 303c99834f5..843bb0284cf 100644
--- a/src/tools/miri/tests/pass/portable-simd-ptrs.rs
+++ b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
@@ -6,7 +6,7 @@ use std::simd::*;
 
 fn main() {
     // Pointer casts
-    let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast_ptr();
+    let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast();
     let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr();
     let _ptrs = Simd::<*const i32, 4>::from_exposed_addr(addrs);
 }
diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
index 0d019b1f502..3f49020bbea 100644
--- a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
+++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
@@ -11,7 +11,7 @@ fn define() -> Bar {
 
 type Foo2 = impl Debug;
 
-fn define2() {
+fn define2(_: Foo2) {
     let x = || -> Foo2 { 42 };
 }
 
@@ -20,13 +20,13 @@ type Foo3 = impl Debug;
 fn define3(x: Foo3) {
     let y: i32 = x;
 }
-fn define3_1() {
+fn define3_1(_: Foo3) {
     define3(42)
 }
 
 type Foo4 = impl Debug;
 
-fn define4() {
+fn define4(_: Foo4) {
     let y: Foo4 = 42;
 }
 
diff --git a/tests/ui/generic-associated-types/issue-90014-tait.rs b/tests/ui/generic-associated-types/issue-90014-tait.rs
new file mode 100644
index 00000000000..bc3a4e12965
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-90014-tait.rs
@@ -0,0 +1,23 @@
+//! This test is reporting the wrong error. We need
+//! more inherent associated type tests that use opaque types
+//! in general. Some variant of this test should compile successfully.
+// known-bug: unknown
+// edition:2018
+
+#![feature(impl_trait_in_assoc_type, inherent_associated_types)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+struct Foo<'a>(&'a mut ());
+
+impl Foo<'_> {
+    type Fut<'a> = impl Future<Output = ()>;
+    //^ ERROR: the type `&mut ()` does not fulfill the required lifetime
+
+    fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
+        async { () }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/generic-associated-types/issue-90014-tait.stderr b/tests/ui/generic-associated-types/issue-90014-tait.stderr
new file mode 100644
index 00000000000..8330a387ecd
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-90014-tait.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-90014-tait.rs:19:9
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |                    ------------------------ the expected future
+...
+LL |     fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
+   |                                  ------------- expected `Foo<'_>::Fut<'a>` because of return type
+LL |         async { () }
+   |         ^^^^^^^^^^^^ expected future, found `async` block
+   |
+   = note: expected opaque type `Foo<'_>::Fut<'a>`
+            found `async` block `[async block@$DIR/issue-90014-tait.rs:19:9: 19:21]`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/issue-90014-tait.rs:18:8
+   |
+LL |     fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
+   |        ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.rs b/tests/ui/generic-associated-types/issue-90014-tait2.rs
new file mode 100644
index 00000000000..dacbc93dec8
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.rs
@@ -0,0 +1,46 @@
+//! This test checks that opaque type collection doesn't try to normalize the projection
+//! without respecting its binders (which would ICE).
+//! Unfortunately we don't even reach opaque type collection, as we ICE in typeck before that.
+// known-bug: #109281
+// failure-status: 101
+// error-pattern:internal compiler error
+// normalize-stderr-test "internal compiler error.*" -> ""
+// normalize-stderr-test "DefId\([^)]*\)" -> "..."
+// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
+// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
+// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
+// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
+// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
+// normalize-stderr-test "thread.*panicked.*\n" -> ""
+// normalize-stderr-test "stack backtrace:\n" -> ""
+// normalize-stderr-test "\s\d{1,}: .*\n" -> ""
+// normalize-stderr-test "\s at .*\n" -> ""
+// normalize-stderr-test ".*note: Some details.*\n" -> ""
+// normalize-stderr-test "\n\n[ ]*\n" -> ""
+// normalize-stderr-test "compiler/.*: projection" -> "projection"
+// edition:2018
+
+#![feature(type_alias_impl_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+struct Foo<'a>(&'a mut ());
+
+type Fut<'a> = impl Future<Output = ()>;
+
+trait Trait<'x> {
+    type Thing;
+}
+
+impl<'x, T: 'x> Trait<'x> for (T,) {
+    type Thing = T;
+}
+
+impl Foo<'_> {
+    fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> {
+        Box::new((async { () },))
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
new file mode 100644
index 00000000000..3187be3334c
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
@@ -0,0 +1,12 @@
+error: 
+  --> $DIR/issue-90014-tait2.rs:41:27
+   |
+LL |     fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> {
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^query stack during panic:
+#0 [typeck] type-checking `<impl at $DIR/issue-90014-tait2.rs:40:1: 40:13>::make_fut`
+#1 [type_of] computing type of `Fut::{opaque#0}`
+#2 [check_mod_item_types] checking item types in top-level module
+#3 [analysis] running analysis passes on this crate
+end of query stack
+error: aborting due to previous error
+
diff --git a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs
index d2c34792035..7a51aac44e2 100644
--- a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs
+++ b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs
@@ -8,8 +8,10 @@ impl<T: Fn(i32)> SuperExpectation for T {}
 
 type Foo = impl SuperExpectation;
 
-fn main() {
+fn bop(_: Foo) {
     let _: Foo = |x| {
         let _ = x.to_string();
     };
 }
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-assoc-type.rs b/tests/ui/impl-trait/in-assoc-type.rs
index 36c54bdd6de..38ad2fa6f02 100644
--- a/tests/ui/impl-trait/in-assoc-type.rs
+++ b/tests/ui/impl-trait/in-assoc-type.rs
@@ -1,3 +1,6 @@
+//! This test checks that we don't allow registering hidden types for
+//! opaque types from other impls.
+
 #![feature(impl_trait_in_assoc_type)]
 
 trait Foo<T> {
diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr
index ab3f3a14410..af60da07cac 100644
--- a/tests/ui/impl-trait/in-assoc-type.stderr
+++ b/tests/ui/impl-trait/in-assoc-type.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/in-assoc-type.rs:17:22
+  --> $DIR/in-assoc-type.rs:20:22
    |
 LL |     type Bar = impl std::fmt::Debug;
    |                -------------------- the expected opaque type
@@ -12,7 +12,7 @@ LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
    = note: expected opaque type `<() as Foo<()>>::Bar`
                 found unit type `()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/in-assoc-type.rs:17:8
+  --> $DIR/in-assoc-type.rs:20:8
    |
 LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
    |        ^^^
diff --git a/tests/ui/impl-trait/issues/issue-70877.rs b/tests/ui/impl-trait/issues/issue-70877.rs
index 8169cfafac7..df772298674 100644
--- a/tests/ui/impl-trait/issues/issue-70877.rs
+++ b/tests/ui/impl-trait/issues/issue-70877.rs
@@ -25,12 +25,12 @@ fn ham() -> Foo {
     Bar(1)
 }
 
-fn oof() -> impl std::fmt::Debug {
+fn oof(_: Foo) -> impl std::fmt::Debug {
     let mut bar = ham();
     let func = bar.next().unwrap();
     return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type
 }
 
 fn main() {
-    let _ = oof();
+    let _ = oof(ham());
 }
diff --git a/tests/ui/impl-trait/issues/issue-70877.stderr b/tests/ui/impl-trait/issues/issue-70877.stderr
index 8813bff3c35..ee140e6f6c4 100644
--- a/tests/ui/impl-trait/issues/issue-70877.stderr
+++ b/tests/ui/impl-trait/issues/issue-70877.stderr
@@ -5,10 +5,10 @@ LL |     return func(&"oof");
    |            ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
    |
 note: opaque type whose hidden type is being assigned
-  --> $DIR/issue-70877.rs:28:13
+  --> $DIR/issue-70877.rs:28:19
    |
-LL | fn oof() -> impl std::fmt::Debug {
-   |             ^^^^^^^^^^^^^^^^^^^^
+LL | fn oof(_: Foo) -> impl std::fmt::Debug {
+   |                   ^^^^^^^^^^^^^^^^^^^^
 note: opaque type being used as hidden type
   --> $DIR/issue-70877.rs:4:15
    |
diff --git a/tests/ui/impl-trait/issues/issue-74282.rs b/tests/ui/impl-trait/issues/issue-74282.rs
index 654de0cd025..51bd5f67ed5 100644
--- a/tests/ui/impl-trait/issues/issue-74282.rs
+++ b/tests/ui/impl-trait/issues/issue-74282.rs
@@ -3,9 +3,12 @@
 type Closure = impl Fn() -> u64;
 struct Anonymous(Closure);
 
-fn main() {
+fn bop(_: Closure) {
     let y = || -> Closure { || 3 };
-    Anonymous(|| { //~ ERROR mismatched types
-        3 //~^ ERROR mismatched types
+    Anonymous(|| {
+        //~^ ERROR mismatched types
+        3 //~^^ ERROR mismatched types
     })
 }
+
+fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr
index 724f3c5d674..d43e9fee0b3 100644
--- a/tests/ui/impl-trait/issues/issue-74282.stderr
+++ b/tests/ui/impl-trait/issues/issue-74282.stderr
@@ -8,6 +8,7 @@ LL |       Anonymous(|| {
    |  _____---------_^
    | |     |
    | |     arguments to this struct are incorrect
+LL | |
 LL | |         3
 LL | |     })
    | |_____^ expected opaque type, found closure
@@ -25,15 +26,20 @@ LL | struct Anonymous(Closure);
 error[E0308]: mismatched types
   --> $DIR/issue-74282.rs:8:5
    |
-LL |   fn main() {
-   |             - expected `()` because of default return type
-LL |       let y = || -> Closure { || 3 };
 LL | /     Anonymous(|| {
+LL | |
 LL | |         3
 LL | |     })
-   | |      ^- help: consider using a semicolon here: `;`
-   | |______|
-   |        expected `()`, found `Anonymous`
+   | |______^ expected `()`, found `Anonymous`
+   |
+help: consider using a semicolon here
+   |
+LL |     });
+   |       +
+help: try adding a return type
+   |
+LL | fn bop(_: Closure) -> Anonymous {
+   |                    ++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.rs b/tests/ui/impl-trait/issues/issue-78722-2.rs
new file mode 100644
index 00000000000..cf5361e1e60
--- /dev/null
+++ b/tests/ui/impl-trait/issues/issue-78722-2.rs
@@ -0,0 +1,22 @@
+//! test that we cannot register hidden types for opaque types
+//! declared outside an anonymous constant.
+// edition:2018
+
+#![feature(type_alias_impl_trait)]
+
+type F = impl core::future::Future<Output = u8>;
+
+struct Bug {
+    V1: [(); {
+        fn concrete_use() -> F {
+            //~^ ERROR future that resolves to `u8`, but it resolves to `()`
+            async {}
+        }
+        let f: F = async { 1 };
+        //~^ ERROR item constrains opaque type that is not in its signature
+        //~| ERROR `async` blocks are not allowed in constants
+        1
+    }],
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr
new file mode 100644
index 00000000000..6db603e7751
--- /dev/null
+++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr
@@ -0,0 +1,32 @@
+error[E0658]: `async` blocks are not allowed in constants
+  --> $DIR/issue-78722-2.rs:15:20
+   |
+LL |         let f: F = async { 1 };
+   |                    ^^^^^^^^^^^
+   |
+   = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
+   = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
+
+error[E0271]: expected `[async block@$DIR/issue-78722-2.rs:13:13: 13:21]` to be a future that resolves to `u8`, but it resolves to `()`
+  --> $DIR/issue-78722-2.rs:11:30
+   |
+LL |         fn concrete_use() -> F {
+   |                              ^ expected `()`, found `u8`
+
+error: item constrains opaque type that is not in its signature
+  --> $DIR/issue-78722-2.rs:15:20
+   |
+LL |         let f: F = async { 1 };
+   |                    ^^^^^^^^^^^
+   |
+   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
+note: this item must mention the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/issue-78722-2.rs:15:20
+   |
+LL |         let f: F = async { 1 };
+   |                    ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0271, E0658.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/impl-trait/issues/issue-78722.rs b/tests/ui/impl-trait/issues/issue-78722.rs
index 7b5ab5f2298..75ccc8d8e8a 100644
--- a/tests/ui/impl-trait/issues/issue-78722.rs
+++ b/tests/ui/impl-trait/issues/issue-78722.rs
@@ -2,10 +2,9 @@
 
 #![feature(type_alias_impl_trait)]
 
-type F = impl core::future::Future<Output = u8>;
-
 struct Bug {
     V1: [(); {
+        type F = impl core::future::Future<Output = u8>;
         fn concrete_use() -> F {
             //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()`
             async {}
diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.stderr
index 05a2c135cf7..36340a0bab4 100644
--- a/tests/ui/impl-trait/issues/issue-78722.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `async` blocks are not allowed in constants
-  --> $DIR/issue-78722.rs:13:20
+  --> $DIR/issue-78722.rs:12:20
    |
 LL |         let f: F = async { 1 };
    |                    ^^^^^^^^^^^
@@ -7,8 +7,8 @@ LL |         let f: F = async { 1 };
    = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
    = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
 
-error[E0271]: expected `[async block@$DIR/issue-78722.rs:11:13: 11:21]` to be a future that resolves to `u8`, but it resolves to `()`
-  --> $DIR/issue-78722.rs:9:30
+error[E0271]: expected `[async block@$DIR/issue-78722.rs:10:13: 10:21]` to be a future that resolves to `u8`, but it resolves to `()`
+  --> $DIR/issue-78722.rs:8:30
    |
 LL |         fn concrete_use() -> F {
    |                              ^ expected `()`, found `u8`
diff --git a/tests/ui/lint/issue-99387.rs b/tests/ui/lint/issue-99387.rs
index 616eb935e93..ba5031167e3 100644
--- a/tests/ui/lint/issue-99387.rs
+++ b/tests/ui/lint/issue-99387.rs
@@ -1,4 +1,5 @@
-// check-pass
+//! Test that we don't follow through projections to find
+//! opaque types.
 
 #![feature(type_alias_impl_trait)]
 #![allow(private_in_public)]
@@ -18,6 +19,7 @@ impl<'a> Tr for &'a () {
 }
 
 pub fn ohno<'a>() -> <&'a () as Tr>::Item {
+    //~^ ERROR item constrains opaque type that is not in its signature
     None.into_iter()
 }
 
diff --git a/tests/ui/lint/issue-99387.stderr b/tests/ui/lint/issue-99387.stderr
new file mode 100644
index 00000000000..3a46ce7e195
--- /dev/null
+++ b/tests/ui/lint/issue-99387.stderr
@@ -0,0 +1,15 @@
+error: item constrains opaque type that is not in its signature
+  --> $DIR/issue-99387.rs:21:22
+   |
+LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item {
+   |                      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
+note: this item must mention the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/issue-99387.rs:21:8
+   |
+LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item {
+   |        ^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs
index 028222f4e6d..309bee8aa8c 100644
--- a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs
+++ b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs
@@ -12,7 +12,7 @@ type Foo<T: Send, U> = impl NeedsSend<T>;
 trait NeedsSend<T> {}
 impl<T: Send> NeedsSend<T> for T {}
 
-fn define<A, B: Send>(a: A, b: B) {
+fn define<A, B: Send>(a: A, b: B, _: Foo<B, A>) {
     let y: Option<Foo<B, A>> = Some(b);
 }
 
diff --git a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs
index 5a0dcd0e8cc..08f14d7494d 100644
--- a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs
+++ b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs
@@ -12,11 +12,13 @@ type Foo = impl Sized;
 
 fn needs_send<T: Send>() {}
 
-fn test() {
+fn test(_: Foo) {
     needs_send::<Foo>();
     //[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
 }
 
-fn main() {
+fn defines(_: Foo) {
     let _: Foo = ();
 }
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/tait-eq-proj-2.rs b/tests/ui/traits/new-solver/tait-eq-proj-2.rs
index 99a3d02bd1a..77ea8bc246e 100644
--- a/tests/ui/traits/new-solver/tait-eq-proj-2.rs
+++ b/tests/ui/traits/new-solver/tait-eq-proj-2.rs
@@ -8,9 +8,11 @@
 
 type Tait = impl Iterator<Item = impl Sized>;
 
-fn mk<T>() -> T { todo!() }
+fn mk<T>() -> T {
+    todo!()
+}
 
-fn a() {
+fn a(_: Tait) {
     let x: Tait = mk();
     let mut array = mk();
     let mut z = IntoIterator::into_iter(array);
diff --git a/tests/ui/traits/new-solver/tait-eq-proj.rs b/tests/ui/traits/new-solver/tait-eq-proj.rs
index 01141b2819a..01ef2ec953a 100644
--- a/tests/ui/traits/new-solver/tait-eq-proj.rs
+++ b/tests/ui/traits/new-solver/tait-eq-proj.rs
@@ -28,7 +28,7 @@ goals together. Essentially:
 
 */
 
-fn a() {
+fn a(_: Tait) {
     let _: Tait = IntoIterator::into_iter([0i32; 32]);
 }
 
diff --git a/tests/ui/traits/new-solver/tait-eq-tait.rs b/tests/ui/traits/new-solver/tait-eq-tait.rs
index 532c4c39bd4..70d9dc0eaa8 100644
--- a/tests/ui/traits/new-solver/tait-eq-tait.rs
+++ b/tests/ui/traits/new-solver/tait-eq-tait.rs
@@ -6,12 +6,13 @@
 
 #![feature(type_alias_impl_trait)]
 
-type Tait = impl Sized;
-type Tait2 = impl Sized;
-
-fn mk<T>() -> T { todo!() }
+fn mk<T>() -> T {
+    todo!()
+}
 
 fn main() {
+    type Tait = impl Sized;
+    type Tait2 = impl Sized;
     let x: Tait = 1u32;
     let y: Tait2 = x;
 }
diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs
index 0bcc9e002ca..4e9f65d88a1 100644
--- a/tests/ui/type-alias-impl-trait/bound_reduction2.rs
+++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs
@@ -13,6 +13,7 @@ trait Trait<U> {}
 impl<W> Trait<W> for () {}
 
 fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+    //~^ ERROR non-defining opaque type use
     ()
     //~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
 }
diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
index 3c259bd9e97..14f9dbbdb4e 100644
--- a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
+++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
@@ -1,5 +1,17 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/bound_reduction2.rs:15:46
+   |
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+   |                                              ^^^^^^^^^^^^^ argument `<T as TraitWithAssoc>::Assoc` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/bound_reduction2.rs:9:15
+   |
+LL | type Foo<V> = impl Trait<V>;
+   |               ^^^^^^^^^^^^^
+
 error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
-  --> $DIR/bound_reduction2.rs:16:5
+  --> $DIR/bound_reduction2.rs:17:5
    |
 LL | type Foo<V> = impl Trait<V>;
    |          - this generic parameter must be used with a generic type parameter
@@ -7,6 +19,6 @@ LL | type Foo<V> = impl Trait<V>;
 LL |     ()
    |     ^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/closure_args.rs b/tests/ui/type-alias-impl-trait/closure_args.rs
index c5e7af81d3d..243f9cd6d4f 100644
--- a/tests/ui/type-alias-impl-trait/closure_args.rs
+++ b/tests/ui/type-alias-impl-trait/closure_args.rs
@@ -11,6 +11,13 @@ fn run<F: FnOnce(Input) -> ()>(f: F, i: Input) {
     f(i);
 }
 
-fn main() {
-    run(|x: u32| {println!("{x}");}, 0);
+fn bop(_: Input) {
+    run(
+        |x: u32| {
+            println!("{x}");
+        },
+        0,
+    );
 }
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/closure_args2.rs b/tests/ui/type-alias-impl-trait/closure_args2.rs
index 82386c280a8..1dd5c3e40cd 100644
--- a/tests/ui/type-alias-impl-trait/closure_args2.rs
+++ b/tests/ui/type-alias-impl-trait/closure_args2.rs
@@ -1,10 +1,12 @@
-// run-pass
+// check-pass
 
 #![feature(type_alias_impl_trait)]
 
 trait Foo {
     // This was reachable in https://github.com/rust-lang/rust/issues/100800
-    fn foo(&self) { unreachable!() }
+    fn foo(&self) {
+        unreachable!()
+    }
 }
 impl<T> Foo for T {}
 
@@ -14,10 +16,17 @@ impl B {
 }
 
 type Input = impl Foo;
-fn run1<F: FnOnce(Input)>(f: F, i: Input) {f(i)}
-fn run2<F: FnOnce(B)>(f: F, i: B) {f(i)}
+fn run1<F: FnOnce(Input)>(f: F, i: Input) {
+    f(i)
+}
+fn run2<F: FnOnce(B)>(f: F, i: B) {
+    f(i)
+}
 
-fn main() {
-    run1(|x: B| {x.foo()}, B);
-    run2(|x: B| {x.foo()}, B);
+fn bop() -> Input {
+    run1(|x: B| x.foo(), B);
+    run2(|x: B| x.foo(), B);
+    panic!()
 }
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
index fbfa0ccf1e8..d60f1ffbccc 100644
--- a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
+++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
@@ -19,6 +19,11 @@ LL |     ""
    |
    = note: expected opaque type `Boo`
                 found reference `&'static str`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/declared_but_not_defined_in_scope.rs:10:4
+   |
+LL | fn bomp() -> boo::Boo {
+   |    ^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
index e5bfbfdae91..b2842df150a 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
@@ -2,7 +2,7 @@
 
 type Tait<'a> = impl Sized + 'a;
 
-fn foo<'a, 'b>() {
+fn foo<'a, 'b>() -> Tait<'a> {
     if false {
         if { return } {
             let y: Tait<'b> = 1i32;
@@ -10,6 +10,7 @@ fn foo<'a, 'b>() {
         }
     }
     let x: Tait<'a> = ();
+    x
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
index f2eb7bc4dc7..b138f9d5c45 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
@@ -5,10 +5,10 @@ LL |             let y: Tait<'b> = 1i32;
    |                               ^^^^ expected `()`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type-2.rs:12:23
+  --> $DIR/different_defining_uses_never_type-2.rs:7:14
    |
-LL |     let x: Tait<'a> = ();
-   |                       ^^
+LL |         if { return } {
+   |              ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
index 2b30a9cd57c..a4ac27378e1 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
@@ -2,7 +2,7 @@
 
 type Tait<T> = impl Sized;
 
-fn foo<T, U>() {
+fn foo<T, U>() -> Tait<T> {
     if false {
         if { return } {
             let y: Tait<U> = 1i32;
@@ -10,6 +10,7 @@ fn foo<T, U>() {
         }
     }
     let x: Tait<T> = ();
+    x
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
index 9d938a61600..14ced341854 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
@@ -9,6 +9,7 @@ impl<'a, T: ?Sized> Captures<'a> for T {}
 type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
 
 fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
+    //~^ ERROR non-defining opaque type use
     t
     //~^ ERROR non-defining opaque type use
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
index 72e1ef4b492..4da69a705c0 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
@@ -1,5 +1,17 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_lifetime_param.rs:12:5
+  --> $DIR/generic_duplicate_lifetime_param.rs:11:26
+   |
+LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
+   |                          ^^^^^^^^^^^ generic argument `'a` used twice
+   |
+note: for this opaque type
+  --> $DIR/generic_duplicate_lifetime_param.rs:9:20
+   |
+LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_lifetime_param.rs:13:5
    |
 LL |     t
    |     ^
@@ -10,5 +22,5 @@ note: lifetime used multiple times
 LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
    |          ^^  ^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
index 80462f8ac04..1e391b55a4f 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
@@ -1,5 +1,12 @@
 #![feature(type_alias_impl_trait)]
 
+//! This test checks various cases where we are using the same
+//! generic parameter twice in the parameter list of a TAIT.
+//! Within defining scopes that is not legal, because the hidden type
+//! is not fully defined then. This could cause us to have a TAIT
+//! that doesn't have a hidden type for all possible combinations of generic
+//! parameters passed to it.
+
 use std::fmt::Debug;
 
 fn main() {}
@@ -7,7 +14,6 @@ fn main() {}
 // test that unused generic parameters are ok
 type TwoTys<T, U> = impl Debug;
 
-
 pub trait Captures<'a> {}
 
 impl<'a, T: ?Sized> Captures<'a> for T {}
@@ -16,18 +22,20 @@ type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
 
 type TwoConsts<const X: usize, const Y: usize> = impl Debug;
 
-
 fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
+    //~^ ERROR non-defining opaque type use in defining scope
     t
     //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
+    //~^ ERROR non-defining opaque type use in defining scope
     t
     //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
+    //~^ ERROR non-defining opaque type use in defining scope
     t
     //~^ ERROR non-defining opaque type use in defining scope
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index 98e4bfea10d..d8330771d30 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -1,38 +1,74 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:21:5
+  --> $DIR/generic_duplicate_param_use.rs:25:30
+   |
+LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
+   |                              ^^^^^^^^^^^^ generic argument `T` used twice
+   |
+note: for this opaque type
+  --> $DIR/generic_duplicate_param_use.rs:15:21
+   |
+LL | type TwoTys<T, U> = impl Debug;
+   |                     ^^^^^^^^^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use.rs:27:5
    |
 LL |     t
    |     ^
    |
 note: type used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:8:13
+  --> $DIR/generic_duplicate_param_use.rs:15:13
    |
 LL | type TwoTys<T, U> = impl Debug;
    |             ^  ^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:26:5
+  --> $DIR/generic_duplicate_param_use.rs:31:36
+   |
+LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
+   |                                    ^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
+   |
+note: for this opaque type
+  --> $DIR/generic_duplicate_param_use.rs:21:29
+   |
+LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use.rs:33:5
    |
 LL |     t
    |     ^
    |
 note: lifetime used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:15:19
+  --> $DIR/generic_duplicate_param_use.rs:21:19
    |
 LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
    |                   ^^  ^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:31:5
+  --> $DIR/generic_duplicate_param_use.rs:37:50
+   |
+LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
+   |                                                  ^^^^^^^^^^^^^^^ generic argument `N` used twice
+   |
+note: for this opaque type
+  --> $DIR/generic_duplicate_param_use.rs:23:50
+   |
+LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
+   |                                                  ^^^^^^^^^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use.rs:39:5
    |
 LL |     t
    |     ^
    |
 note: constant used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:17:16
+  --> $DIR/generic_duplicate_param_use.rs:23:16
    |
 LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
    |                ^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
index e7b8567b9a2..68f4c6923ae 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -13,16 +13,19 @@ type OneConst<const X: usize> = impl Debug;
 // Not defining uses, because they doesn't define *all* possible generics.
 
 fn concrete_ty() -> OneTy<u32> {
+    //~^ ERROR: non-defining opaque type use in defining scope
     5u32
-    //~^ ERROR expected generic type parameter, found `u32`
+    //~^ ERROR: expected generic type parameter, found `u32`
 }
 
 fn concrete_lifetime() -> OneLifetime<'static> {
+    //~^ ERROR: non-defining opaque type use in defining scope
     6u32
-    //~^ ERROR expected generic lifetime parameter, found `'static`
+    //~^ ERROR: expected generic lifetime parameter, found `'static`
 }
 
 fn concrete_const() -> OneConst<{ 123 }> {
+    //~^ ERROR: non-defining opaque type use in defining scope
     7u32
-    //~^ ERROR expected generic constant parameter, found `123`
+    //~^ ERROR: expected generic constant parameter, found `123`
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
index 966fe823f02..e3b7b1a76b0 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -1,5 +1,17 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/generic_nondefining_use.rs:15:21
+   |
+LL | fn concrete_ty() -> OneTy<u32> {
+   |                     ^^^^^^^^^^ argument `u32` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/generic_nondefining_use.rs:7:17
+   |
+LL | type OneTy<T> = impl Debug;
+   |                 ^^^^^^^^^^
+
 error[E0792]: expected generic type parameter, found `u32`
-  --> $DIR/generic_nondefining_use.rs:16:5
+  --> $DIR/generic_nondefining_use.rs:17:5
    |
 LL | type OneTy<T> = impl Debug;
    |            - this generic parameter must be used with a generic type parameter
@@ -7,8 +19,20 @@ LL | type OneTy<T> = impl Debug;
 LL |     5u32
    |     ^^^^
 
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/generic_nondefining_use.rs:21:27
+   |
+LL | fn concrete_lifetime() -> OneLifetime<'static> {
+   |                           ^^^^^^^^^^^^^^^^^^^^ argument `'static` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/generic_nondefining_use.rs:9:24
+   |
+LL | type OneLifetime<'a> = impl Debug;
+   |                        ^^^^^^^^^^
+
 error[E0792]: expected generic lifetime parameter, found `'static`
-  --> $DIR/generic_nondefining_use.rs:21:5
+  --> $DIR/generic_nondefining_use.rs:23:5
    |
 LL | type OneLifetime<'a> = impl Debug;
    |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@@ -16,8 +40,20 @@ LL | type OneLifetime<'a> = impl Debug;
 LL |     6u32
    |     ^^^^
 
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/generic_nondefining_use.rs:27:24
+   |
+LL | fn concrete_const() -> OneConst<{ 123 }> {
+   |                        ^^^^^^^^^^^^^^^^^ argument `123` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/generic_nondefining_use.rs:11:33
+   |
+LL | type OneConst<const X: usize> = impl Debug;
+   |                                 ^^^^^^^^^^
+
 error[E0792]: expected generic constant parameter, found `123`
-  --> $DIR/generic_nondefining_use.rs:26:5
+  --> $DIR/generic_nondefining_use.rs:29:5
    |
 LL | type OneConst<const X: usize> = impl Debug;
    |               -------------- this generic parameter must be used with a generic constant parameter
@@ -25,6 +61,6 @@ LL | type OneConst<const X: usize> = impl Debug;
 LL |     7u32
    |     ^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
index cdd8f6f1976..c60f5c11cd1 100644
--- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
+++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
@@ -5,12 +5,12 @@ fn main() {
     let x = wrong_generic(&y);
     let z: i32 = x;
     //~^ ERROR expected generic type parameter, found `&i32`
-}
 
-type WrongGeneric<T> = impl 'static;
-//~^ ERROR: at least one trait must be specified
+    type WrongGeneric<T> = impl 'static;
+    //~^ ERROR: at least one trait must be specified
 
-fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-    t
-    //~^ ERROR the parameter type `T` may not live long enough
+    fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+        t
+        //~^ ERROR the parameter type `T` may not live long enough
+    }
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index fa79e51e9f7..8c3a25dbfe7 100644
--- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -1,8 +1,8 @@
 error: at least one trait must be specified
-  --> $DIR/generic_type_does_not_live_long_enough.rs:10:24
+  --> $DIR/generic_type_does_not_live_long_enough.rs:9:28
    |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
+LL |     type WrongGeneric<T> = impl 'static;
+   |                            ^^^^^^^^^^^^
 
 error[E0792]: expected generic type parameter, found `&i32`
   --> $DIR/generic_type_does_not_live_long_enough.rs:6:18
@@ -10,19 +10,19 @@ error[E0792]: expected generic type parameter, found `&i32`
 LL |     let z: i32 = x;
    |                  ^
 ...
-LL | type WrongGeneric<T> = impl 'static;
-   |                   - this generic parameter must be used with a generic type parameter
+LL |     type WrongGeneric<T> = impl 'static;
+   |                       - this generic parameter must be used with a generic type parameter
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:14:5
+  --> $DIR/generic_type_does_not_live_long_enough.rs:13:9
    |
-LL |     t
-   |     ^ ...so that the type `T` will meet its required lifetime bounds
+LL |         t
+   |         ^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
-LL | fn wrong_generic<T: 'static>(t: T) -> WrongGeneric<T> {
-   |                   +++++++++
+LL |     fn wrong_generic<T: 'static>(t: T) -> WrongGeneric<T> {
+   |                       +++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params.rs
new file mode 100644
index 00000000000..db1a3a1c7a9
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params.rs
@@ -0,0 +1,28 @@
+//! This test checks that walking into binders
+//! during opaque type collection does not ICE or raise errors.
+
+// edition: 2021
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait B {
+    type C;
+}
+
+struct A;
+
+impl<'a> B for &'a A {
+    type C = ();
+}
+
+struct Terminator;
+
+type Successors<'a> = impl std::fmt::Debug + 'a;
+
+impl Terminator {
+    fn successors(&self, _: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {}
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
new file mode 100644
index 00000000000..f011e5b2148
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
@@ -0,0 +1,35 @@
+//! This test checks the behaviour of walking into binders
+//! and normalizing something behind them actually works.
+
+// edition: 2021
+
+#![feature(type_alias_impl_trait)]
+
+trait B {
+    type C;
+}
+
+struct A;
+
+impl<'a> B for &'a A {
+    type C = Tait;
+}
+
+type Tait = impl std::fmt::Debug;
+
+struct Terminator;
+
+type Successors<'a> = impl std::fmt::Debug + 'a;
+
+impl Terminator {
+    fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
+        f = g;
+        //~^ ERROR item constrains opaque type that is not in its signature
+    }
+}
+
+fn g(_: &()) -> String {
+    String::new()
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr
new file mode 100644
index 00000000000..39f584dd49c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr
@@ -0,0 +1,15 @@
+error: item constrains opaque type that is not in its signature
+  --> $DIR/higher_kinded_params2.rs:26:13
+   |
+LL |         f = g;
+   |             ^
+   |
+   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
+note: this item must mention the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/higher_kinded_params2.rs:25:8
+   |
+LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
+   |        ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
index 839a611cb71..6edfccaf7d1 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
@@ -24,7 +24,8 @@ type Successors<'a> = impl std::fmt::Debug + 'a;
 impl Terminator {
     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
         f = g;
-        //~^ ERROR: mismatched types
+        //~^ ERROR mismatched types
+        //~| ERROR item constrains opaque type that is not in its signature
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
index aaba9ad5ca7..14372d8f3e6 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
@@ -1,3 +1,16 @@
+error: item constrains opaque type that is not in its signature
+  --> $DIR/higher_kinded_params3.rs:26:13
+   |
+LL |         f = g;
+   |             ^
+   |
+   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
+note: this item must mention the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/higher_kinded_params3.rs:25:8
+   |
+LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
+   |        ^^^^^^^^^^
+
 error[E0308]: mismatched types
   --> $DIR/higher_kinded_params3.rs:26:9
    |
@@ -10,6 +23,6 @@ LL |         f = g;
    = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>`
               found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs
index 093afc25249..20175a4feca 100644
--- a/tests/ui/type-alias-impl-trait/inference-cycle.rs
+++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs
@@ -17,8 +17,8 @@ mod m {
         //~^ ERROR: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits
     }
 
-    fn baz() {
-        let f: Foo = ();
+    fn baz() -> Foo {
+        ()
     }
 
     fn is_send<T: Send>(_: T) {}
diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
index a3f126d56cf..a213dbba4ea 100644
--- a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
@@ -1,19 +1,22 @@
 #![feature(generators, generator_trait, rustc_attrs)]
 #![feature(type_alias_impl_trait)]
 
-use std::ops::Generator;
+// check-pass
 
-type GenOnce<Y, R> = impl Generator<Yield = Y, Return = R>;
+mod gen {
+    use std::ops::Generator;
 
-const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> {
-    move || {
-        yield yielding;
+    pub type GenOnce<Y, R> = impl Generator<Yield = Y, Return = R>;
 
-        return returning;
+    pub const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> {
+        move || {
+            yield yielding;
+
+            return returning;
+        }
     }
 }
 
-const FOO: GenOnce<usize, usize> = const_generator(10, 100);
+const FOO: gen::GenOnce<usize, usize> = gen::const_generator(10, 100);
 
-#[rustc_error]
-fn main() {} //~ ERROR
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr
deleted file mode 100644
index eb1c9603a60..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-53678-generator-and-const-fn.rs:19:1
-   |
-LL | fn main() {}
-   | ^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/tests/ui/type-alias-impl-trait/issue-57961.rs b/tests/ui/type-alias-impl-trait/issue-57961.rs
index 4aa5966ff25..61af7a0f625 100644
--- a/tests/ui/type-alias-impl-trait/issue-57961.rs
+++ b/tests/ui/type-alias-impl-trait/issue-57961.rs
@@ -11,8 +11,8 @@ impl Foo for () {
     //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
 }
 
-fn incoherent() {
-    let f: X = 22_i32;
+fn incoherent() -> X {
+    22_i32
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs
index c2f4c370807..48bd70bcca9 100644
--- a/tests/ui/type-alias-impl-trait/issue-60564.rs
+++ b/tests/ui/type-alias-impl-trait/issue-60564.rs
@@ -17,6 +17,7 @@ where
 {
     type BitsIter = IterBitsIter<T, E, u8>;
     fn iter_bits(self, n: u8) -> Self::BitsIter {
+        //~^ ERROR non-defining opaque type use
         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
         //~^ ERROR expected generic type parameter, found `u8`
     }
diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr
index f8fdb004d09..d42495e934d 100644
--- a/tests/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr
@@ -1,5 +1,17 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/issue-60564.rs:19:34
+   |
+LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
+   |                                  ^^^^^^^^^^^^^^ argument `u8` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/issue-60564.rs:8:30
+   |
+LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0792]: expected generic type parameter, found `u8`
-  --> $DIR/issue-60564.rs:20:9
+  --> $DIR/issue-60564.rs:21:9
    |
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    |                         - this generic parameter must be used with a generic type parameter
@@ -7,6 +19,6 @@ LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
 LL |         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs
index 7414611a748..ddea7aeb6cd 100644
--- a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs
+++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs
@@ -8,6 +8,9 @@
 
 pub type Closure = impl FnOnce();
 
-fn main() {
+fn bop() -> Closure {
     || -> Closure { || () };
+    panic!()
 }
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
index b91cbce3727..7b3e9e12405 100644
--- a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
+++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
@@ -11,7 +11,9 @@ type T = impl Sized;
 
 fn take(_: fn() -> T) {}
 
-fn main() {
+fn bop(_: T) {
     take(|| {});
     take(|| {});
 }
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
index 5e0a82a7286..9dcdb578568 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
@@ -7,7 +7,8 @@ trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
 
 fn f<'a>() -> Alias<'a, ()> {}
-//~^ ERROR expected generic type parameter, found `()`
+//~^ ERROR non-defining opaque type use
+//~| ERROR expected generic type parameter, found `()`
 
 fn main() {}
 
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
index 271743a4010..085bffe907b 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
@@ -1,3 +1,15 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/issue-68368-non-defining-use-2.rs:9:15
+   |
+LL | fn f<'a>() -> Alias<'a, ()> {}
+   |               ^^^^^^^^^^^^^ argument `()` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/issue-68368-non-defining-use-2.rs:7:21
+   |
+LL | type Alias<'a, U> = impl Trait<U>;
+   |                     ^^^^^^^^^^^^^
+
 error[E0792]: expected generic type parameter, found `()`
   --> $DIR/issue-68368-non-defining-use-2.rs:9:29
    |
@@ -7,6 +19,6 @@ LL |
 LL | fn f<'a>() -> Alias<'a, ()> {}
    |                             ^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
index 3b32260c96f..dfe2ee8204c 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
@@ -8,6 +8,7 @@ type Alias<'a, U> = impl Trait<U>;
 
 fn f<'a>() -> Alias<'a, ()> {}
 //~^ ERROR expected generic type parameter, found `()`
+//~| ERROR non-defining opaque type use
 
 fn main() {}
 
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
index 4d9a8d6eef9..ea704ffff97 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
@@ -1,3 +1,15 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/issue-68368-non-defining-use.rs:9:15
+   |
+LL | fn f<'a>() -> Alias<'a, ()> {}
+   |               ^^^^^^^^^^^^^ argument `()` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/issue-68368-non-defining-use.rs:7:21
+   |
+LL | type Alias<'a, U> = impl Trait<U>;
+   |                     ^^^^^^^^^^^^^
+
 error[E0792]: expected generic type parameter, found `()`
   --> $DIR/issue-68368-non-defining-use.rs:9:29
    |
@@ -7,6 +19,6 @@ LL |
 LL | fn f<'a>() -> Alias<'a, ()> {}
    |                             ^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
index 7657fe2fb1a..a0f8e48e268 100644
--- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
+++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
@@ -1,4 +1,6 @@
-// Regression test for #69136
+//! Regression test for #69136
+//! This test checks that the unknown lifetime `'a` doesn't cause
+//! ICEs after emitting the error.
 
 #![feature(type_alias_impl_trait)]
 
@@ -17,7 +19,6 @@ impl<T> WithAssoc<T> for () {
 type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
 //~^ ERROR use of undeclared lifetime name `'a`
 
-fn my_fun() -> Return<()> {}
-//~^ ERROR expected generic type parameter, found `()`
+fn my_fun<T>() -> Return<T> {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
index d1250786d93..b7af3f06d0d 100644
--- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
@@ -1,5 +1,5 @@
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65
+  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:19:65
    |
 LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
    |                                                                 ^^ undeclared lifetime
@@ -14,16 +14,6 @@ help: consider introducing lifetime `'a` here
 LL | type Return<'a, A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
    |             +++
 
-error[E0792]: expected generic type parameter, found `()`
-  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
-   |
-LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
-   |             - this generic parameter must be used with a generic type parameter
-...
-LL | fn my_fun() -> Return<()> {}
-   |                           ^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0261, E0792.
-For more information about an error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/type-alias-impl-trait/issue-70121.rs b/tests/ui/type-alias-impl-trait/issue-70121.rs
index dff0d89d465..bfd8d8872e3 100644
--- a/tests/ui/type-alias-impl-trait/issue-70121.rs
+++ b/tests/ui/type-alias-impl-trait/issue-70121.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(type_alias_impl_trait)]
 
 pub type Successors<'a> = impl Iterator<Item = &'a ()>;
@@ -17,6 +15,7 @@ impl<'a> Tr for &'a () {
 }
 
 pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
+    //~^ ERROR item constrains opaque type that is not in its signature
     None.into_iter()
 }
 
diff --git a/tests/ui/type-alias-impl-trait/issue-70121.stderr b/tests/ui/type-alias-impl-trait/issue-70121.stderr
new file mode 100644
index 00000000000..30c3ddd8659
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/issue-70121.stderr
@@ -0,0 +1,15 @@
+error: item constrains opaque type that is not in its signature
+  --> $DIR/issue-70121.rs:17:24
+   |
+LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
+   |                        ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
+note: this item must mention the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/issue-70121.rs:17:8
+   |
+LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
+   |        ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs
index 8d818d4a387..e7b04a48975 100644
--- a/tests/ui/type-alias-impl-trait/issue-77179.rs
+++ b/tests/ui/type-alias-impl-trait/issue-77179.rs
@@ -2,7 +2,7 @@
 
 #![feature(type_alias_impl_trait)]
 
-type Pointer<T> = impl std::ops::Deref<Target=T>;
+type Pointer<T> = impl std::ops::Deref<Target = T>;
 
 fn test() -> Pointer<_> {
     //~^ ERROR: the placeholder `_` is not allowed within types
diff --git a/tests/ui/type-alias-impl-trait/nested_in_closure.rs b/tests/ui/type-alias-impl-trait/nested_in_closure.rs
new file mode 100644
index 00000000000..362f3d53e88
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/nested_in_closure.rs
@@ -0,0 +1,17 @@
+#![feature(type_alias_impl_trait)]
+// check-pass
+
+fn main() {
+    let x = || {
+        type Tait = impl Sized;
+        let y: Tait = ();
+    };
+
+    let y = || {
+        type Tait = impl std::fmt::Debug;
+        let y: Tait = ();
+        y
+    };
+    let mut z = y();
+    z = ();
+}
diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
index 60b6e1aac62..07607516cc4 100644
--- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
+++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
@@ -10,11 +10,11 @@ mod my_mod {
         5i32
     }
 
-    pub fn get_foot() -> Foot {
+    pub fn get_foot(_: Foo) -> Foot {
         get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type
     }
 }
 
 fn main() {
-    let _: my_mod::Foot = my_mod::get_foot();
+    let _: my_mod::Foot = my_mod::get_foot(my_mod::get_foo());
 }
diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
index ae03a5b3e37..863282a0ff9 100644
--- a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
+++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
@@ -11,6 +11,11 @@ LL |     let _: &str = bomp();
    |
    = note: expected reference `&str`
             found opaque type `Boo`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/no_revealing_outside_defining_module.rs:14:4
+   |
+LL | fn bomp2() {
+   |    ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:19:5
@@ -25,6 +30,11 @@ LL |     ""
    |
    = note: expected opaque type `Boo`
                 found reference `&'static str`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/no_revealing_outside_defining_module.rs:18:4
+   |
+LL | fn bomp() -> boo::Boo {
+   |    ^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs
index 75015e41c3d..7943bb240f1 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.rs
+++ b/tests/ui/type-alias-impl-trait/reveal_local.rs
@@ -16,7 +16,7 @@ fn not_good() {
     //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
 }
 
-fn not_gooder() {
+fn not_gooder() -> Foo {
     // Constrain `Foo = u32`
     let x: Foo = 22_u32;
 
@@ -24,6 +24,8 @@ fn not_gooder() {
     // need extra roundabout logic to support it.
     is_send::<Foo>();
     //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
+
+    x
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr
index 202a87ecbb7..0c5ef4a6fb4 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.stderr
+++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr
@@ -78,8 +78,8 @@ LL | type Foo = impl Debug;
 note: ...which requires type-checking `not_gooder`...
   --> $DIR/reveal_local.rs:19:1
    |
-LL | fn not_gooder() {
-   | ^^^^^^^^^^^^^^^
+LL | fn not_gooder() -> Foo {
+   | ^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/reveal_local.rs:1:1
@@ -107,7 +107,7 @@ LL | type Foo = impl Debug;
 note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
   --> $DIR/reveal_local.rs:19:4
    |
-LL | fn not_gooder() {
+LL | fn not_gooder() -> Foo {
    |    ^^^^^^^^^^
 note: required by a bound in `is_send`
   --> $DIR/reveal_local.rs:10:15
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
index 4e9d1788b94..36161171555 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.rs
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
@@ -5,16 +5,16 @@ use std::fmt::Debug;
 
 type Foo = impl Debug;
 
-fn foo1() -> u32 {
+fn foo1() -> (u32, Foo) {
     let x: Foo = 22_u32;
-    x
+    (x, todo!())
 }
 
-fn foo2() -> u32 {
+fn foo2() -> (u32, Foo) {
     let x: Foo = 22_u32;
     let y: Foo = x;
     same_type((x, y)); //~ ERROR use of moved value
-    y //~ ERROR use of moved value
+    (y, todo!()) //~ ERROR use of moved value
 }
 
 fn same_type<T>(x: (T, T)) {}
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr
index 1dabe4586c5..7d7cad874fa 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr
@@ -9,14 +9,14 @@ LL |     same_type((x, y));
    |                ^ value used here after move
 
 error[E0382]: use of moved value: `y`
-  --> $DIR/type_of_a_let.rs:17:5
+  --> $DIR/type_of_a_let.rs:17:6
    |
 LL |     let y: Foo = x;
    |         - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait
 LL |     same_type((x, y));
    |                   - value moved here
-LL |     y
-   |     ^ value used here after move
+LL |     (y, todo!())
+   |      ^ value used here after move
 
 error: aborting due to 2 previous errors