diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index cd6cf36baa44d..e3b4ec9d0aaef 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -99,6 +99,15 @@ hir_analysis_invalid_union_field =
 hir_analysis_invalid_union_field_sugg =
     wrap the field type in `ManuallyDrop<...>`
 
+hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
+    .label = const parameter declared here
+
+hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl
+    .label = lifetime declared here
+
+hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
+    .label = type parameter declared here
+
 hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
     .label = lifetimes do not match {$item_kind} in trait
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index d20f39e9b05b9..523ca63e1daa7 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1344,12 +1344,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Binder {
                     where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
                 } => {
-                    let mut err = self.tcx.sess.struct_span_err(
-                        lifetime_ref.ident.span,
-                        "`impl Trait` can only mention lifetimes bound at the fn or impl level",
-                    );
-                    err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
-                    err.emit();
+                    self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
+                        span: lifetime_ref.ident.span,
+                        param_span: self.tcx.def_span(region_def_id),
+                    });
                     return;
                 }
                 Scope::Root { .. } => break,
@@ -1379,6 +1377,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         let mut late_depth = 0;
         let mut scope = self.scope;
         let mut crossed_anon_const = false;
+
         let result = loop {
             match *scope {
                 Scope::Body { s, .. } => {
@@ -1446,6 +1445,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             return;
         }
 
+        // We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
+        // AST-based resolution does not care for impl-trait desugaring, which are the
+        // responsibility of lowering. This may create a mismatch between the resolution
+        // AST found (`param_def_id`) which points to HRTB, and what HIR allows.
+        // ```
+        // fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
+        // ```
+        //
+        // In such case, walk back the binders to diagnose it properly.
+        let mut scope = self.scope;
+        loop {
+            match *scope {
+                Scope::Binder {
+                    where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
+                } => {
+                    let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
+                        DefKind::TyParam => errors::LateBoundInApit::Type {
+                            span: self.tcx.hir().span(hir_id),
+                            param_span: self.tcx.def_span(param_def_id),
+                        },
+                        DefKind::ConstParam => errors::LateBoundInApit::Const {
+                            span: self.tcx.hir().span(hir_id),
+                            param_span: self.tcx.def_span(param_def_id),
+                        },
+                        kind => {
+                            bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
+                        }
+                    });
+                    self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+                    return;
+                }
+                Scope::Root { .. } => break,
+                Scope::Binder { s, .. }
+                | Scope::Body { s, .. }
+                | Scope::Elision { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::Supertrait { s, .. }
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
+                    scope = s;
+                }
+            }
+        }
+
         self.tcx.sess.delay_span_bug(
             self.tcx.hir().span(hir_id),
             format!("could not resolve {param_def_id:?}"),
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7dce1272f96df..cb840592edd22 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -875,3 +875,28 @@ pub(crate) enum ReturnTypeNotationIllegalParam {
         param_span: Span,
     },
 }
+
+#[derive(Diagnostic)]
+pub(crate) enum LateBoundInApit {
+    #[diag(hir_analysis_late_bound_type_in_apit)]
+    Type {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+    #[diag(hir_analysis_late_bound_const_in_apit)]
+    Const {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+    #[diag(hir_analysis_late_bound_lifetime_in_apit)]
+    Lifetime {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+}
diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.rs b/tests/ui/impl-trait/universal_wrong_hrtb.rs
index b9551c2ceb0e5..48561710143b6 100644
--- a/tests/ui/impl-trait/universal_wrong_hrtb.rs
+++ b/tests/ui/impl-trait/universal_wrong_hrtb.rs
@@ -3,6 +3,6 @@ trait Trait<'a> {
 }
 
 fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
+//~^ ERROR `impl Trait` can only mention lifetimes from an fn or impl
 
 fn main() {}
diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.stderr b/tests/ui/impl-trait/universal_wrong_hrtb.stderr
index 37eb8dfa1a141..b5a091b61faf0 100644
--- a/tests/ui/impl-trait/universal_wrong_hrtb.stderr
+++ b/tests/ui/impl-trait/universal_wrong_hrtb.stderr
@@ -1,14 +1,8 @@
-error: `impl Trait` can only mention lifetimes bound at the fn or impl level
+error: `impl Trait` can only mention lifetimes from an fn or impl
   --> $DIR/universal_wrong_hrtb.rs:5:73
    |
 LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-   |                                                                         ^^
-   |
-note: lifetime declared here
-  --> $DIR/universal_wrong_hrtb.rs:5:39
-   |
-LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-   |                                       ^^
+   |                                       -- lifetime declared here         ^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
new file mode 100644
index 0000000000000..e9ae00df7a09e
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait<Input> {
+    type Assoc;
+}
+
+fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
+//~^ ERROR `impl Trait` can only mention type parameters from an fn or impl
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
new file mode 100644
index 0000000000000..1124076c23c9c
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `impl Trait` can only mention type parameters from an fn or impl
+  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:8:52
+   |
+LL | fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
+   |                    - type parameter declared here  ^
+
+error: aborting due to previous error; 1 warning emitted
+