diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index f3ee83fd4d218..51e1fe531dd1f 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_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 0738961d6ce48..166760166c108 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/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index f4779a3f26533..957a6bb348109 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 205e26d0edaac..c2d2e5f7e50f6 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/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index 05e5db9f0f3a3..d5619af2aae17 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_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index c9a8f8131dffb..63613b59020fb 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_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index e2ee347b639a1..1af8323b6e993 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_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 29de8bf0e53f5..570c3b245cd41 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/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
index 0d019b1f50206..3f49020bbea38 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 0000000000000..bc3a4e1296513
--- /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 0000000000000..8330a387ecd55
--- /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 0000000000000..dacbc93dec880
--- /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 0000000000000..3187be3334c5f
--- /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 d2c3479203573..7a51aac44e2e8 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 36c54bdd6de34..38ad2fa6f02ee 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 ab3f3a14410d0..af60da07cac31 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 8169cfafac711..df7722986744d 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 8813bff3c353e..ee140e6f6c43d 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 654de0cd0253c..51bd5f67ed574 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 724f3c5d6747c..d43e9fee0b359 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 0000000000000..cf5361e1e602c
--- /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 0000000000000..6db603e775175
--- /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 7b5ab5f229835..75ccc8d8e8a9a 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 05a2c135cf7c7..36340a0bab41a 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 616eb935e93d4..ba5031167e33d 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 0000000000000..3a46ce7e1952d
--- /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 028222f4e6dba..309bee8aa8c2c 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 5a0dcd0e8ccea..08f14d7494d79 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 99a3d02bd1aea..77ea8bc246e64 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 01141b2819a8d..01ef2ec953aeb 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 532c4c39bd499..70d9dc0eaa8ae 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 0bcc9e002ca04..4e9f65d88a129 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 3c259bd9e97cc..14f9dbbdb4e93 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 c5e7af81d3dd0..243f9cd6d4f4c 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 82386c280a8e3..1dd5c3e40cda6 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 fbfa0ccf1e8d9..d60f1ffbccc2d 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 e5bfbfdae91fd..b2842df150a3f 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 f2eb7bc4dc79b..b138f9d5c45ab 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 2b30a9cd57cf6..a4ac27378e1d8 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 9d938a61600f5..14ced3418542a 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 72e1ef4b4923b..4da69a705c07c 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 80462f8ac046c..1e391b55a4fac 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 98e4bfea10d63..d8330771d301d 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 e7b8567b9a217..68f4c6923ae18 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 966fe823f024d..e3b7b1a76b09d 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 cdd8f6f1976a5..c60f5c11cd18c 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 fa79e51e9f79f..8c3a25dbfe7de 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 0000000000000..db1a3a1c7a9d0
--- /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 0000000000000..f011e5b214813
--- /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 0000000000000..39f584dd49ca3
--- /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 839a611cb71a9..6edfccaf7d179 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 aaba9ad5ca704..14372d8f3e64d 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 093afc25249a7..20175a4feca00 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 a3f126d56cf20..a213dbba4ea01 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 eb1c9603a60d6..0000000000000
--- 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 4aa5966ff25d4..61af7a0f62500 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 c2f4c37080746..48bd70bcca950 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 f8fdb004d0989..d42495e934d33 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 7414611a74893..ddea7aeb6cda7 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 b91cbce3727f6..7b3e9e12405c7 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 5e0a82a72868a..9dcdb578568aa 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 271743a4010c8..085bffe907b4b 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 3b32260c96fe1..dfe2ee8204c75 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 4d9a8d6eef915..ea704ffff97ab 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 7657fe2fb1aee..a0f8e48e268c9 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 d1250786d938c..b7af3f06d0d9a 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 dff0d89d465dd..bfd8d8872e37f 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 0000000000000..30c3ddd8659d1
--- /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 8d818d4a387a6..e7b04a4897559 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 0000000000000..362f3d53e88bf
--- /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 60b6e1aac6281..07607516cc4bc 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 ae03a5b3e37bf..863282a0ff94d 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 75015e41c3da7..7943bb240f15b 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 202a87ecbb773..0c5ef4a6fb418 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 4e9d1788b94d8..36161171555ca 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 1dabe4586c5b9..7d7cad874faec 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