about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGurinder Singh <frederick.the.fool@gmail.com>2024-04-16 11:11:50 +0530
committerGurinder Singh <frederick.the.fool@gmail.com>2024-04-16 11:11:50 +0530
commitf7ebad494ca7238047d3e64b59da356c5b268985 (patch)
tree29c753bbeed4a6902641b8c7d0b0f61ff9047efe
parent76cf07d5df52c07c3cd4cfeea1ab32b1cfba71bf (diff)
downloadrust-f7ebad494ca7238047d3e64b59da356c5b268985.tar.gz
rust-f7ebad494ca7238047d3e64b59da356c5b268985.zip
Emit suggestions when equality constraints are wrongly used
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs115
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs8
-rw-r--r--tests/rustdoc-ui/invalid_associated_const.stderr9
-rw-r--r--tests/rustdoc-ui/issue-102467.stderr9
-rw-r--r--tests/ui/associated-consts/issue-102335-const.stderr9
-rw-r--r--tests/ui/associated-type-bounds/issue-102335-ty.rs8
-rw-r--r--tests/ui/associated-type-bounds/issue-102335-ty.stderr38
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.rs120
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.stderr366
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr5
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013.stderr5
-rw-r--r--tests/ui/error-codes/E0229.stderr13
-rw-r--r--tests/ui/generic-associated-types/issue-102335-gat.stderr9
-rw-r--r--tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr5
-rw-r--r--tests/ui/suggestions/issue-85347.rs6
-rw-r--r--tests/ui/suggestions/issue-85347.stderr9
17 files changed, 707 insertions, 29 deletions
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 7a0890e50da..3d5be4f7e55 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -17,6 +17,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::traits::FulfillmentError;
 use rustc_middle::query::Key;
+use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, suggest_constraining_type_param};
 use rustc_middle::ty::{AdtDef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{Binder, TraitRef};
@@ -1200,12 +1201,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 /// Emits an error regarding forbidden type binding associations
 pub fn prohibit_assoc_item_binding(
     tcx: TyCtxt<'_>,
-    span: Span,
-    segment: Option<(&hir::PathSegment<'_>, Span)>,
+    binding: &hir::TypeBinding<'_>,
+    segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
 ) -> ErrorGuaranteed {
-    tcx.dcx().emit_err(AssocTypeBindingNotAllowed {
-        span,
-        fn_trait_expansion: if let Some((segment, span)) = segment
+    let mut err = tcx.dcx().create_err(AssocTypeBindingNotAllowed {
+        span: binding.span,
+        fn_trait_expansion: if let Some((_, segment, span)) = segment
             && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
         {
             Some(ParenthesizedFnTraitExpansion {
@@ -1215,7 +1216,109 @@ pub fn prohibit_assoc_item_binding(
         } else {
             None
         },
-    })
+    });
+
+    // Emit a suggestion to turn the assoc item binding into a generic arg
+    // if the relevant item has a generic param whose name matches the binding name;
+    // otherwise suggest the removal of the binding.
+    if let Some((def_id, segment, _)) = segment
+        && segment.args().parenthesized == hir::GenericArgsParentheses::No
+        && let hir::TypeBindingKind::Equality { term } = binding.kind
+    {
+        // Suggests removal of the offending binding
+        let suggest_removal = |e: &mut Diag<'_>| {
+            let bindings = segment.args().bindings;
+            let args = segment.args().args;
+            let binding_span = binding.span;
+
+            // Compute the span to remove based on the position
+            // of the binding. We do that as follows:
+            //  1. Find the index of the binding in the list of bindings
+            //  2. Locate the spans preceding and following the binding.
+            //     If it's the first binding the preceding span would be
+            //     that of the last arg
+            //  3. Using this information work out whether the span
+            //     to remove will start from the end of the preceding span,
+            //     the start of the next span or will simply be the
+            //     span encomassing everything within the generics brackets
+
+            let Some(binding_index) = bindings.iter().position(|b| b.hir_id == binding.hir_id)
+            else {
+                bug!("a type binding exists but its HIR ID not found in generics");
+            };
+
+            let preceding_span = if binding_index > 0 {
+                Some(bindings[binding_index - 1].span)
+            } else {
+                args.last().map(|a| a.span())
+            };
+
+            let next_span = if binding_index < bindings.len() - 1 {
+                Some(bindings[binding_index + 1].span)
+            } else {
+                None
+            };
+
+            let removal_span = match (preceding_span, next_span) {
+                (Some(prec), _) => binding_span.with_lo(prec.hi()),
+                (None, Some(next)) => binding_span.with_hi(next.lo()),
+                (None, None) => {
+                    let Some(generics_span) = segment.args().span_ext() else {
+                        bug!("a type binding exists but generic span is empty");
+                    };
+
+                    generics_span
+                }
+            };
+
+            // Now emit the suggestion
+            if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
+                e.span_suggestion_verbose(
+                    removal_span,
+                    "consider removing this type binding",
+                    suggestion,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        };
+
+        // Suggest replacing the associated item binding with a generic argument.
+        // i.e., replacing `<..., T = A, ...>` with `<..., A, ...>`.
+        let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
+            if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
+                e.span_suggestion_verbose(
+                    binding.span,
+                    format!("to use `{snippet}` as a generic argument specify it directly"),
+                    snippet,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        };
+
+        // Check if the type has a generic param with the
+        // same name as the assoc type name in type binding
+        let generics = tcx.generics_of(def_id);
+        let matching_param =
+            generics.params.iter().find(|p| p.name.as_str() == binding.ident.as_str());
+
+        // Now emit the appropriate suggestion
+        if let Some(matching_param) = matching_param {
+            match (&matching_param.kind, term) {
+                (GenericParamDefKind::Type { .. }, hir::Term::Ty(ty)) => {
+                    suggest_direct_use(&mut err, ty.span);
+                }
+                (GenericParamDefKind::Const { .. }, hir::Term::Const(c)) => {
+                    let span = tcx.hir().span(c.hir_id);
+                    suggest_direct_use(&mut err, span);
+                }
+                _ => suggest_removal(&mut err),
+            }
+        } else {
+            suggest_removal(&mut err);
+        }
+    }
+
+    err.emit()
 }
 
 pub(crate) fn fn_trait_to_string(
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index d340a08ee79..1957849c5aa 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -454,7 +454,7 @@ pub(crate) fn check_generic_arg_count(
     if gen_pos != GenericArgPosition::Type
         && let Some(b) = gen_args.bindings.first()
     {
-        prohibit_assoc_item_binding(tcx, b.span, None);
+        prohibit_assoc_item_binding(tcx, b, None);
     }
 
     let explicit_late_bound =
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 f726f2a7b89..f8596c67d42 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -322,7 +322,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             ty::BoundConstness::NotConst,
         );
         if let Some(b) = item_segment.args().bindings.first() {
-            prohibit_assoc_item_binding(self.tcx(), b.span, Some((item_segment, span)));
+            prohibit_assoc_item_binding(self.tcx(), b, Some((def_id, item_segment, span)));
         }
         args
     }
@@ -619,7 +619,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             ty::BoundConstness::NotConst,
         );
         if let Some(b) = item_segment.args().bindings.first() {
-            prohibit_assoc_item_binding(self.tcx(), b.span, Some((item_segment, span)));
+            prohibit_assoc_item_binding(self.tcx(), b, Some((item_def_id, item_segment, span)));
         }
         args
     }
@@ -764,7 +764,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             constness,
         );
         if let Some(b) = trait_segment.args().bindings.first() {
-            prohibit_assoc_item_binding(self.tcx(), b.span, Some((trait_segment, span)));
+            prohibit_assoc_item_binding(self.tcx(), b, Some((trait_def_id, trait_segment, span)));
         }
         ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
     }
@@ -1556,7 +1556,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         for segment in segments {
             // Only emit the first error to avoid overloading the user with error messages.
             if let Some(b) = segment.args().bindings.first() {
-                return Err(prohibit_assoc_item_binding(self.tcx(), b.span, None));
+                return Err(prohibit_assoc_item_binding(self.tcx(), b, None));
             }
         }
 
diff --git a/tests/rustdoc-ui/invalid_associated_const.stderr b/tests/rustdoc-ui/invalid_associated_const.stderr
index 1eb6d2714e3..5eaddc2b8c9 100644
--- a/tests/rustdoc-ui/invalid_associated_const.stderr
+++ b/tests/rustdoc-ui/invalid_associated_const.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/invalid_associated_const.rs:4:17
@@ -11,6 +16,10 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/rustdoc-ui/issue-102467.stderr b/tests/rustdoc-ui/issue-102467.stderr
index f54a50a4e19..119ca949e99 100644
--- a/tests/rustdoc-ui/issue-102467.stderr
+++ b/tests/rustdoc-ui/issue-102467.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102467.rs:7:17
@@ -11,6 +16,10 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr
index 2a70425a3cc..905d7c75c20 100644
--- a/tests/ui/associated-consts/issue-102335-const.stderr
+++ b/tests/ui/associated-consts/issue-102335-const.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-const.rs:4:17
@@ -11,6 +16,10 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |                 ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<X = 0i32> = 34>;
+   |                ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.rs b/tests/ui/associated-type-bounds/issue-102335-ty.rs
index 5fd8b71e679..b2df68b18ae 100644
--- a/tests/ui/associated-type-bounds/issue-102335-ty.rs
+++ b/tests/ui/associated-type-bounds/issue-102335-ty.rs
@@ -1,5 +1,11 @@
 trait T {
-    type A: S<C<i32 = u32> = ()>;
+    type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+    //~^ ERROR associated type bindings are not allowed here
+    //~| ERROR associated type bindings are not allowed here
+}
+
+trait T2 {
+    type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
     //~^ ERROR associated type bindings are not allowed here
     //~| ERROR associated type bindings are not allowed here
 }
diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.stderr b/tests/ui/associated-type-bounds/issue-102335-ty.stderr
index 3bd7566ad1e..cf30b0a4f6c 100644
--- a/tests/ui/associated-type-bounds/issue-102335-ty.stderr
+++ b/tests/ui/associated-type-bounds/issue-102335-ty.stderr
@@ -1,17 +1,49 @@
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-ty.rs:2:17
    |
-LL |     type A: S<C<i32 = u32> = ()>;
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
    |                 ^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+   |                ~~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-ty.rs:2:17
    |
-LL |     type A: S<C<i32 = u32> = ()>;
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+   |                 ^^^^^^^^^ associated type not allowed here
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+   |                ~~~~~~~~~~~
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-102335-ty.rs:8:17
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+   |                 ^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+   |                 ~~~~~~~~~~
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-102335-ty.rs:8:17
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
    |                 ^^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+   |                 ~~~~~~~~~~
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0229`.
diff --git a/tests/ui/associated-types/associated-types-eq-2.rs b/tests/ui/associated-types/associated-types-eq-2.rs
index 18e38d44667..d71697e9a83 100644
--- a/tests/ui/associated-types/associated-types-eq-2.rs
+++ b/tests/ui/associated-types/associated-types-eq-2.rs
@@ -1,19 +1,125 @@
 // Test equality constraints on associated types. Check we get an error when an
-// equality constraint is used in a qualified path.
+// equality constraint is used in an invalid context
 
-pub trait Foo {
+struct Bar;
+struct Qux;
+
+// Tests for a a non generic trait
+pub trait Tr1 {
     type A;
-    fn boo(&self) -> <Self as Foo>::A;
+    fn boo(&self) -> <Self as Tr1>::A;
 }
 
-struct Bar;
-
-impl Foo for isize {
+impl Tr1 for isize {
     type A = usize;
     fn boo(&self) -> usize { 42 }
 }
 
-fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
+// Test for when the assoc type is
+// specified as an equality constraint
+impl Tr1<A = usize> for usize {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR not all trait items implemented, missing: `A`
+    fn boo(&self) -> usize { 42 }
+}
+
+// Test for a wronngly used equality constraint in a func arg
+fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
+//~^ ERROR associated type bindings are not allowed here
+
+
+
+// Tests for a generic trait
+trait Tr2<T1, T2, T3> {
+}
+
+// Test for when wrongly specifed equality constraint's ident
+// matches some generic param's ident
+// (Note: E0229 is emitted only for the first erroneous equality
+// constraint (T2) not for any subequent ones (e.g. T3))
+impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when equality constraint's ident matches a
+// generic param's ident but has different case
+impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when equality constraint's ident
+// matches none of the generic param idents
+impl Tr2<i32, X = Qux, Y = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when the term in equality constraint is itself generic
+struct GenericTerm<T> { _t: T }
+impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 2 generic arguments were supplied
+}
+
+
+
+// Tests for a trait with a const param
+trait Tr3<const N: i32, T2, T3> {
+}
+
+// Test for when equality constraint's ident
+// matches the const param's ident
+// (Deliberately spread over multiple lines to test that
+// our suggestion spans are kosher in the face of such formatting)
+impl Tr3<N
 //~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+= 42, T2 = Qux, T3 = usize> for Bar {
+}
+
+// Test for when equality constraint's ident
+// matches the const param's ident but has a different case
+impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+}
+
+// Test for when equality constraint's ident
+// matches the const param ident but the constraint is a type arg
+impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+}
+
+// Test for when equality constraint's ident
+// matches a type param ident but the constraint is a const arg
+impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
+}
+
+// Test for when equality constraint's ident
+// matches none of the param idents
+impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR associated const equality is incomplete
+//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
+}
+
+
+
+// Test for the case when lifetimes are present
+struct St<'a, T> { v: &'a T }
+
+impl<'a, T> St<'a , T = Qux> {
+//~^ ERROR associated type bindings are not allowed here
+//~| ERROR struct takes 1 generic argument but 0 generic arguments were supplied
+}
+
 
 pub fn main() {}
diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr
index 447b8413ee2..b68c82f590c 100644
--- a/tests/ui/associated-types/associated-types-eq-2.stderr
+++ b/tests/ui/associated-types/associated-types-eq-2.stderr
@@ -1,9 +1,365 @@
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:76:10
+   |
+LL |   impl Tr3<N
+   |  __________^
+LL | |
+LL | |
+LL | |
+LL | | = 42, T2 = Qux, T3 = usize> for Bar {
+   | |____^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:85:10
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ^^^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:100:14
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |              ^^^^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/associated-types-eq-2.rs:108:10
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |          ^^^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
 error[E0229]: associated type bindings are not allowed here
-  --> $DIR/associated-types-eq-2.rs:16:30
+  --> $DIR/associated-types-eq-2.rs:20:10
+   |
+LL | impl Tr1<A = usize> for usize {
+   |          ^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr1<A = usize> for usize {
+   |         ~~~~~~~~~~~
+
+error[E0046]: not all trait items implemented, missing: `A`
+  --> $DIR/associated-types-eq-2.rs:20:1
+   |
+LL |     type A;
+   |     ------ `A` from trait
+...
+LL | impl Tr1<A = usize> for usize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `A` in implementation
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:27:31
+   |
+LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
+   |                               ^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
+   |                              ~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:40:6
+   |
+LL | impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
+   |      ^^^ --- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr2<i32, T2, T3, T2 = Qux, T3 = usize> for Bar {
+   |             ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:40:15
+   |
+LL | impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
+   |               ^^^^^^^^ associated type not allowed here
+   |
+help: to use `Qux` as a generic argument specify it directly
+   |
+LL | impl Tr2<i32, Qux, T3 = usize> for Bar {
+   |               ~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:47:6
+   |
+LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+   |      ^^^ --- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr2<i32, T2, T3, t2 = Qux, T3 = usize> for Qux {
+   |             ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:47:15
+   |
+LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+   |               ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+   |             ~~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:54:6
+   |
+LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
+   |      ^^^ --- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr2<i32, T2, T3, X = Qux, Y = usize> for Bar {
+   |             ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:54:15
+   |
+LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
+   |               ^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
+   |             ~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 2 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:61:6
+   |
+LL | impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
+   |      ^^^ ---  --- supplied 2 generic arguments
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:33:7
+   |
+LL | trait Tr2<T1, T2, T3> {
+   |       ^^^ --  --  --
+help: add missing generic argument
+   |
+LL | impl Tr2<i32, Qux, T3, T3 = GenericTerm<i32>> for Bar {
+   |                  ++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:61:20
+   |
+LL | impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
+   |                    ^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here
+   |
+help: to use `GenericTerm<i32>` as a generic argument specify it directly
+   |
+LL | impl Tr2<i32, Qux, GenericTerm<i32>> for Bar {
+   |                    ~~~~~~~~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:76:6
+   |
+LL | impl Tr3<N
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, N
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:76:10
+   |
+LL |   impl Tr3<N
+   |  __________^
+LL | |
+LL | |
+LL | |
+LL | | = 42, T2 = Qux, T3 = usize> for Bar {
+   | |____^ associated type not allowed here
+   |
+help: to use `42` as a generic argument specify it directly
+   |
+LL | impl Tr3<42, T2 = Qux, T3 = usize> for Bar {
+   |          ~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:85:6
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:85:10
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+   |          ~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:93:6
+   |
+LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, N = u32, T2 = Qux, T3 = usize> for Bar {
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:93:10
+   |
+LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+   |          ^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+   |          ~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
+  --> $DIR/associated-types-eq-2.rs:100:6
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |      ^^^ -- supplied 1 generic argument
+   |      |
+   |      expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<42, T2, T3, T2 = 42, T3 = usize> for Bar {
+   |            ++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:100:14
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |              ^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+   |            ~~~~~~~~~
+
+error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:108:6
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |      ^^^ expected 3 generic arguments
+   |
+note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
+  --> $DIR/associated-types-eq-2.rs:69:7
+   |
+LL | trait Tr3<const N: i32, T2, T3> {
+   |       ^^^ ------------  --  --
+help: add missing generic arguments
+   |
+LL | impl Tr3<N, T2, T3, X = 42, Y = Qux, Z = usize> for Bar {
+   |          ++++++++++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:108:10
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |          ^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+   |          ~~~~~~~
+
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
+  --> $DIR/associated-types-eq-2.rs:119:13
+   |
+LL | impl<'a, T> St<'a , T = Qux> {
+   |             ^^ expected 1 generic argument
+   |
+note: struct defined here, with 1 generic parameter: `T`
+  --> $DIR/associated-types-eq-2.rs:117:8
+   |
+LL | struct St<'a, T> { v: &'a T }
+   |        ^^     -
+help: add missing generic argument
+   |
+LL | impl<'a, T> St<'a, T , T = Qux> {
+   |                  +++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/associated-types-eq-2.rs:119:21
+   |
+LL | impl<'a, T> St<'a , T = Qux> {
+   |                     ^^^^^^^ associated type not allowed here
+   |
+help: to use `Qux` as a generic argument specify it directly
    |
-LL | fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
-   |                              ^^^^^ associated type not allowed here
+LL | impl<'a, T> St<'a , Qux> {
+   |                     ~~~
 
-error: aborting due to 1 previous error
+error: aborting due to 27 previous errors
 
-For more information about this error, try `rustc --explain E0229`.
+Some errors have detailed explanations: E0046, E0107, E0229, E0658.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
index 92dedd74feb..941764a575e 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
@@ -29,6 +29,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | impl Foo<N = 3> for Bar {
    |          ^^^^^ associated type not allowed here
+   |
+help: to use `3` as a generic argument specify it directly
+   |
+LL | impl Foo<3> for Bar {
+   |          ~
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
index 801d14b3950..a4c9e065c15 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
@@ -41,6 +41,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | impl Foo<N = const 3> for Bar {
    |          ^^^^^^^^^^^ associated type not allowed here
+   |
+help: to use `3` as a generic argument specify it directly
+   |
+LL | impl Foo<3> for Bar {
+   |          ~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr
index bd8e1955ac6..ae7dc9ac265 100644
--- a/tests/ui/error-codes/E0229.stderr
+++ b/tests/ui/error-codes/E0229.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
    |                         ^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+   |                        ~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/E0229.rs:13:25
@@ -11,6 +16,10 @@ LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
    |                         ^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+   |                        ~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/E0229.rs:13:25
@@ -19,6 +28,10 @@ LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
    |                         ^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
+   |                        ~~~~~~~
 
 error[E0277]: the trait bound `I: Foo` is not satisfied
   --> $DIR/E0229.rs:13:15
diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr
index f5e782e92fc..23b114a3a55 100644
--- a/tests/ui/generic-associated-types/issue-102335-gat.stderr
+++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type A: S<C<(), i32 = ()> = ()>;
    |                     ^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type A: S<C<(), i32 = ()> = ()>;
+   |                   ~~~~~~~~~~
 
 error[E0229]: associated type bindings are not allowed here
   --> $DIR/issue-102335-gat.rs:2:21
@@ -11,6 +16,10 @@ LL |     type A: S<C<(), i32 = ()> = ()>;
    |                     ^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type A: S<C<(), i32 = ()> = ()>;
+   |                   ~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
index d99ea6a0c30..d6da842e6ab 100644
--- a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
+++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     fn bar(foo: Foo<Target = usize>) {}
    |                     ^^^^^^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     fn bar(foo: Foo<Target = usize>) {}
+   |                    ~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/issue-85347.rs b/tests/ui/suggestions/issue-85347.rs
index d14cf07d915..95e76e76cfa 100644
--- a/tests/ui/suggestions/issue-85347.rs
+++ b/tests/ui/suggestions/issue-85347.rs
@@ -2,11 +2,13 @@ use std::ops::Deref;
 trait Foo {
     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
     //~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
-    //~| ERROR associated type bindings are not allowed here
     //~| HELP add missing
-    //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
     //~| ERROR associated type bindings are not allowed here
+    //~| HELP consider removing this type binding
+    //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
     //~| HELP add missing
+    //~| ERROR associated type bindings are not allowed here
+    //~| HELP consider removing this type binding
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/issue-85347.stderr b/tests/ui/suggestions/issue-85347.stderr
index 45f87e539b4..de0aa09ce49 100644
--- a/tests/ui/suggestions/issue-85347.stderr
+++ b/tests/ui/suggestions/issue-85347.stderr
@@ -19,6 +19,11 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
    |                                              ^^^^^^^^^^^^^ associated type not allowed here
+   |
+help: consider removing this type binding
+   |
+LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+   |                                             ~~~~~~~~~~~~~~~
 
 error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/issue-85347.rs:3:42
@@ -44,6 +49,10 @@ LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
    |                                              ^^^^^^^^^^^^^ associated type not allowed here
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider removing this type binding
+   |
+LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+   |                                             ~~~~~~~~~~~~~~~
 
 error: aborting due to 4 previous errors