diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 258655de486f9..6a0f03c8b3196 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -34,7 +34,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         modifiers: Option<ast::TraitBoundModifiers>,
     ) -> hir::QPath<'hir> {
         let qself_position = qself.as_ref().map(|q| q.position);
-        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
+        let qself = qself
+            .as_ref()
+            // Reject cases like `<impl Trait>::Assoc` and `<impl Trait as Trait>::Assoc`.
+            .map(|q| self.lower_ty(&q.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path)));
 
         let partial_res =
             self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
@@ -75,6 +78,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             None
         };
 
+        // Only permit `impl Trait` in the final segment. E.g., we permit `Option<impl Trait>`,
+        // `option::Option<T>::Xyz<impl Trait>` and reject `option::Option<impl Trait>::Xyz`.
+        let itctx = |i| {
+            if i + 1 == p.segments.len() {
+                itctx
+            } else {
+                ImplTraitContext::Disallowed(ImplTraitPosition::Path)
+            }
+        };
+
         let path_span_lo = p.span.shrink_to_lo();
         let proj_start = p.segments.len() - unresolved_segments;
         let path = self.arena.alloc(hir::Path {
@@ -121,7 +134,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         segment,
                         param_mode,
                         generic_args_mode,
-                        itctx,
+                        itctx(i),
                         bound_modifier_allowed_features.clone(),
                     )
                 },
@@ -185,7 +198,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 segment,
                 param_mode,
                 generic_args_mode,
-                itctx,
+                itctx(i),
                 None,
             ));
             let qpath = hir::QPath::TypeRelative(ty, hir_segment);
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 92acaaa5f36b0..d81fd53938b89 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -146,8 +146,6 @@ ast_passes_generic_before_constraints = generic arguments must come before the f
 
 ast_passes_generic_default_trailing = generic parameters with a default must be trailing
 
-ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
-
 ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
     .help = remove one of these features
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index bf6ebfb160bc4..485d84b0b6dd3 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -80,10 +80,6 @@ struct AstValidator<'a> {
 
     disallow_tilde_const: Option<TildeConstReason>,
 
-    /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
-    /// or `Foo::Bar<impl Trait>`
-    is_impl_trait_banned: bool,
-
     /// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
     extern_mod_safety: Option<Safety>,
 
@@ -123,12 +119,6 @@ impl<'a> AstValidator<'a> {
         self.extern_mod_safety = old;
     }
 
-    fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.is_impl_trait_banned, true);
-        f(self);
-        self.is_impl_trait_banned = old;
-    }
-
     fn with_tilde_const(
         &mut self,
         disallowed: Option<TildeConstReason>,
@@ -213,37 +203,6 @@ impl<'a> AstValidator<'a> {
                 .with_tilde_const(Some(TildeConstReason::TraitObject), |this| {
                     visit::walk_ty(this, t)
                 }),
-            TyKind::Path(qself, path) => {
-                // We allow these:
-                //  - `Option<impl Trait>`
-                //  - `option::Option<impl Trait>`
-                //  - `option::Option<T>::Foo<impl Trait>`
-                //
-                // But not these:
-                //  - `<impl Trait>::Foo`
-                //  - `option::Option<impl Trait>::Foo`.
-                //
-                // To implement this, we disallow `impl Trait` from `qself`
-                // (for cases like `<impl Trait>::Foo>`)
-                // but we allow `impl Trait` in `GenericArgs`
-                // iff there are no more PathSegments.
-                if let Some(qself) = qself {
-                    // `impl Trait` in `qself` is always illegal
-                    self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
-                }
-
-                // Note that there should be a call to visit_path here,
-                // so if any logic is added to process `Path`s a call to it should be
-                // added both in visit_path and here. This code mirrors visit::walk_path.
-                for (i, segment) in path.segments.iter().enumerate() {
-                    // Allow `impl Trait` iff we're on the final path segment
-                    if i == path.segments.len() - 1 {
-                        self.visit_path_segment(segment);
-                    } else {
-                        self.with_banned_impl_trait(|this| this.visit_path_segment(segment));
-                    }
-                }
-            }
             _ => visit::walk_ty(self, t),
         }
     }
@@ -737,10 +696,6 @@ impl<'a> AstValidator<'a> {
                 }
             }
             TyKind::ImplTrait(_, bounds) => {
-                if self.is_impl_trait_banned {
-                    self.dcx().emit_err(errors::ImplTraitPath { span: ty.span });
-                }
-
                 if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
                     self.dcx().emit_err(errors::NestedImplTrait {
                         span: ty.span,
@@ -1729,7 +1684,6 @@ pub fn check_crate(
         has_proc_macro_decls: false,
         outer_impl_trait: None,
         disallow_tilde_const: Some(TildeConstReason::Item),
-        is_impl_trait_banned: false,
         extern_mod_safety: None,
         lint_buffer: lints,
     };
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 4ca1acde1e289..8c3ac9864ed8a 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -418,13 +418,6 @@ pub(crate) struct TraitObjectBound {
     pub span: Span,
 }
 
-#[derive(Diagnostic)]
-#[diag(ast_passes_impl_trait_path, code = E0667)]
-pub(crate) struct ImplTraitPath {
-    #[primary_span]
-    pub span: Span,
-}
-
 #[derive(Diagnostic)]
 #[diag(ast_passes_nested_impl_trait, code = E0666)]
 pub(crate) struct NestedImplTrait {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0667.md b/compiler/rustc_error_codes/src/error_codes/E0667.md
index 0709a24c43312..339bc0686103a 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0667.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0667.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `impl Trait` is not allowed in path parameters.
 
 Erroneous code example:
 
-```compile_fail,E0667
+```ignore (removed error code)
 fn some_fn(mut x: impl Iterator) -> <impl Iterator>::Item { // error!
     x.next().unwrap()
 }
@@ -11,7 +13,7 @@ fn some_fn(mut x: impl Iterator) -> <impl Iterator>::Item { // error!
 You cannot use `impl Trait` in path parameters. If you want something
 equivalent, you can do this instead:
 
-```
+```ignore (removed error code)
 fn some_fn<T: Iterator>(mut x: T) -> T::Item { // ok!
     x.next().unwrap()
 }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 863c077a9e03c..cfd1241ad69c8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1203,15 +1203,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     err.emit()
                 } else if let Err(reported) = qself_ty.error_reported() {
                     reported
-                } else if let ty::Alias(ty::Opaque, alias_ty) = qself_ty.kind() {
-                    // `<impl Trait as OtherTrait>::Assoc` makes no sense.
-                    struct_span_code_err!(
-                        self.dcx(),
-                        tcx.def_span(alias_ty.def_id),
-                        E0667,
-                        "`impl Trait` is not allowed in path parameters"
-                    )
-                    .emit() // Already reported in an earlier stage.
                 } else {
                     self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?;
 
diff --git a/tests/crashes/126725.rs b/tests/crashes/126725.rs
deleted file mode 100644
index d7a7d21ae4244..0000000000000
--- a/tests/crashes/126725.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ known-bug: rust-lang/rust#126725
-trait Foo {
-    fn foo<'a>(&'a self) -> <&'a impl Sized as Bar>::Output;
-}
-
-trait Bar {
-    type Output;
-}
-
-struct X(i32);
-
-impl<'a> Bar for &'a X {
-    type Output = &'a i32;
-}
-
-impl Foo for X {
-    fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output {
-        &self.0
-    }
-}
diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs
index 365ac85e2f665..2c277aee06dad 100644
--- a/tests/ui/impl-trait/impl_trait_projections.rs
+++ b/tests/ui/impl-trait/impl_trait_projections.rs
@@ -10,30 +10,27 @@ fn path_parametrized_type_is_allowed() -> option::Option<impl Debug> {
 }
 
 fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
-//~^ ERROR `impl Trait` is not allowed in path parameters
-//~| ERROR `impl Trait` is not allowed in path parameters
+//~^ ERROR `impl Trait` is not allowed in paths
     x.next().unwrap()
 }
 
 fn projection_with_named_trait_is_disallowed(mut x: impl Iterator)
     -> <impl Iterator as Iterator>::Item
-//~^ ERROR `impl Trait` is not allowed in path parameters
+//~^ ERROR `impl Trait` is not allowed in paths
 {
     x.next().unwrap()
 }
 
 fn projection_with_named_trait_inside_path_is_disallowed()
     -> <::std::ops::Range<impl Debug> as Iterator>::Item
-//~^ ERROR `impl Trait` is not allowed in path parameters
-//~| ERROR `impl Debug: Step` is not satisfied
+//~^ ERROR `impl Trait` is not allowed in paths
 {
-    //~^ ERROR `impl Debug: Step` is not satisfied
     (1i32..100).next().unwrap()
 }
 
 fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
-//~^ ERROR `impl Trait` is not allowed in path parameters
+//~^ ERROR `impl Trait` is not allowed in paths
 {
     panic!()
 }
diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr
index d62e3ac4183f5..5e0b80fcd5922 100644
--- a/tests/ui/impl-trait/impl_trait_projections.stderr
+++ b/tests/ui/impl-trait/impl_trait_projections.stderr
@@ -1,73 +1,35 @@
-error[E0667]: `impl Trait` is not allowed in path parameters
+error[E0562]: `impl Trait` is not allowed in paths
   --> $DIR/impl_trait_projections.rs:12:51
    |
 LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
    |                                                   ^^^^^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:19:9
+error[E0562]: `impl Trait` is not allowed in paths
+  --> $DIR/impl_trait_projections.rs:18:9
    |
 LL |     -> <impl Iterator as Iterator>::Item
    |         ^^^^^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:26:27
+error[E0562]: `impl Trait` is not allowed in paths
+  --> $DIR/impl_trait_projections.rs:25:27
    |
 LL |     -> <::std::ops::Range<impl Debug> as Iterator>::Item
    |                           ^^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:35:29
+error[E0562]: `impl Trait` is not allowed in paths
+  --> $DIR/impl_trait_projections.rs:32:29
    |
 LL |     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
    |                             ^^^^^^^^^^
-
-error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:12:51
-   |
-LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
-   |                                                   ^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `impl Debug: Step` is not satisfied
-  --> $DIR/impl_trait_projections.rs:26:8
-   |
-LL |     -> <::std::ops::Range<impl Debug> as Iterator>::Item
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range<impl Debug>: Iterator`
-   |
-   = help: the following other types implement trait `Step`:
-             Char
-             Ipv4Addr
-             Ipv6Addr
-             char
-             i128
-             i16
-             i32
-             i64
-           and 8 others
-   = note: required for `std::ops::Range<impl Debug>` to implement `Iterator`
-
-error[E0277]: the trait bound `impl Debug: Step` is not satisfied
-  --> $DIR/impl_trait_projections.rs:29:1
-   |
-LL | / {
-LL | |
-LL | |     (1i32..100).next().unwrap()
-LL | | }
-   | |_^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range<impl Debug>: Iterator`
    |
-   = help: the following other types implement trait `Step`:
-             Char
-             Ipv4Addr
-             Ipv6Addr
-             char
-             i128
-             i16
-             i32
-             i64
-           and 8 others
-   = note: required for `std::ops::Range<impl Debug>` to implement `Iterator`
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error: aborting due to 7 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0277, E0667.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/impl-trait/in-trait/bad-projection-from-opaque.rs b/tests/ui/impl-trait/in-trait/bad-projection-from-opaque.rs
new file mode 100644
index 0000000000000..c2c22cd1abfcc
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/bad-projection-from-opaque.rs
@@ -0,0 +1,22 @@
+// issue: rust-lang/rust#126725
+
+trait Foo {
+    fn foo<'a>() -> <&'a impl Sized as Bar>::Output;
+    //~^ ERROR `impl Trait` is not allowed in paths
+}
+
+trait Bar {
+    type Output;
+}
+
+impl<'a> Bar for &'a () {
+    type Output = &'a i32;
+}
+
+impl Foo for () {
+    fn foo<'a>() -> <&'a Self as Bar>::Output {
+        &0
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/bad-projection-from-opaque.stderr b/tests/ui/impl-trait/in-trait/bad-projection-from-opaque.stderr
new file mode 100644
index 0000000000000..bea7ccd1a18d0
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/bad-projection-from-opaque.stderr
@@ -0,0 +1,11 @@
+error[E0562]: `impl Trait` is not allowed in paths
+  --> $DIR/bad-projection-from-opaque.rs:4:26
+   |
+LL |     fn foo<'a>() -> <&'a impl Sized as Bar>::Output;
+   |                          ^^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs
index c5ecd1caae1f9..9466668b1dcd4 100644
--- a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs
+++ b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs
@@ -6,7 +6,7 @@
 pub trait Bar { }
 pub trait Quux<T> { type Assoc; }
 pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
-//~^ ERROR `impl Trait` is not allowed in path parameters
+//~^ ERROR `impl Trait` is not allowed in paths
 impl<T> Quux<T> for () { type Assoc = u32; }
 
 fn main() { }
diff --git a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
index 55f47785f0eeb..25547dfa66f5d 100644
--- a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
+++ b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
@@ -1,9 +1,11 @@
-error[E0667]: `impl Trait` is not allowed in path parameters
+error[E0562]: `impl Trait` is not allowed in paths
   --> $DIR/issue-57979-impl-trait-in-path.rs:8:48
    |
 LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
    |                                                ^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0667`.
+For more information about this error, try `rustc --explain E0562`.