diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index a5a906658b89f..4b096a592344a 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -153,12 +153,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
                 if prev.ty != ty {
                     let guar = ty.error_reported().err().unwrap_or_else(|| {
-                        prev.report_mismatch(
-                            &OpaqueHiddenType { ty, span: concrete_type.span },
-                            opaque_type_key.def_id,
-                            infcx.tcx,
-                        )
-                        .emit()
+                        let (Ok(e) | Err(e)) = prev
+                            .build_mismatch_error(
+                                &OpaqueHiddenType { ty, span: concrete_type.span },
+                                opaque_type_key.def_id,
+                                infcx.tcx,
+                            )
+                            .map(|d| d.emit());
+                        e
                     });
                     prev.ty = Ty::new_error(infcx.tcx, guar);
                 }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index b3700013f9c2d..d87ddc6497df1 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -478,7 +478,7 @@ fn sanity_check_found_hidden_type<'tcx>(
     } else {
         let span = tcx.def_span(key.def_id);
         let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
-        Err(ty.report_mismatch(&other, key.def_id, tcx).emit())
+        Err(ty.build_mismatch_error(&other, key.def_id, tcx)?.emit())
     }
 }
 
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 79cb384c5bded..f0e998b7a0032 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -58,10 +58,10 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
         // Only check against typeck if we didn't already error
         if !hidden.ty.references_error() {
             for concrete_type in locator.typeck_types {
-                if concrete_type.ty != tcx.erase_regions(hidden.ty)
-                    && !(concrete_type, hidden).references_error()
-                {
-                    hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+                if concrete_type.ty != tcx.erase_regions(hidden.ty) {
+                    if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
+                        d.emit();
+                    }
                 }
             }
         }
@@ -134,10 +134,10 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
         // Only check against typeck if we didn't already error
         if !hidden.ty.references_error() {
             for concrete_type in locator.typeck_types {
-                if concrete_type.ty != tcx.erase_regions(hidden.ty)
-                    && !(concrete_type, hidden).references_error()
-                {
-                    hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+                if concrete_type.ty != tcx.erase_regions(hidden.ty) {
+                    if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
+                        d.emit();
+                    }
                 }
             }
         }
@@ -287,8 +287,10 @@ impl TaitConstraintLocator<'_> {
         if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) {
             debug!(?concrete_type, "found constraint");
             if let Some(prev) = &mut self.found {
-                if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
-                    let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+                if concrete_type.ty != prev.ty {
+                    let (Ok(guar) | Err(guar)) = prev
+                        .build_mismatch_error(&concrete_type, self.def_id, self.tcx)
+                        .map(|d| d.emit());
                     prev.ty = Ty::new_error(self.tcx, guar);
                 }
             } else {
@@ -361,11 +363,13 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
                 hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
             );
             if let Some(prev) = &mut hir_opaque_ty {
-                if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
-                    prev.report_mismatch(&concrete_type, def_id, tcx).stash(
-                        tcx.def_span(opaque_type_key.def_id),
-                        StashKey::OpaqueHiddenTypeMismatch,
-                    );
+                if concrete_type.ty != prev.ty {
+                    if let Ok(d) = prev.build_mismatch_error(&concrete_type, def_id, tcx) {
+                        d.stash(
+                            tcx.def_span(opaque_type_key.def_id),
+                            StashKey::OpaqueHiddenTypeMismatch,
+                        );
+                    }
                 }
             } else {
                 hir_opaque_ty = Some(concrete_type);
@@ -436,9 +440,12 @@ impl RpitConstraintChecker<'_> {
 
             debug!(?concrete_type, "found constraint");
 
-            if concrete_type.ty != self.found.ty && !(concrete_type, self.found).references_error()
-            {
-                self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+            if concrete_type.ty != self.found.ty {
+                if let Ok(d) =
+                    self.found.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
+                {
+                    d.emit();
+                }
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index b83a0f893f5f8..ed102a7fac0be 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -589,12 +589,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 && last_opaque_ty.ty != hidden_type.ty
             {
                 assert!(!self.fcx.next_trait_solver());
-                hidden_type
-                    .report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
-                    .stash(
+                if let Ok(d) = hidden_type.build_mismatch_error(
+                    &last_opaque_ty,
+                    opaque_type_key.def_id,
+                    self.tcx(),
+                ) {
+                    d.stash(
                         self.tcx().def_span(opaque_type_key.def_id),
                         StashKey::OpaqueHiddenTypeMismatch,
                     );
+                }
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index eea3624898c8c..6c7ed14f5f124 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -840,12 +840,12 @@ pub struct OpaqueHiddenType<'tcx> {
 }
 
 impl<'tcx> OpaqueHiddenType<'tcx> {
-    pub fn report_mismatch(
+    pub fn build_mismatch_error(
         &self,
         other: &Self,
         opaque_def_id: LocalDefId,
         tcx: TyCtxt<'tcx>,
-    ) -> DiagnosticBuilder<'tcx> {
+    ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
         if let Some(diag) = tcx
             .sess
             .dcx()
@@ -853,18 +853,19 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
         {
             diag.cancel();
         }
+        (self.ty, other.ty).error_reported()?;
         // Found different concrete types for the opaque type.
         let sub_diag = if self.span == other.span {
             TypeMismatchReason::ConflictType { span: self.span }
         } else {
             TypeMismatchReason::PreviousUse { span: self.span }
         };
-        tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
+        Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
             self_ty: self.ty,
             other_ty: other.ty,
             other_span: other.span,
             sub: sub_diag,
-        })
+        }))
     }
 
     #[instrument(level = "debug", skip(tcx), ret)]
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index fb09f094d37ae..8cf8de4509f39 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -98,6 +98,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
         query_key: ParamEnvAnd<'tcx, Self>,
         infcx: &InferCtxt<'tcx>,
         output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
+        span: Span,
     ) -> Result<
         (
             Self::QueryResponse,
@@ -118,7 +119,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
 
         let InferOk { value, obligations } = infcx
             .instantiate_nll_query_response_and_region_obligations(
-                &ObligationCause::dummy(),
+                &ObligationCause::dummy_with_span(span),
                 old_param_env,
                 &canonical_var_values,
                 canonical_result,
@@ -160,7 +161,7 @@ where
 
         let mut region_constraints = QueryRegionConstraints::default();
         let (output, error_info, mut obligations, _) =
-            Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
+            Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| {
                 infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
             })?;
 
@@ -178,6 +179,7 @@ where
                     obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
                     infcx,
                     &mut region_constraints,
+                    span,
                 ) {
                     Ok(((), _, new, certainty)) => {
                         obligations.extend(new);
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
index ed0b2085c8858..58390032d92d6 100644
--- a/tests/ui/generic-associated-types/issue-90014-tait2.stderr
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
@@ -1,4 +1,11 @@
 error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/issue-90014-tait2.rs:27:9
+   |
+LL | type Fut<'a> = impl Future<Output = ()>;
+   |          -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |         Box::new((async { () },))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs
new file mode 100644
index 0000000000000..02ed08bd6567b
--- /dev/null
+++ b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.rs
@@ -0,0 +1,23 @@
+// Regression test for #97099.
+// This was an ICE because `impl Sized` captures the lifetime 'a.
+
+trait Trait<E> {
+    type Assoc;
+}
+
+struct Foo;
+
+impl<'a> Trait<&'a ()> for Foo {
+    type Assoc = ();
+}
+
+fn foo() -> impl for<'a> Trait<&'a ()> {
+    Foo
+}
+
+fn bar() -> impl for<'a> Trait<&'a (), Assoc = impl Sized> {
+    foo()
+    //~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr
new file mode 100644
index 0000000000000..c177c3bbf00be
--- /dev/null
+++ b/tests/ui/rfcs/impl-trait/higher-ranked-regions-diag.stderr
@@ -0,0 +1,13 @@
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/higher-ranked-regions-diag.rs:19:5
+   |
+LL | fn bar() -> impl for<'a> Trait<&'a (), Assoc = impl Sized> {
+   |                      --                        ---------- opaque type defined here
+   |                      |
+   |                      hidden type `<impl for<'a> Trait<&'a ()> as Trait<&'a ()>>::Assoc` captures the lifetime `'a` as defined here
+LL |     foo()
+   |     ^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
new file mode 100644
index 0000000000000..34b94f2e1c782
--- /dev/null
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
@@ -0,0 +1,80 @@
+// Basic tests for opaque type inference under for<_> binders.
+
+#![feature(type_alias_impl_trait)]
+
+trait Trait<'a> {
+    type Ty;
+}
+impl<'a, T> Trait<'a> for T {
+    type Ty = &'a ();
+}
+
+mod basic_pass {
+    use super::*;
+    type Opq<'a> = impl Sized + 'a;
+    fn test() -> impl for<'a> Trait<'a, Ty = Opq<'a>> {}
+    //~^ ERROR: expected generic lifetime parameter, found `'a`
+}
+
+mod capture_rpit {
+    use super::*;
+    fn test() -> impl for<'a> Trait<'a, Ty = impl Sized> {}
+    //~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
+}
+
+mod capture_tait {
+    use super::*;
+    type Opq0 = impl Sized;
+    type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0>;
+    type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    fn test() -> Opq2 {}
+    //~^ ERROR hidden type for `capture_tait::Opq0` captures lifetime that does not appear in bounds
+}
+
+mod capture_tait_complex_pass {
+    use super::*;
+    type Opq0<'a> = impl Sized;
+    type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
+    type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    fn test() -> Opq2 {}
+    //~^ ERROR: expected generic lifetime parameter, found `'a`
+}
+
+// Same as the above, but make sure that different placeholder regions are not equal.
+mod capture_tait_complex_fail {
+    use super::*;
+    type Opq0<'a> = impl Sized;
+    type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a>>; // <- Note 'a
+    type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    fn test() -> Opq2 {}
+    //~^ ERROR hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
+}
+
+// non-defining use because 'static is used.
+mod constrain_fail0 {
+    use super::*;
+    type Opq0<'a, 'b> = impl Sized;
+    fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
+    //~^ ERROR non-defining opaque type use in defining scope
+    //~| ERROR: expected generic lifetime parameter, found `'a`
+}
+
+// non-defining use because generic lifetime is used multiple times.
+mod constrain_fail {
+    use super::*;
+    type Opq0<'a, 'b> = impl Sized;
+    fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
+    //~^ ERROR non-defining opaque type use in defining scope
+    //~| ERROR: expected generic lifetime parameter, found `'a`
+}
+
+mod constrain_pass {
+    use super::*;
+    type Opq0<'a, 'b> = impl Sized;
+    type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
+    type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    fn test() -> Opq2 {}
+    //~^ ERROR: expected generic lifetime parameter, found `'a`
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
new file mode 100644
index 0000000000000..fb1e4cca3f40b
--- /dev/null
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
@@ -0,0 +1,101 @@
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/higher-ranked-regions-basic.rs:15:55
+   |
+LL |     type Opq<'a> = impl Sized + 'a;
+   |              -- this generic parameter must be used with a generic lifetime parameter
+LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq<'a>> {}
+   |                                                       ^^
+
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/higher-ranked-regions-basic.rs:21:58
+   |
+LL |     fn test() -> impl for<'a> Trait<'a, Ty = impl Sized> {}
+   |                           --                 ----------  ^^
+   |                           |                  |
+   |                           |                  opaque type defined here
+   |                           hidden type `&'a ()` captures the lifetime `'a` as defined here
+
+error[E0700]: hidden type for `capture_tait::Opq0` captures lifetime that does not appear in bounds
+  --> $DIR/higher-ranked-regions-basic.rs:30:23
+   |
+LL |     type Opq0 = impl Sized;
+   |                 ---------- opaque type defined here
+LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0>;
+   |                              -- hidden type `&'b ()` captures the lifetime `'b` as defined here
+LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+LL |     fn test() -> Opq2 {}
+   |                       ^^
+
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/higher-ranked-regions-basic.rs:39:23
+   |
+LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
+   |               -- this generic parameter must be used with a generic lifetime parameter
+LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+LL |     fn test() -> Opq2 {}
+   |                       ^^
+
+error[E0700]: hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
+  --> $DIR/higher-ranked-regions-basic.rs:49:23
+   |
+LL |     type Opq0<'a> = impl Sized;
+   |                     ---------- opaque type defined here
+LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a>>; // <- Note 'a
+   |                              -- hidden type `&'b ()` captures the lifetime `'b` as defined here
+LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+LL |     fn test() -> Opq2 {}
+   |                       ^^
+
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/higher-ranked-regions-basic.rs:57:41
+   |
+LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^ argument `'static` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/higher-ranked-regions-basic.rs:56:25
+   |
+LL |     type Opq0<'a, 'b> = impl Sized;
+   |                         ^^^^^^^^^^
+
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/higher-ranked-regions-basic.rs:57:65
+   |
+LL |     type Opq0<'a, 'b> = impl Sized;
+   |               -- this generic parameter must be used with a generic lifetime parameter
+LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
+   |                                                                 ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/higher-ranked-regions-basic.rs:66:41
+   |
+LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
+   |                                         ^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
+   |
+note: for this opaque type
+  --> $DIR/higher-ranked-regions-basic.rs:65:25
+   |
+LL |     type Opq0<'a, 'b> = impl Sized;
+   |                         ^^^^^^^^^^
+
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/higher-ranked-regions-basic.rs:66:60
+   |
+LL |     type Opq0<'a, 'b> = impl Sized;
+   |               -- this generic parameter must be used with a generic lifetime parameter
+LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
+   |                                                            ^^
+
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/higher-ranked-regions-basic.rs:76:23
+   |
+LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
+   |               -- this generic parameter must be used with a generic lifetime parameter
+LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+LL |     fn test() -> Opq2 {}
+   |                       ^^
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0700, E0792.
+For more information about an error, try `rustc --explain E0700`.
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs
new file mode 100644
index 0000000000000..db5e5e05e54be
--- /dev/null
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs
@@ -0,0 +1,20 @@
+// Regression test for #97098.
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Trait {
+    type Assoc<'a>;
+}
+
+pub type Foo = impl for<'a> Trait<Assoc<'a> = FooAssoc<'a>>;
+pub type FooAssoc<'a> = impl Sized;
+
+struct Struct;
+impl Trait for Struct {
+    type Assoc<'a> = &'a u32;
+}
+
+const FOO: Foo = Struct;
+//~^ ERROR: expected generic lifetime parameter, found `'a`
+
+fn main() {}
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr
new file mode 100644
index 0000000000000..9b361445f1ec3
--- /dev/null
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/higher-ranked-regions-gat.rs:17:18
+   |
+LL | pub type FooAssoc<'a> = impl Sized;
+   |                   -- this generic parameter must be used with a generic lifetime parameter
+...
+LL | const FOO: Foo = Struct;
+   |                  ^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
new file mode 100644
index 0000000000000..c6d1202ef85fd
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
@@ -0,0 +1,39 @@
+#![feature(type_alias_impl_trait)]
+
+fn id(s: &str) -> &str {
+    s
+}
+
+type Opaque<'a> = impl Sized + 'a;
+
+fn test(s: &str) -> (impl Fn(&str) -> Opaque<'_>, impl Fn(&str) -> Opaque<'_>) {
+    (id, id) //~ ERROR expected generic lifetime parameter, found `'_`
+}
+
+fn id2<'a, 'b>(s: (&'a str, &'b str)) -> (&'a str, &'b str) {
+    s
+}
+
+type Opaque2<'a> = impl Sized + 'a;
+
+fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'b>) {
+    id2 //~ ERROR expected generic lifetime parameter, found `'a`
+}
+
+type Opaque3<'a> = impl Sized + 'a;
+
+fn test3(s: &str) -> (impl Fn(&str) -> Opaque3<'_>, Opaque3<'_>) {
+    (id, s) //~ ERROR expected generic lifetime parameter, found `'_`
+}
+
+type Opaque4<'a> = impl Sized + 'a;
+fn test4(s: &str) -> (Opaque4<'_>, impl Fn(&str) -> Opaque4<'_>) {
+    (s, id) //~ ERROR expected generic lifetime parameter, found `'_`
+}
+
+type Inner<'a> = impl Sized;
+fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> {
+    |x| x //~ ERROR expected generic lifetime parameter, found `'a`
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
new file mode 100644
index 0000000000000..d49be73d94e77
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
@@ -0,0 +1,48 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/hkl_forbidden.rs:10:5
+   |
+LL | type Opaque<'a> = impl Sized + 'a;
+   |             -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     (id, id)
+   |     ^^^^^^^^
+
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/hkl_forbidden.rs:20:5
+   |
+LL | type Opaque2<'a> = impl Sized + 'a;
+   |              -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     id2
+   |     ^^^
+
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/hkl_forbidden.rs:26:5
+   |
+LL | type Opaque3<'a> = impl Sized + 'a;
+   |              -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     (id, s)
+   |     ^^^^^^^
+
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/hkl_forbidden.rs:31:5
+   |
+LL | type Opaque4<'a> = impl Sized + 'a;
+   |              -- this generic parameter must be used with a generic lifetime parameter
+LL | fn test4(s: &str) -> (Opaque4<'_>, impl Fn(&str) -> Opaque4<'_>) {
+LL |     (s, id)
+   |     ^^^^^^^
+
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/hkl_forbidden.rs:36:5
+   |
+LL | type Inner<'a> = impl Sized;
+   |            -- this generic parameter must be used with a generic lifetime parameter
+LL | fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> {
+LL |     |x| x
+   |     ^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs
new file mode 100644
index 0000000000000..3d583d4413d9a
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs
@@ -0,0 +1,18 @@
+#![feature(type_alias_impl_trait)]
+
+type Opaque<'a> = impl Sized + 'a;
+
+trait Trait<'a> {
+    type Assoc;
+}
+
+impl<'a> Trait<'a> for () {
+    type Assoc = ();
+}
+
+fn test() -> &'static dyn for<'a> Trait<'a, Assoc = Opaque<'a>> {
+    &()
+    //~^ ERROR: expected generic lifetime parameter, found `'a`
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr
new file mode 100644
index 0000000000000..0a9a9d6bcf4e6
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/hkl_forbidden2.rs:14:5
+   |
+LL | type Opaque<'a> = impl Sized + 'a;
+   |             -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     &()
+   |     ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs
new file mode 100644
index 0000000000000..a4148599f77a3
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs
@@ -0,0 +1,13 @@
+#![feature(type_alias_impl_trait)]
+
+type Opaque<'a> = impl Sized + 'a;
+
+fn foo<'a>(x: &'a ()) -> &'a () {
+    x
+}
+
+fn test() -> for<'a> fn(&'a ()) -> Opaque<'a> {
+    foo //~ ERROR: mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr
new file mode 100644
index 0000000000000..d262177a86bca
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/hkl_forbidden3.rs:10:5
+   |
+LL | type Opaque<'a> = impl Sized + 'a;
+   |                   --------------- the expected opaque type
+...
+LL |     foo
+   |     ^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'a> fn(&'a ()) -> Opaque<'a>`
+              found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.