From 5f3e48baab34a3d659e58de54aa9dda2520abc5c Mon Sep 17 00:00:00 2001
From: kei519 <masaki.keigo.q00@kyoto-u.jp>
Date: Sun, 22 Dec 2024 17:31:39 +0900
Subject: [PATCH 1/2] Suggest how to fix with unconstrained type parameters

Unconstrained type parameters made no suggestion and it makes difficult
to know how to fix (#107295).

To make fixing easier, we output suggestions how to fix.
---
 compiler/rustc_hir/src/hir.rs                 | 55 ++++++++++++++
 .../rustc_hir_analysis/src/impl_wf_check.rs   | 72 ++++++++++++++++++-
 2 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index dd96b30fefc36..89c833a40a5cc 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -845,6 +845,61 @@ impl<'hir> Generics<'hir> {
             bound_span.with_lo(bounds[bound_pos - 1].span().hi())
         }
     }
+
+    pub fn span_for_param_removal(&self, param_index: usize) -> Span {
+        if param_index >= self.params.len() {
+            return self.span.shrink_to_hi();
+        }
+
+        let is_impl_generic = |par: &&GenericParam<'_>| match par.kind {
+            GenericParamKind::Type { .. }
+            | GenericParamKind::Const { .. }
+            | GenericParamKind::Lifetime { kind: LifetimeParamKind::Explicit } => true,
+            _ => false,
+        };
+
+        // Find the span of the type parameter.
+        if let Some(next) = self.params[param_index + 1..].iter().find(is_impl_generic) {
+            self.params[param_index].span.until(next.span)
+        } else if let Some(prev) = self.params[..param_index].iter().rfind(is_impl_generic) {
+            let mut prev_span = prev.span;
+            // Consider the span of the bounds with the previous generic parameter when there is.
+            if let Some(prev_bounds_span) = self.span_for_param_bounds(prev) {
+                prev_span = prev_span.to(prev_bounds_span);
+            }
+
+            // Consider the span of the bounds with the current generic parameter when there is.
+            prev_span.shrink_to_hi().to(
+                if let Some(cur_bounds_span) = self.span_for_param_bounds(&self.params[param_index])
+                {
+                    cur_bounds_span
+                } else {
+                    self.params[param_index].span
+                },
+            )
+        } else {
+            // Remove also angle brackets <> when there is just ONE generic parameter.
+            self.span
+        }
+    }
+
+    fn span_for_param_bounds(&self, param: &GenericParam<'hir>) -> Option<Span> {
+        self.predicates
+            .iter()
+            .find(|pred| {
+                if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
+                    origin: PredicateOrigin::GenericParam,
+                    bounded_ty,
+                    ..
+                }) = pred.kind
+                {
+                    bounded_ty.span == param.span
+                } else {
+                    false
+                }
+            })
+            .map(|pred| pred.span)
+    }
 }
 
 /// A single predicate in a where-clause.
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 42034736ad674..ee0e88406bd1e 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -13,9 +13,11 @@ use std::assert_matches::debug_assert_matches;
 use min_specialization::check_min_specialization;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::codes::*;
+use rustc_errors::{Applicability, Diag};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
+use rustc_hir::{Path, QPath, Ty, TyKind};
+use rustc_middle::ty::{self, GenericParamDef, TyCtxt, TypeVisitableExt};
 use rustc_span::ErrorGuaranteed;
 
 use crate::constrained_generic_params as cgp;
@@ -128,6 +130,21 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
     for param in &impl_generics.own_params {
         match param.kind {
             ty::GenericParamDefKind::Lifetime => {
+                let param_lt = cgp::Parameter::from(param.to_early_bound_region_data());
+                if lifetimes_in_associated_types.contains(&param_lt) // (*)
+                    && !input_parameters.contains(&param_lt)
+                {
+                    let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
+                        span: tcx.def_span(param.def_id),
+                        param_name: param.name,
+                        param_def_kind: tcx.def_descr(param.def_id),
+                        const_param_note: false,
+                        const_param_note2: false,
+                    });
+                    diag.code(E0207);
+                    suggest_to_remove_or_use_generic(tcx, &mut diag, impl_def_id, param);
+                    res = Err(diag.emit());
+                }
                 // This is a horrible concession to reality. I think it'd be
                 // better to just ban unconstrained lifetimes outright, but in
                 // practice people do non-hygienic macros like:
@@ -158,6 +175,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
                         const_param_note2: false,
                     });
                     diag.code(E0207);
+                    suggest_to_remove_or_use_generic(tcx, &mut diag, impl_def_id, param);
                     res = Err(diag.emit());
                 }
             }
@@ -229,8 +247,60 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained(
                 const_param_note2: const_param_note,
             });
             diag.code(E0207);
+            suggest_to_remove_or_use_generic(tcx, &mut diag, impl_def_id, &param);
             res = Err(diag.emit());
         }
     }
     res
 }
+
+fn suggest_to_remove_or_use_generic(
+    tcx: TyCtxt<'_>,
+    diag: &mut Diag<'_>,
+    impl_def_id: LocalDefId,
+    param: &GenericParamDef,
+) {
+    let node = tcx.hir_node_by_def_id(impl_def_id);
+    let hir_impl = node.expect_item().expect_impl();
+
+    let Some((index, _)) = hir_impl
+        .generics
+        .params
+        .iter()
+        .enumerate()
+        .find(|(_, par)| par.def_id.to_def_id() == param.def_id)
+    else {
+        return;
+    };
+
+    let mut suggestions = vec![];
+
+    // Suggestion for removing the type parameter.
+    suggestions.push(vec![(hir_impl.generics.span_for_param_removal(index), String::new())]);
+
+    // Suggestion for making use of the type parameter.
+    if let Some(path) = extract_ty_as_path(hir_impl.self_ty) {
+        let seg = path.segments.last().unwrap();
+        if let Some(args) = seg.args {
+            suggestions
+                .push(vec![(args.span().unwrap().shrink_to_hi(), format!(", {}", param.name))]);
+        } else {
+            suggestions.push(vec![(seg.ident.span.shrink_to_hi(), format!("<{}>", param.name))]);
+        }
+    }
+
+    diag.multipart_suggestions(
+        format!("either remove the type parameter {}, or make use of it, for example", param.name),
+        suggestions,
+        Applicability::MaybeIncorrect,
+    );
+}
+
+fn extract_ty_as_path<'hir>(ty: &Ty<'hir>) -> Option<&'hir Path<'hir>> {
+    match ty.kind {
+        TyKind::Path(QPath::Resolved(_, path)) => Some(path),
+        TyKind::Slice(ty) | TyKind::Array(ty, _) => extract_ty_as_path(ty),
+        TyKind::Ptr(ty) | TyKind::Ref(_, ty) => extract_ty_as_path(ty.ty),
+        _ => None,
+    }
+}

From 8315598b8dbbd0ad7543d53211bb991b0e5675e0 Mon Sep 17 00:00:00 2001
From: kei519 <masaki.keigo.q00@kyoto-u.jp>
Date: Mon, 23 Dec 2024 00:31:31 +0900
Subject: [PATCH 2/2] Update tests

---
 .../not-wf-ambiguous-normalization.stderr     |  8 ++++
 ...constrained-param-in-impl-ambiguity.stderr |  8 ++++
 tests/ui/associated-types/issue-26262.stderr  | 16 ++++++++
 .../in-trait/unconstrained-impl-region.stderr |  6 +++
 .../issues/issue-78654.full.stderr            |  7 ++++
 .../async-await/issues/issue-78654.min.stderr |  7 ++++
 ...post-analysis-user-facing-param-env.stderr |  7 ++++
 ...ice-unexpected-inference-var-122549.stderr |  7 ++++
 .../issues/issue-68366.full.stderr            | 14 +++++++
 .../issues/issue-68366.min.stderr             | 14 +++++++
 .../unconstrained_const_param_on_drop.stderr  |  7 ++++
 tests/ui/error-codes/E0207.stderr             |  8 ++++
 .../bugs/issue-87735.stderr                   |  8 ++++
 .../bugs/issue-88526.stderr                   |  8 ++++
 .../gat-trait-path-generic-type-arg.stderr    |  8 ++++
 .../in-trait/refine-resolution-errors.stderr  |  6 +++
 .../in-trait/unconstrained-lt.stderr          |  8 ++++
 tests/ui/impl-trait/issues/issue-87340.stderr |  6 +++
 tests/ui/impl-unused-rps-in-assoc-type.stderr |  8 ++++
 tests/ui/impl-unused-tps-inherent.stderr      | 16 ++++++++
 tests/ui/impl-unused-tps.stderr               | 40 +++++++++++++++++++
 tests/ui/issues/issue-16562.stderr            |  8 ++++
 tests/ui/issues/issue-22886.stderr            |  8 ++++
 tests/ui/issues/issue-29861.stderr            |  8 ++++
 tests/ui/issues/issue-35139.stderr            |  8 ++++
 ...ined-params-in-impl-due-to-overflow.stderr |  8 ++++
 .../unconstrained-params-in-impl.stderr       |  8 ++++
 ...ice-const-not-fully-resolved-113045.stderr |  6 +++
 ...assoc-type-suggestion-in-trait-impl.stderr |  8 ++++
 ...resolve-impl-before-constrain-check.stderr |  6 +++
 ...-projection-normalization-2.current.stderr |  8 ++++
 ...ned-projection-normalization-2.next.stderr |  8 ++++
 ...ed-projection-normalization.current.stderr |  8 ++++
 ...ained-projection-normalization.next.stderr |  8 ++++
 .../assoc-type-lifetime-unconstrained.stderr  |  8 ++++
 ...iled-to-resolve-instance-for-110696.stderr |  8 ++++
 .../impl-with-unconstrained-param.stderr      |  6 +++
 .../type-alias-impl-trait/issue-74244.stderr  |  8 ++++
 .../issue-74761-2.stderr                      | 12 ++++++
 .../type-alias-impl-trait/issue-74761.stderr  | 12 ++++++
 ...s-impl-trait-unconstrained-lifetime.stderr |  6 +++
 .../unconstrained-impl-param.stderr           |  8 ++++
 tests/ui/typeck/issue-13853-5.stderr          |  8 ++++
 43 files changed, 393 insertions(+)

diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
index 55ab144b92419..e9966a7f5bec6 100644
--- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
+++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T> Allocator for DefaultAllocator {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T> Allocator for DefaultAllocator {
+LL + impl Allocator for DefaultAllocator {
+   |
+LL | impl<T> Allocator for DefaultAllocator<T> {
+   |                                       +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/unconstrained-param-in-impl-ambiguity.stderr b/tests/rustdoc-ui/synthetic-auto-trait-impls/unconstrained-param-in-impl-ambiguity.stderr
index 38d1a537fe458..f5c82f0851d63 100644
--- a/tests/rustdoc-ui/synthetic-auto-trait-impls/unconstrained-param-in-impl-ambiguity.stderr
+++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/unconstrained-param-in-impl-ambiguity.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `Q` is not constrained by the impl trait, self
    |
 LL | unsafe impl<Q: Trait> Send for Inner {}
    |             ^ unconstrained type parameter
+   |
+help: either remove the type parameter Q, or make use of it, for example
+   |
+LL - unsafe impl<Q: Trait> Send for Inner {}
+LL + unsafe impl Send for Inner {}
+   |
+LL | unsafe impl<Q: Trait> Send for Inner<Q> {}
+   |                                     +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-types/issue-26262.stderr b/tests/ui/associated-types/issue-26262.stderr
index 90e2d0d930164..09aa37e935d1e 100644
--- a/tests/ui/associated-types/issue-26262.stderr
+++ b/tests/ui/associated-types/issue-26262.stderr
@@ -3,12 +3,28 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: Tr> S<T::Assoc> {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: Tr> S<T::Assoc> {
+LL + impl S<T::Assoc> {
+   |
+LL | impl<T: Tr> S<T::Assoc, T> {
+   |                       +++
 
 error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-26262.rs:17:6
    |
 LL | impl<'a,T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a,T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T {
+LL + impl<T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T {
+   |
+LL | impl<'a,T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T<'a> {
+   |                                                            ++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr
index ef7e4ef0eb85f..4a3aeea29d149 100644
--- a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr
+++ b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr
@@ -3,6 +3,12 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a> Actor for () {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a> Actor for () {
+LL + impl Actor for () {
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/issues/issue-78654.full.stderr b/tests/ui/async-await/issues/issue-78654.full.stderr
index 0d12a948c68bd..dd4eadde64a6c 100644
--- a/tests/ui/async-await/issues/issue-78654.full.stderr
+++ b/tests/ui/async-await/issues/issue-78654.full.stderr
@@ -12,6 +12,13 @@ LL | impl<const H: feature> Foo {
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter H, or make use of it, for example
+   |
+LL - impl<const H: feature> Foo {
+LL + impl Foo {
+   |
+LL | impl<const H: feature> Foo<H> {
+   |                           +++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/issues/issue-78654.min.stderr b/tests/ui/async-await/issues/issue-78654.min.stderr
index 0d12a948c68bd..dd4eadde64a6c 100644
--- a/tests/ui/async-await/issues/issue-78654.min.stderr
+++ b/tests/ui/async-await/issues/issue-78654.min.stderr
@@ -12,6 +12,13 @@ LL | impl<const H: feature> Foo {
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter H, or make use of it, for example
+   |
+LL - impl<const H: feature> Foo {
+LL + impl Foo {
+   |
+LL | impl<const H: feature> Foo<H> {
+   |                           +++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
index ade18eb88b901..3399ece7337f5 100644
--- a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
@@ -25,6 +25,13 @@ LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter NUM, or make use of it, for example
+   |
+LL - impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
+LL + impl<'a> std::ops::Add<&'a Foo> for Foo
+   |
+LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo<NUM>
+   |                                                          +++++
 
 error[E0284]: type annotations needed
   --> $DIR/post-analysis-user-facing-param-env.rs:11:40
diff --git a/tests/ui/const-generics/ice-unexpected-inference-var-122549.stderr b/tests/ui/const-generics/ice-unexpected-inference-var-122549.stderr
index afad3388145c7..a17656c9d6ac0 100644
--- a/tests/ui/const-generics/ice-unexpected-inference-var-122549.stderr
+++ b/tests/ui/const-generics/ice-unexpected-inference-var-122549.stderr
@@ -54,6 +54,13 @@ LL | impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}> {
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter N, or make use of it, for example
+   |
+LL - impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}> {
+LL + impl<'a, T> Iterator for ConstChunksExact<'a, T, {}> {
+   |
+LL | impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}, N> {
+   |                                                                    +++
 
 error[E0308]: mismatched types
   --> $DIR/ice-unexpected-inference-var-122549.rs:15:66
diff --git a/tests/ui/const-generics/issues/issue-68366.full.stderr b/tests/ui/const-generics/issues/issue-68366.full.stderr
index caed3c1bf3f7d..34a5ab398567f 100644
--- a/tests/ui/const-generics/issues/issue-68366.full.stderr
+++ b/tests/ui/const-generics/issues/issue-68366.full.stderr
@@ -18,6 +18,13 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter N, or make use of it, for example
+   |
+LL - impl <const N: usize> Collatz<{Some(N)}> {}
+LL + impl  Collatz<{Some(N)}> {}
+   |
+LL | impl <const N: usize> Collatz<{Some(N)}, N> {}
+   |                                        +++
 
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-68366.rs:19:6
@@ -27,6 +34,13 @@ LL | impl<const N: usize> Foo {}
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter N, or make use of it, for example
+   |
+LL - impl<const N: usize> Foo {}
+LL + impl Foo {}
+   |
+LL | impl<const N: usize> Foo<N> {}
+   |                         +++
 
 error: overly complex generic constant
   --> $DIR/issue-68366.rs:12:31
diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr
index 10b5a06682f53..a0e72c8221d0f 100644
--- a/tests/ui/const-generics/issues/issue-68366.min.stderr
+++ b/tests/ui/const-generics/issues/issue-68366.min.stderr
@@ -27,6 +27,13 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter N, or make use of it, for example
+   |
+LL - impl <const N: usize> Collatz<{Some(N)}> {}
+LL + impl  Collatz<{Some(N)}> {}
+   |
+LL | impl <const N: usize> Collatz<{Some(N)}, N> {}
+   |                                        +++
 
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-68366.rs:19:6
@@ -36,6 +43,13 @@ LL | impl<const N: usize> Foo {}
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter N, or make use of it, for example
+   |
+LL - impl<const N: usize> Foo {}
+LL + impl Foo {}
+   |
+LL | impl<const N: usize> Foo<N> {}
+   |                         +++
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/dropck/unconstrained_const_param_on_drop.stderr b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr
index 851888534eeb2..a0ac2e1b36e80 100644
--- a/tests/ui/dropck/unconstrained_const_param_on_drop.stderr
+++ b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr
@@ -18,6 +18,13 @@ LL | impl<const UNUSED: usize> Drop for Foo {}
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
+help: either remove the type parameter UNUSED, or make use of it, for example
+   |
+LL - impl<const UNUSED: usize> Drop for Foo {}
+LL + impl Drop for Foo {}
+   |
+LL | impl<const UNUSED: usize> Drop for Foo<UNUSED> {}
+   |                                       ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/error-codes/E0207.stderr b/tests/ui/error-codes/E0207.stderr
index 01d7c41854412..b00222ed4d194 100644
--- a/tests/ui/error-codes/E0207.stderr
+++ b/tests/ui/error-codes/E0207.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: Default> Foo {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: Default> Foo {
+LL + impl Foo {
+   |
+LL | impl<T: Default> Foo<T> {
+   |                     +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.stderr b/tests/ui/generic-associated-types/bugs/issue-87735.stderr
index 1b95543136303..4d2fdeebec9e5 100644
--- a/tests/ui/generic-associated-types/bugs/issue-87735.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-87735.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
    |
 LL | impl<'b, T, U> AsRef2 for Foo<T>
    |             ^ unconstrained type parameter
+   |
+help: either remove the type parameter U, or make use of it, for example
+   |
+LL - impl<'b, T, U> AsRef2 for Foo<T>
+LL + impl<'b, T> AsRef2 for Foo<T>
+   |
+LL | impl<'b, T, U> AsRef2 for Foo<T, U>
+   |                                +++
 
 error[E0309]: the parameter type `U` may not live long enough
   --> $DIR/issue-87735.rs:34:21
diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.stderr b/tests/ui/generic-associated-types/bugs/issue-88526.stderr
index 5da3e3ff64ab9..98ebef6a7b0fd 100644
--- a/tests/ui/generic-associated-types/bugs/issue-88526.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-88526.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `I` is not constrained by the impl trait, self
    |
 LL | impl<'q, Q, I, F> A for TestB<Q, F>
    |             ^ unconstrained type parameter
+   |
+help: either remove the type parameter I, or make use of it, for example
+   |
+LL - impl<'q, Q, I, F> A for TestB<Q, F>
+LL + impl<'q, Q, F> A for TestB<Q, F>
+   |
+LL | impl<'q, Q, I, F> A for TestB<Q, F, I>
+   |                                   +++
 
 error[E0309]: the parameter type `F` may not live long enough
   --> $DIR/issue-88526.rs:16:18
diff --git a/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
index cb2b9f32bfe72..c01c8763a2da1 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
@@ -18,6 +18,14 @@ error[E0207]: the type parameter `T1` is not constrained by the impl trait, self
    |
 LL | impl <T, T1> Foo for T {
    |          ^^ unconstrained type parameter
+   |
+help: either remove the type parameter T1, or make use of it, for example
+   |
+LL - impl <T, T1> Foo for T {
+LL + impl <T> Foo for T {
+   |
+LL | impl <T, T1> Foo for T<T1> {
+   |                       ++++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr
index 10ebad2a7d5a1..8542c2cd07a1c 100644
--- a/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr
+++ b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr
@@ -3,6 +3,12 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: ?Sized> Mirror for () {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: ?Sized> Mirror for () {
+LL + impl Mirror for () {
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr
index 4c5a42c0b4b47..45cdbc42bfef3 100644
--- a/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr
+++ b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr
@@ -3,6 +3,14 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a, T> Foo for T {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a, T> Foo for T {
+LL + impl<T> Foo for T {
+   |
+LL | impl<'a, T> Foo for T<'a> {
+   |                      ++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-87340.stderr b/tests/ui/impl-trait/issues/issue-87340.stderr
index 8513cb2881e1f..afa0fa01fc2b2 100644
--- a/tests/ui/impl-trait/issues/issue-87340.stderr
+++ b/tests/ui/impl-trait/issues/issue-87340.stderr
@@ -3,6 +3,12 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T> X for () {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T> X for () {
+LL + impl X for () {
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-unused-rps-in-assoc-type.stderr b/tests/ui/impl-unused-rps-in-assoc-type.stderr
index ef61fa4be4830..84bacd4968fa0 100644
--- a/tests/ui/impl-unused-rps-in-assoc-type.stderr
+++ b/tests/ui/impl-unused-rps-in-assoc-type.stderr
@@ -3,6 +3,14 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a> Fun for Holder {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a> Fun for Holder {
+LL + impl Fun for Holder {
+   |
+LL | impl<'a> Fun for Holder<'a> {
+   |                        ++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-unused-tps-inherent.stderr b/tests/ui/impl-unused-tps-inherent.stderr
index 43f63cf968cf5..86b8d5c3d56f5 100644
--- a/tests/ui/impl-unused-tps-inherent.stderr
+++ b/tests/ui/impl-unused-tps-inherent.stderr
@@ -3,12 +3,28 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T> MyType {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T> MyType {
+LL + impl MyType {
+   |
+LL | impl<T> MyType<T> {
+   |               +++
 
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
   --> $DIR/impl-unused-tps-inherent.rs:17:8
    |
 LL | impl<T,U> MyType1<T> {
    |        ^ unconstrained type parameter
+   |
+help: either remove the type parameter U, or make use of it, for example
+   |
+LL - impl<T,U> MyType1<T> {
+LL + impl<T> MyType1<T> {
+   |
+LL | impl<T,U> MyType1<T, U> {
+   |                    +++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr
index 09c3fce641cfe..499be7ba6472f 100644
--- a/tests/ui/impl-unused-tps.stderr
+++ b/tests/ui/impl-unused-tps.stderr
@@ -12,6 +12,14 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
    |
 LL | impl<T, U> Bar for T {
    |         ^ unconstrained type parameter
+   |
+help: either remove the type parameter U, or make use of it, for example
+   |
+LL - impl<T, U> Bar for T {
+LL + impl<T> Bar for T {
+   |
+LL | impl<T, U> Bar for T<U> {
+   |                     +++
 
 error[E0119]: conflicting implementations of trait `Bar`
   --> $DIR/impl-unused-tps.rs:40:1
@@ -51,24 +59,56 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
    |
 LL | impl<T, U> Foo<T> for [isize; 1] {
    |         ^ unconstrained type parameter
+   |
+help: either remove the type parameter U, or make use of it, for example
+   |
+LL - impl<T, U> Foo<T> for [isize; 1] {
+LL + impl<T> Foo<T> for [isize; 1] {
+   |
+LL | impl<T, U> Foo<T> for [isize<U>; 1] {
+   |                             +++
 
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
   --> $DIR/impl-unused-tps.rs:40:9
    |
 LL | impl<T, U> Bar for T
    |         ^ unconstrained type parameter
+   |
+help: either remove the type parameter U, or make use of it, for example
+   |
+LL - impl<T, U> Bar for T
+LL + impl<T> Bar for T
+   |
+LL | impl<T, U> Bar for T<U>
+   |                     +++
 
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
   --> $DIR/impl-unused-tps.rs:49:9
    |
 LL | impl<T, U, V> Foo<T> for T
    |         ^ unconstrained type parameter
+   |
+help: either remove the type parameter U, or make use of it, for example
+   |
+LL - impl<T, U, V> Foo<T> for T
+LL + impl<T, V> Foo<T> for T
+   |
+LL | impl<T, U, V> Foo<T> for T<U>
+   |                           +++
 
 error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
   --> $DIR/impl-unused-tps.rs:49:12
    |
 LL | impl<T, U, V> Foo<T> for T
    |            ^ unconstrained type parameter
+   |
+help: either remove the type parameter V, or make use of it, for example
+   |
+LL - impl<T, U, V> Foo<T> for T
+LL + impl<T, U> Foo<T> for T
+   |
+LL | impl<T, U, V> Foo<T> for T<V>
+   |                           +++
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/issues/issue-16562.stderr b/tests/ui/issues/issue-16562.stderr
index efbd7f712a45a..185d5a8e67e2d 100644
--- a/tests/ui/issues/issue-16562.stderr
+++ b/tests/ui/issues/issue-16562.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T, M: MatrixShape> Collection for Col<M, usize> {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T, M: MatrixShape> Collection for Col<M, usize> {
+LL + impl<M: MatrixShape> Collection for Col<M, usize> {
+   |
+LL | impl<T, M: MatrixShape> Collection for Col<M, usize, T> {
+   |                                                    +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-22886.stderr b/tests/ui/issues/issue-22886.stderr
index a04fa677f9ec5..609436800564c 100644
--- a/tests/ui/issues/issue-22886.stderr
+++ b/tests/ui/issues/issue-22886.stderr
@@ -3,6 +3,14 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a> Iterator for Newtype {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a> Iterator for Newtype {
+LL + impl Iterator for Newtype {
+   |
+LL | impl<'a> Iterator for Newtype<'a> {
+   |                              ++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-29861.stderr b/tests/ui/issues/issue-29861.stderr
index a25cbf0515d84..c5014203b2bcf 100644
--- a/tests/ui/issues/issue-29861.stderr
+++ b/tests/ui/issues/issue-29861.stderr
@@ -3,6 +3,14 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a, T: 'a> MakeRef2 for T {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a, T: 'a> MakeRef2 for T {
+LL + impl<T: 'a> MakeRef2 for T {
+   |
+LL | impl<'a, T: 'a> MakeRef2 for T<'a> {
+   |                               ++++
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/issue-29861.rs:16:43
diff --git a/tests/ui/issues/issue-35139.stderr b/tests/ui/issues/issue-35139.stderr
index 875af70483224..f0d88c5076835 100644
--- a/tests/ui/issues/issue-35139.stderr
+++ b/tests/ui/issues/issue-35139.stderr
@@ -3,6 +3,14 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a> MethodType for MTFn {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a> MethodType for MTFn {
+LL + impl MethodType for MTFn {
+   |
+LL | impl<'a> MethodType for MTFn<'a> {
+   |                             ++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr
index bcffa02ddd424..7c42c870ec20a 100644
--- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr
+++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T> Loop<T> {}
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T> Loop<T> {}
+LL + impl Loop<T> {}
+   |
+LL | impl<T> Loop<T, T> {}
+   |               +++
 
 error[E0275]: overflow normalizing the type alias `Loop<T>`
   --> $DIR/unconstrained-params-in-impl-due-to-overflow.rs:6:16
diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl.stderr b/tests/ui/lazy-type-alias/unconstrained-params-in-impl.stderr
index 2419c78cba8d9..57c0a6abd868a 100644
--- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl.stderr
+++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T> NotInjective<T> {}
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T> NotInjective<T> {}
+LL + impl NotInjective<T> {}
+   |
+LL | impl<T> NotInjective<T, T> {}
+   |                       +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/specialization/min_specialization/ice-const-not-fully-resolved-113045.stderr b/tests/ui/specialization/min_specialization/ice-const-not-fully-resolved-113045.stderr
index acbdb9b0a308e..45ec1be44c6ed 100644
--- a/tests/ui/specialization/min_specialization/ice-const-not-fully-resolved-113045.stderr
+++ b/tests/ui/specialization/min_specialization/ice-const-not-fully-resolved-113045.stderr
@@ -3,6 +3,12 @@ error[E0207]: the type parameter `Unconstrained` is not constrained by the impl
    |
 LL | impl<'a, Unconstrained> X for [(); 0] {}
    |          ^^^^^^^^^^^^^ unconstrained type parameter
+   |
+help: either remove the type parameter Unconstrained, or make use of it, for example
+   |
+LL - impl<'a, Unconstrained> X for [(); 0] {}
+LL + impl<'a> X for [(); 0] {}
+   |
 
 error: specialization impl does not specialize any associated items
   --> $DIR/ice-const-not-fully-resolved-113045.rs:11:1
diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
index a22d88b7c59fa..e0c990cec7576 100644
--- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
+++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `S` is not constrained by the impl trait, self
    |
 LL | impl<T, S> Trait<T> for i32 {
    |         ^ unconstrained type parameter
+   |
+help: either remove the type parameter S, or make use of it, for example
+   |
+LL - impl<T, S> Trait<T> for i32 {
+LL + impl<T> Trait<T> for i32 {
+   |
+LL | impl<T, S> Trait<T> for i32<S> {
+   |                            +++
 
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
   --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:12
diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.stderr b/tests/ui/traits/resolve-impl-before-constrain-check.stderr
index e8e569ba625ee..6a97ab4e5cf41 100644
--- a/tests/ui/traits/resolve-impl-before-constrain-check.stderr
+++ b/tests/ui/traits/resolve-impl-before-constrain-check.stderr
@@ -3,6 +3,12 @@ error[E0207]: the type parameter `V` is not constrained by the impl trait, self
    |
 LL |     impl<V: ?Sized> Callable for () {
    |          ^ unconstrained type parameter
+   |
+help: either remove the type parameter V, or make use of it, for example
+   |
+LL -     impl<V: ?Sized> Callable for () {
+LL +     impl Callable for () {
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/unconstrained-projection-normalization-2.current.stderr b/tests/ui/traits/unconstrained-projection-normalization-2.current.stderr
index 2bb389c6ec161..4fc93c2aa5c44 100644
--- a/tests/ui/traits/unconstrained-projection-normalization-2.current.stderr
+++ b/tests/ui/traits/unconstrained-projection-normalization-2.current.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: ?Sized> Every for Thing {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: ?Sized> Every for Thing {
+LL + impl Every for Thing {
+   |
+LL | impl<T: ?Sized> Every for Thing<T> {
+   |                                +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr b/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr
index 2bb389c6ec161..4fc93c2aa5c44 100644
--- a/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr
+++ b/tests/ui/traits/unconstrained-projection-normalization-2.next.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: ?Sized> Every for Thing {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: ?Sized> Every for Thing {
+LL + impl Every for Thing {
+   |
+LL | impl<T: ?Sized> Every for Thing<T> {
+   |                                +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/unconstrained-projection-normalization.current.stderr b/tests/ui/traits/unconstrained-projection-normalization.current.stderr
index 991f0e8ba666e..5c8b8a485222e 100644
--- a/tests/ui/traits/unconstrained-projection-normalization.current.stderr
+++ b/tests/ui/traits/unconstrained-projection-normalization.current.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: ?Sized> Every for Thing {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: ?Sized> Every for Thing {
+LL + impl Every for Thing {
+   |
+LL | impl<T: ?Sized> Every for Thing<T> {
+   |                                +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/unconstrained-projection-normalization.next.stderr b/tests/ui/traits/unconstrained-projection-normalization.next.stderr
index 991f0e8ba666e..5c8b8a485222e 100644
--- a/tests/ui/traits/unconstrained-projection-normalization.next.stderr
+++ b/tests/ui/traits/unconstrained-projection-normalization.next.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: ?Sized> Every for Thing {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: ?Sized> Every for Thing {
+LL + impl Every for Thing {
+   |
+LL | impl<T: ?Sized> Every for Thing<T> {
+   |                                +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
index e6b94c525ff23..94e29424ec950 100644
--- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
+++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
@@ -3,6 +3,14 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a, I> UnwrapItemsExt for I {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a, I> UnwrapItemsExt for I {
+LL + impl<I> UnwrapItemsExt for I {
+   |
+LL | impl<'a, I> UnwrapItemsExt for I<'a> {
+   |                                 ++++
 
 error[E0792]: expected generic lifetime parameter, found `'_`
   --> $DIR/assoc-type-lifetime-unconstrained.rs:22:9
diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
index 0ab4c34381a26..1f4c34e4ac16d 100644
--- a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
+++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
+LL + impl<U> MyIndex<DummyT<T>> for Scope<U> {
+   |
+LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U, T> {
+   |                                                                       +++
 
 error: item does not constrain `DummyT::{opaque#0}`, but has it in its signature
   --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:28:8
diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
index 137a4db81b563..1e3f408aba66b 100644
--- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
+++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
@@ -3,6 +3,12 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T> X for () {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T> X for () {
+LL + impl X for () {
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-74244.stderr b/tests/ui/type-alias-impl-trait/issue-74244.stderr
index f5ca56bacccf6..6532f788ee5fa 100644
--- a/tests/ui/type-alias-impl-trait/issue-74244.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-74244.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<T> Allocator for DefaultAllocator {
    |      ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<T> Allocator for DefaultAllocator {
+LL + impl Allocator for DefaultAllocator {
+   |
+LL | impl<T> Allocator for DefaultAllocator<T> {
+   |                                       +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr
index 26babc29000c0..0fe4422f13b42 100644
--- a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr
@@ -3,12 +3,24 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a, 'b> A for () {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a, 'b> A for () {
+LL + impl<'b> A for () {
+   |
 
 error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-74761-2.rs:7:10
    |
 LL | impl<'a, 'b> A for () {
    |          ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'b, or make use of it, for example
+   |
+LL - impl<'a, 'b> A for () {
+LL + impl<'a> A for () {
+   |
 
 error[E0792]: expected generic lifetime parameter, found `'_`
   --> $DIR/issue-74761-2.rs:12:28
diff --git a/tests/ui/type-alias-impl-trait/issue-74761.stderr b/tests/ui/type-alias-impl-trait/issue-74761.stderr
index a4826c293467e..3be849611bf17 100644
--- a/tests/ui/type-alias-impl-trait/issue-74761.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-74761.stderr
@@ -3,12 +3,24 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a, 'b> A for () {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a, 'b> A for () {
+LL + impl<'b> A for () {
+   |
 
 error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-74761.rs:7:10
    |
 LL | impl<'a, 'b> A for () {
    |          ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'b, or make use of it, for example
+   |
+LL - impl<'a, 'b> A for () {
+LL + impl<'a> A for () {
+   |
 
 error[E0792]: expected generic lifetime parameter, found `'_`
   --> $DIR/issue-74761.rs:12:28
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr
index 5f9c56f1ca9d0..ad613b902e6b8 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr
@@ -3,6 +3,12 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) {
+LL + impl<I: Iterator<Item = i32>> Trait for (i32, I) {
+   |
 
 error[E0792]: expected generic lifetime parameter, found `'_`
   --> $DIR/type-alias-impl-trait-unconstrained-lifetime.rs:14:9
diff --git a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr
index 6206f169c5b9e..c14d947b1f2cc 100644
--- a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr
+++ b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr
@@ -3,6 +3,14 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
    |
 LL | impl<'a> Trait for Opaque<&'a str> {
    |      ^^ unconstrained lifetime parameter
+   |
+help: either remove the type parameter 'a, or make use of it, for example
+   |
+LL - impl<'a> Trait for Opaque<&'a str> {
+LL + impl Trait for Opaque<&'a str> {
+   |
+LL | impl<'a> Trait for Opaque<&'a str, 'a> {
+   |                                  ++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/typeck/issue-13853-5.stderr b/tests/ui/typeck/issue-13853-5.stderr
index 388d5ec746ce6..87d81db126c94 100644
--- a/tests/ui/typeck/issue-13853-5.stderr
+++ b/tests/ui/typeck/issue-13853-5.stderr
@@ -3,6 +3,14 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
    |
 LL | impl<'a, T: Deserializable> Deserializable for &'a str {
    |          ^ unconstrained type parameter
+   |
+help: either remove the type parameter T, or make use of it, for example
+   |
+LL - impl<'a, T: Deserializable> Deserializable for &'a str {
+LL + impl<'a: Deserializable> Deserializable for &'a str {
+   |
+LL | impl<'a, T: Deserializable> Deserializable for &'a str<T> {
+   |                                                       +++
 
 error[E0308]: mismatched types
   --> $DIR/issue-13853-5.rs:9:70