From 3988ff25bc577a007926f016fac04333b1ea57bc Mon Sep 17 00:00:00 2001
From: yukang <moorekang@gmail.com>
Date: Mon, 28 Aug 2023 16:57:29 +0800
Subject: [PATCH 1/9] suggest iter_mut() where trying to modify elements from
 .iter()

---
 .../src/diagnostics/mutability_errors.rs      | 42 ++++++++++++++++++-
 .../issue-115259-suggest-iter-mut.fixed       | 20 +++++++++
 .../borrowck/issue-115259-suggest-iter-mut.rs | 20 +++++++++
 .../issue-115259-suggest-iter-mut.stderr      | 16 +++++++
 .../issue-62387-suggest-iter-mut-2.fixed      | 36 ++++++++++++++++
 .../issue-62387-suggest-iter-mut-2.rs         | 36 ++++++++++++++++
 .../issue-62387-suggest-iter-mut-2.stderr     | 16 +++++++
 .../issue-62387-suggest-iter-mut.fixed        | 30 +++++++++++++
 .../borrowck/issue-62387-suggest-iter-mut.rs  | 30 +++++++++++++
 .../issue-62387-suggest-iter-mut.stderr       | 29 +++++++++++++
 10 files changed, 274 insertions(+), 1 deletion(-)
 create mode 100644 tests/ui/borrowck/issue-115259-suggest-iter-mut.fixed
 create mode 100644 tests/ui/borrowck/issue-115259-suggest-iter-mut.rs
 create mode 100644 tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr
 create mode 100644 tests/ui/borrowck/issue-62387-suggest-iter-mut-2.fixed
 create mode 100644 tests/ui/borrowck/issue-62387-suggest-iter-mut-2.rs
 create mode 100644 tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr
 create mode 100644 tests/ui/borrowck/issue-62387-suggest-iter-mut.fixed
 create mode 100644 tests/ui/borrowck/issue-62387-suggest-iter-mut.rs
 create mode 100644 tests/ui/borrowck/issue-62387-suggest-iter-mut.stderr

diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 31e863b8a4ed6..54a557c514547 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1,9 +1,10 @@
+use hir::ExprKind;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
 use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt};
 use rustc_middle::{
     hir::place::PlaceBase,
     mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
@@ -491,6 +492,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                             ),
                         );
 
+                        self.suggest_using_iter_mut(&mut err);
                         self.suggest_make_local_mut(&mut err, local, name);
                     }
                     _ => {
@@ -953,6 +955,44 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         }
     }
 
+    fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>) {
+        let source = self.body.source;
+        let hir = self.infcx.tcx.hir();
+        if let InstanceDef::Item(def_id) = source.instance
+            && let Some(Node::Expr(hir::Expr { hir_id, kind, ..})) = hir.get_if_local(def_id)
+            && let ExprKind::Closure(closure) = kind && closure.movability == None
+            && let Some(Node::Expr(expr)) = hir.find_parent(*hir_id) {
+                let mut cur_expr = expr;
+                while let ExprKind::MethodCall(path_segment, recv, _, _) = cur_expr.kind {
+                    if path_segment.ident.name == sym::iter {
+                        // check `_ty` has `iter_mut` method
+                        let res = self
+                            .infcx
+                            .tcx
+                            .typeck(path_segment.hir_id.owner.def_id)
+                            .type_dependent_def_id(cur_expr.hir_id)
+                            .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
+                            .map(|def_id| self.infcx.tcx.associated_items(def_id))
+                            .map(|assoc_items| {
+                                assoc_items.filter_by_name_unhygienic(sym::iter_mut).peekable()
+                            });
+
+                        if let Some(mut res) = res && res.peek().is_some() {
+                            err.span_suggestion_verbose(
+                                path_segment.ident.span,
+                                "you may want to use `iter_mut` here",
+                                "iter_mut",
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        break;
+                    } else {
+                        cur_expr = recv;
+                    }
+                }
+            }
+    }
+
     fn suggest_make_local_mut(
         &self,
         err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
diff --git a/tests/ui/borrowck/issue-115259-suggest-iter-mut.fixed b/tests/ui/borrowck/issue-115259-suggest-iter-mut.fixed
new file mode 100644
index 0000000000000..4653fe7375d38
--- /dev/null
+++ b/tests/ui/borrowck/issue-115259-suggest-iter-mut.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+#![allow(unused_mut)]
+#![allow(dead_code)]
+
+pub trait Layer {
+    fn process(&mut self) -> u32;
+}
+
+pub struct State {
+    layers: Vec<Box<dyn Layer>>,
+}
+
+impl State {
+    pub fn process(&mut self) -> u32 {
+        self.layers.iter_mut().fold(0, |result, mut layer| result + layer.process())
+        //~^ ERROR cannot borrow `**layer` as mutable, as it is behind a `&` reference
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-115259-suggest-iter-mut.rs b/tests/ui/borrowck/issue-115259-suggest-iter-mut.rs
new file mode 100644
index 0000000000000..e0f6ab1321f83
--- /dev/null
+++ b/tests/ui/borrowck/issue-115259-suggest-iter-mut.rs
@@ -0,0 +1,20 @@
+// run-rustfix
+#![allow(unused_mut)]
+#![allow(dead_code)]
+
+pub trait Layer {
+    fn process(&mut self) -> u32;
+}
+
+pub struct State {
+    layers: Vec<Box<dyn Layer>>,
+}
+
+impl State {
+    pub fn process(&mut self) -> u32 {
+        self.layers.iter().fold(0, |result, mut layer| result + layer.process())
+        //~^ ERROR cannot borrow `**layer` as mutable, as it is behind a `&` reference
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr b/tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr
new file mode 100644
index 0000000000000..7e0fc2cf298b0
--- /dev/null
+++ b/tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr
@@ -0,0 +1,16 @@
+error[E0596]: cannot borrow `**layer` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-115259-suggest-iter-mut.rs:15:65
+   |
+LL |         self.layers.iter().fold(0, |result, mut layer| result + layer.process())
+   |                                             ---------           ^^^^^ `layer` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |                                             |
+   |                                             consider changing this binding's type to be: `&mut Box<dyn Layer>`
+   |
+help: you may want to use `iter_mut` here
+   |
+LL |         self.layers.iter_mut().fold(0, |result, mut layer| result + layer.process())
+   |                     ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.fixed b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.fixed
new file mode 100644
index 0000000000000..f02374d8e11de
--- /dev/null
+++ b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.fixed
@@ -0,0 +1,36 @@
+// run-rustfix
+#![allow(unused_mut)]
+#![allow(dead_code)]
+use std::path::PathBuf;
+
+#[derive(Clone)]
+struct Container {
+    things: Vec<PathBuf>,
+}
+
+impl Container {
+    fn things(&mut self) -> &[PathBuf] {
+        &self.things
+    }
+}
+
+// contains containers
+struct ContainerContainer {
+    contained: Vec<Container>,
+}
+
+impl ContainerContainer {
+    fn contained(&self) -> &[Container] {
+        &self.contained
+    }
+
+    fn all_the_things(&mut self) -> &[PathBuf] {
+        let mut vec = self.contained.clone();
+        let _a =
+            vec.iter_mut().flat_map(|container| container.things()).cloned().collect::<Vec<PathBuf>>();
+        //~^ ERROR cannot borrow `*container` as mutable, as it is behind a `&` reference
+        unimplemented!();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.rs b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.rs
new file mode 100644
index 0000000000000..2d0b837a946ca
--- /dev/null
+++ b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.rs
@@ -0,0 +1,36 @@
+// run-rustfix
+#![allow(unused_mut)]
+#![allow(dead_code)]
+use std::path::PathBuf;
+
+#[derive(Clone)]
+struct Container {
+    things: Vec<PathBuf>,
+}
+
+impl Container {
+    fn things(&mut self) -> &[PathBuf] {
+        &self.things
+    }
+}
+
+// contains containers
+struct ContainerContainer {
+    contained: Vec<Container>,
+}
+
+impl ContainerContainer {
+    fn contained(&self) -> &[Container] {
+        &self.contained
+    }
+
+    fn all_the_things(&mut self) -> &[PathBuf] {
+        let mut vec = self.contained.clone();
+        let _a =
+            vec.iter().flat_map(|container| container.things()).cloned().collect::<Vec<PathBuf>>();
+        //~^ ERROR cannot borrow `*container` as mutable, as it is behind a `&` reference
+        unimplemented!();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr
new file mode 100644
index 0000000000000..19f194100a199
--- /dev/null
+++ b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr
@@ -0,0 +1,16 @@
+error[E0596]: cannot borrow `*container` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-62387-suggest-iter-mut-2.rs:30:45
+   |
+LL |             vec.iter().flat_map(|container| container.things()).cloned().collect::<Vec<PathBuf>>();
+   |                                  ---------  ^^^^^^^^^ `container` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |                                  |
+   |                                  consider changing this binding's type to be: `&mut Container`
+   |
+help: you may want to use `iter_mut` here
+   |
+LL |             vec.iter_mut().flat_map(|container| container.things()).cloned().collect::<Vec<PathBuf>>();
+   |                 ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/borrowck/issue-62387-suggest-iter-mut.fixed b/tests/ui/borrowck/issue-62387-suggest-iter-mut.fixed
new file mode 100644
index 0000000000000..8bf2625de6da6
--- /dev/null
+++ b/tests/ui/borrowck/issue-62387-suggest-iter-mut.fixed
@@ -0,0 +1,30 @@
+// run-rustfix
+#![allow(unused_mut)]
+#![allow(dead_code)]
+
+#[derive(Debug)]
+struct A {
+    a: i32,
+}
+
+impl A {
+    fn double(&mut self) {
+        self.a += self.a
+    }
+}
+
+fn baz() {
+    let mut v = [A { a: 4 }];
+    v.iter_mut().for_each(|a| a.double());
+    //~^ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference
+    println!("{:?}", v);
+}
+
+fn bar() {
+    let mut v = [A { a: 4 }];
+    v.iter_mut().rev().rev().for_each(|a| a.double());
+    //~^ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference
+    println!("{:?}", v);
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-62387-suggest-iter-mut.rs b/tests/ui/borrowck/issue-62387-suggest-iter-mut.rs
new file mode 100644
index 0000000000000..39bc30bf29452
--- /dev/null
+++ b/tests/ui/borrowck/issue-62387-suggest-iter-mut.rs
@@ -0,0 +1,30 @@
+// run-rustfix
+#![allow(unused_mut)]
+#![allow(dead_code)]
+
+#[derive(Debug)]
+struct A {
+    a: i32,
+}
+
+impl A {
+    fn double(&mut self) {
+        self.a += self.a
+    }
+}
+
+fn baz() {
+    let mut v = [A { a: 4 }];
+    v.iter().for_each(|a| a.double());
+    //~^ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference
+    println!("{:?}", v);
+}
+
+fn bar() {
+    let mut v = [A { a: 4 }];
+    v.iter().rev().rev().for_each(|a| a.double());
+    //~^ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference
+    println!("{:?}", v);
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-62387-suggest-iter-mut.stderr b/tests/ui/borrowck/issue-62387-suggest-iter-mut.stderr
new file mode 100644
index 0000000000000..fd58e43302025
--- /dev/null
+++ b/tests/ui/borrowck/issue-62387-suggest-iter-mut.stderr
@@ -0,0 +1,29 @@
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-62387-suggest-iter-mut.rs:18:27
+   |
+LL |     v.iter().for_each(|a| a.double());
+   |                        -  ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |                        |
+   |                        consider changing this binding's type to be: `&mut A`
+   |
+help: you may want to use `iter_mut` here
+   |
+LL |     v.iter_mut().for_each(|a| a.double());
+   |       ~~~~~~~~
+
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/issue-62387-suggest-iter-mut.rs:25:39
+   |
+LL |     v.iter().rev().rev().for_each(|a| a.double());
+   |                                    -  ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |                                    |
+   |                                    consider changing this binding's type to be: `&mut A`
+   |
+help: you may want to use `iter_mut` here
+   |
+LL |     v.iter_mut().rev().rev().for_each(|a| a.double());
+   |       ~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.

From a8f3c7684df5ac15c770ef92d58436aa3386cfcf Mon Sep 17 00:00:00 2001
From: surechen <chenshuo17@huawei.com>
Date: Wed, 6 Sep 2023 11:33:03 +0800
Subject: [PATCH 2/9] fixes #114896

---
 .../src/diagnostics/mutability_errors.rs      | 84 +++++++++++++++++--
 tests/ui/pattern/issue-114896.rs              |  7 ++
 tests/ui/pattern/issue-114896.stderr          | 11 +++
 3 files changed, 96 insertions(+), 6 deletions(-)
 create mode 100644 tests/ui/pattern/issue-114896.rs
 create mode 100644 tests/ui/pattern/issue-114896.stderr

diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 31e863b8a4ed6..1df4e94b9145a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -370,12 +370,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     err.span_label(span, format!("cannot {act}"));
                 }
                 if suggest {
-                    err.span_suggestion_verbose(
-                        local_decl.source_info.span.shrink_to_lo(),
-                        "consider changing this to be mutable",
-                        "mut ",
-                        Applicability::MachineApplicable,
-                    );
+                    self.construct_mut_suggestion_for_local_binding_patterns(&mut err, local);
                     let tcx = self.infcx.tcx;
                     if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() {
                         self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
@@ -710,6 +705,83 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         )
     }
 
+    fn construct_mut_suggestion_for_local_binding_patterns(
+        &self,
+        err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+        local: Local,
+    ) {
+        let local_decl = &self.body.local_decls[local];
+        debug!("local_decl: {:?}", local_decl);
+        let pat_span = match *local_decl.local_info() {
+            LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
+                binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
+                opt_ty_info: _,
+                opt_match_place: _,
+                pat_span,
+            })) => pat_span,
+            _ => local_decl.source_info.span,
+        };
+
+        struct BindingFinder {
+            span: Span,
+            hir_id: Option<hir::HirId>,
+        }
+
+        impl<'tcx> Visitor<'tcx> for BindingFinder {
+            fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
+                if let hir::StmtKind::Local(local) = s.kind {
+                    if local.pat.span == self.span {
+                        self.hir_id = Some(local.hir_id);
+                    }
+                }
+                hir::intravisit::walk_stmt(self, s);
+            }
+        }
+
+        let hir_map = self.infcx.tcx.hir();
+        let def_id = self.body.source.def_id();
+        let hir_id = if let Some(local_def_id) = def_id.as_local()
+            && let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
+        {
+            let body = hir_map.body(body_id);
+            let mut v = BindingFinder {
+                span: pat_span,
+                hir_id: None,
+            };
+            v.visit_body(body);
+            v.hir_id
+        } else {
+            None
+        };
+
+        // With ref-binding patterns, the mutability suggestion has to apply to
+        // the binding, not the reference (which would be a type error):
+        //
+        // `let &b = a;` -> `let &(mut b) = a;`
+        if let Some(hir_id) = hir_id
+            && let Some(hir::Node::Local(hir::Local {
+                pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
+                ..
+            })) = hir_map.find(hir_id)
+            && let Ok(name) = self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
+        {
+            err.span_suggestion(
+                pat_span,
+                "consider changing this to be mutable",
+                format!("&(mut {name})"),
+                Applicability::MachineApplicable,
+            );
+            return;
+        }
+
+        err.span_suggestion_verbose(
+            local_decl.source_info.span.shrink_to_lo(),
+            "consider changing this to be mutable",
+            "mut ",
+            Applicability::MachineApplicable,
+        );
+    }
+
     // point to span of upvar making closure call require mutable borrow
     fn show_mutating_upvar(
         &self,
diff --git a/tests/ui/pattern/issue-114896.rs b/tests/ui/pattern/issue-114896.rs
new file mode 100644
index 0000000000000..cde37f658d6ae
--- /dev/null
+++ b/tests/ui/pattern/issue-114896.rs
@@ -0,0 +1,7 @@
+fn main() {
+    fn x(a: &char) {
+        let &b = a;
+        b.make_ascii_uppercase();
+//~^ cannot borrow `b` as mutable, as it is not declared as mutable
+    }
+}
diff --git a/tests/ui/pattern/issue-114896.stderr b/tests/ui/pattern/issue-114896.stderr
new file mode 100644
index 0000000000000..ffeb7bc136508
--- /dev/null
+++ b/tests/ui/pattern/issue-114896.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
+  --> $DIR/issue-114896.rs:4:9
+   |
+LL |         let &b = a;
+   |             -- help: consider changing this to be mutable: `&(mut b)`
+LL |         b.make_ascii_uppercase();
+   |         ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.

From 8488c27860d3aeade58a562f6d8468142f139644 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 9 Sep 2023 12:22:06 +0200
Subject: [PATCH 3/9] Update mailmap

---
 .mailmap | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.mailmap b/.mailmap
index c072f6282f19b..eb82cf4de8d0b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -205,6 +205,10 @@ Gareth Daniel Smith <garethdanielsmith@gmail.com> gareth <gareth@gareth-N56VM.(n
 Gareth Daniel Smith <garethdanielsmith@gmail.com> Gareth Smith <garethdanielsmith@gmail.com>
 Gauri Kholkar <f2013002@goa.bits-pilani.ac.in>
 Georges Dubus <georges.dubus@gmail.com> <georges.dubus@compiletoi.net>
+Ghost <ghost> <jonasschievink@gmail.com>
+Ghost <ghost> <jonas.schievink@ferrous-systems.com>
+Ghost <ghost> <jonas@schievink.net>
+Ghost <ghost> <Jonas.Schievink@sony.com>
 Giles Cope <gilescope@gmail.com>
 Glen De Cauwsemaecker <decauwsemaecker.glen@gmail.com>
 Graham Fawcett <graham.fawcett@gmail.com> Graham Fawcett <fawcett@uwindsor.ca>

From 254e13d9f9dd38817a28880b99acd29a2fcc5613 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 10 Sep 2023 07:38:03 +0200
Subject: [PATCH 4/9] fix homogeneous_aggregate not ignoring some 1-ZST

---
 compiler/rustc_target/src/abi/call/mod.rs     | 13 ++++--
 tests/ui/abi/compatibility.rs                 | 10 +----
 .../ui/layout/homogeneous-aggr-transparent.rs | 44 +++++++++++++++++++
 .../homogeneous-aggr-transparent.stderr       | 32 ++++++++++++++
 4 files changed, 87 insertions(+), 12 deletions(-)
 create mode 100644 tests/ui/layout/homogeneous-aggr-transparent.rs
 create mode 100644 tests/ui/layout/homogeneous-aggr-transparent.stderr

diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 5d75974279ed0..1a4a46ceb4025 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -382,8 +382,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
     /// only a single type (e.g., `(u32, u32)`). Such aggregates are often
     /// special-cased in ABIs.
     ///
-    /// Note: We generally ignore fields of zero-sized type when computing
-    /// this value (see #56877).
+    /// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
     ///
     /// This is public so that it can be used in unit tests, but
     /// should generally only be relevant to the ABI details of
@@ -441,12 +440,18 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
                         let mut total = start;
 
                         for i in 0..layout.fields.count() {
+                            let field = layout.field(cx, i);
+                            if field.is_1zst() {
+                                // No data here and no impact on layout, can be ignored.
+                                // (We might be able to also ignore all aligned ZST but that's less clear.)
+                                continue;
+                            }
+
                             if !is_union && total != layout.fields.offset(i) {
+                                // This field isn't just after the previous one we considered, abort.
                                 return Err(Heterogeneous);
                             }
 
-                            let field = layout.field(cx, i);
-
                             result = result.merge(field.homogeneous_aggregate(cx)?)?;
 
                             // Keep track of the offset (without padding).
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index 0bbcba200c7e3..56ff1ebc52429 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -105,6 +105,8 @@ test_transparent!(zst, Zst);
 test_transparent!(unit, ());
 test_transparent!(pair, (i32, f32)); // mixing in some floats since they often get special treatment
 test_transparent!(triple, (i8, i16, f32)); // chosen to fit into 64bit
+test_transparent!(triple_f32, (f32, f32, f32)); // homogeneous case
+test_transparent!(triple_f64, (f64, f64, f64));
 test_transparent!(tuple, (i32, f32, i64, f64));
 test_transparent!(empty_array, [u32; 0]);
 test_transparent!(empty_1zst_array, [u8; 0]);
@@ -112,14 +114,6 @@ test_transparent!(small_array, [i32; 2]); // chosen to fit into 64bit
 test_transparent!(large_array, [i32; 16]);
 test_transparent!(enum_, Option<i32>);
 test_transparent!(enum_niched, Option<&'static i32>);
-// Pure-float types that are not ScalarPair seem to be tricky.
-// FIXME: <https://github.com/rust-lang/rust/issues/115664>
-#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
-mod tricky {
-    use super::*;
-    test_transparent!(triple_f32, (f32, f32, f32));
-    test_transparent!(triple_f64, (f64, f64, f64));
-}
 
 // RFC 3391 <https://rust-lang.github.io/rfcs/3391-result_ffi_guarantees.html>.
 macro_rules! test_nonnull {
diff --git a/tests/ui/layout/homogeneous-aggr-transparent.rs b/tests/ui/layout/homogeneous-aggr-transparent.rs
new file mode 100644
index 0000000000000..9703d2bf294f6
--- /dev/null
+++ b/tests/ui/layout/homogeneous-aggr-transparent.rs
@@ -0,0 +1,44 @@
+#![feature(rustc_attrs)]
+#![feature(transparent_unions)]
+use std::marker::PhantomData;
+
+// Regression test for #115664. We want to ensure that `repr(transparent)` wrappers do not affect
+// the result of `homogeneous_aggregate`.
+
+type Tuple = (f32, f32, f32);
+
+struct Zst;
+
+#[repr(transparent)]
+struct Wrapper1<T>(T);
+#[repr(transparent)]
+struct Wrapper2<T>((), Zst, T);
+#[repr(transparent)]
+struct Wrapper3<T>(T, [u8; 0], PhantomData<u64>);
+#[repr(transparent)]
+union WrapperUnion<T: Copy> {
+    nothing: (),
+    something: T,
+}
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test0 = Tuple;
+//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test1 = Wrapper1<Tuple>;
+//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test2 = Wrapper2<Tuple>;
+//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test3 = Wrapper3<Tuple>;
+//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+
+#[rustc_layout(homogeneous_aggregate)]
+pub type Test4 = WrapperUnion<Tuple>;
+//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+
+fn main() {}
diff --git a/tests/ui/layout/homogeneous-aggr-transparent.stderr b/tests/ui/layout/homogeneous-aggr-transparent.stderr
new file mode 100644
index 0000000000000..99eb703ac82b8
--- /dev/null
+++ b/tests/ui/layout/homogeneous-aggr-transparent.stderr
@@ -0,0 +1,32 @@
+error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+  --> $DIR/homogeneous-aggr-transparent.rs:25:1
+   |
+LL | pub type Test0 = Tuple;
+   | ^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+  --> $DIR/homogeneous-aggr-transparent.rs:29:1
+   |
+LL | pub type Test1 = Wrapper1<Tuple>;
+   | ^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+  --> $DIR/homogeneous-aggr-transparent.rs:33:1
+   |
+LL | pub type Test2 = Wrapper2<Tuple>;
+   | ^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+  --> $DIR/homogeneous-aggr-transparent.rs:37:1
+   |
+LL | pub type Test3 = Wrapper3<Tuple>;
+   | ^^^^^^^^^^^^^^
+
+error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
+  --> $DIR/homogeneous-aggr-transparent.rs:41:1
+   |
+LL | pub type Test4 = WrapperUnion<Tuple>;
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+

From ce3b0442983e3689464f512b93b0c6bf020e7c36 Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Sun, 10 Sep 2023 18:17:47 +0000
Subject: [PATCH 5/9] Call `LateLintPass::check_attribute` from
 `with_lint_attrs`

---
 compiler/rustc_lint/src/late.rs               | 25 +++++++++----------
 .../clippy/tests/ui/allow_attributes.fixed    |  7 ++++++
 src/tools/clippy/tests/ui/allow_attributes.rs |  7 ++++++
 .../blanket_clippy_restriction_lints.stderr   | 14 +++++------
 4 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 73af51d9e9061..b24186ae1aa7f 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -21,7 +21,6 @@ use rustc_data_structures::sync::join;
 use rustc_hir as hir;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_hir::intravisit as hir_visit;
-use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::LintPass;
@@ -61,6 +60,9 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
         self.context.last_node_with_lint_attrs = id;
         debug!("late context: enter_attrs({:?})", attrs);
         lint_callback!(self, enter_lint_attrs, attrs);
+        for attr in attrs {
+            lint_callback!(self, check_attribute, attr);
+        }
         f(self);
         debug!("late context: exit_attrs({:?})", attrs);
         lint_callback!(self, exit_lint_attrs, attrs);
@@ -377,20 +379,18 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
 
     let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
 
-    // There is no module lint that will have the crate itself as an item, so check it here.
-    if hir_id == hir::CRATE_HIR_ID {
-        lint_callback!(cx, check_crate,);
-    }
+    cx.with_lint_attrs(hir_id, |cx| {
+        // There is no module lint that will have the crate itself as an item, so check it here.
+        if hir_id == hir::CRATE_HIR_ID {
+            lint_callback!(cx, check_crate,);
+        }
 
-    cx.process_mod(module, hir_id);
+        cx.process_mod(module, hir_id);
 
-    // Visit the crate attributes
-    if hir_id == hir::CRATE_HIR_ID {
-        for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() {
-            cx.visit_attribute(attr)
+        if hir_id == hir::CRATE_HIR_ID {
+            lint_callback!(cx, check_crate_post,);
         }
-        lint_callback!(cx, check_crate_post,);
-    }
+    });
 }
 
 fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
@@ -431,7 +431,6 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
         // item), warn for it here.
         lint_callback!(cx, check_crate,);
         tcx.hir().walk_toplevel_module(cx);
-        tcx.hir().walk_attributes(cx);
         lint_callback!(cx, check_crate_post,);
     })
 }
diff --git a/src/tools/clippy/tests/ui/allow_attributes.fixed b/src/tools/clippy/tests/ui/allow_attributes.fixed
index 945ba83611c0d..b506a9890f5b9 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.fixed
+++ b/src/tools/clippy/tests/ui/allow_attributes.fixed
@@ -22,6 +22,13 @@ struct T4;
 #[cfg_attr(panic = "unwind", expect(dead_code))]
 struct CfgT;
 
+#[allow(clippy::allow_attributes, unused)]
+struct Allowed;
+
+#[expect(clippy::allow_attributes)]
+#[allow(unused)]
+struct Expected;
+
 fn ignore_external() {
     external! {
         #[allow(clippy::needless_borrow)] // Should not lint
diff --git a/src/tools/clippy/tests/ui/allow_attributes.rs b/src/tools/clippy/tests/ui/allow_attributes.rs
index 8afa61c7002c5..c7daa7abd9d41 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.rs
+++ b/src/tools/clippy/tests/ui/allow_attributes.rs
@@ -22,6 +22,13 @@ struct T4;
 #[cfg_attr(panic = "unwind", allow(dead_code))]
 struct CfgT;
 
+#[allow(clippy::allow_attributes, unused)]
+struct Allowed;
+
+#[expect(clippy::allow_attributes)]
+#[allow(unused)]
+struct Expected;
+
 fn ignore_external() {
     external! {
         #[allow(clippy::needless_borrow)] // Should not lint
diff --git a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
index d04ea7151c2a5..afb634f34b41a 100644
--- a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
+++ b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
@@ -1,10 +1,3 @@
-error: `clippy::restriction` is not meant to be enabled as a group
-   |
-   = note: because of the command line `--warn clippy::restriction`
-   = help: enable the restriction lints you need individually
-   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
-
 error: `clippy::restriction` is not meant to be enabled as a group
   --> $DIR/blanket_clippy_restriction_lints.rs:6:9
    |
@@ -12,6 +5,8 @@ LL | #![warn(clippy::restriction)]
    |         ^^^^^^^^^^^^^^^^^^^
    |
    = help: enable the restriction lints you need individually
+   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
 
 error: `clippy::restriction` is not meant to be enabled as a group
   --> $DIR/blanket_clippy_restriction_lints.rs:8:9
@@ -29,5 +24,10 @@ LL | #![forbid(clippy::restriction)]
    |
    = help: enable the restriction lints you need individually
 
+error: `clippy::restriction` is not meant to be enabled as a group
+   |
+   = note: because of the command line `--warn clippy::restriction`
+   = help: enable the restriction lints you need individually
+
 error: aborting due to 4 previous errors
 

From b00e408e613700124463b72f0a449a28c44a8178 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Sun, 10 Sep 2023 23:06:14 +0200
Subject: [PATCH 6/9] Generalize E0401

---
 .../src/error_codes/E0401.md                  |  6 ++--
 compiler/rustc_resolve/src/diagnostics.rs     | 22 +++++--------
 compiler/rustc_resolve/src/ident.rs           | 10 ++----
 compiler/rustc_resolve/src/lib.rs             |  4 +--
 .../early/const-param-from-outer-fn.rs        |  2 +-
 .../early/const-param-from-outer-fn.stderr    |  8 ++---
 tests/ui/error-codes/E0401.stderr             | 22 ++++++-------
 tests/ui/generics/issue-94432-garbage-ice.rs  |  2 +-
 tests/ui/generics/issue-98432.rs              |  2 +-
 tests/ui/generics/issue-98432.stderr          |  8 ++---
 tests/ui/inner-static-type-parameter.rs       |  2 +-
 tests/ui/inner-static-type-parameter.stderr   |  6 ++--
 tests/ui/issues/issue-3214.rs                 |  2 +-
 tests/ui/issues/issue-3214.stderr             |  8 ++---
 tests/ui/issues/issue-5997-enum.rs            |  2 +-
 tests/ui/issues/issue-5997-enum.stderr        |  8 ++---
 tests/ui/issues/issue-5997-struct.rs          |  2 +-
 tests/ui/issues/issue-5997-struct.stderr      |  8 ++---
 tests/ui/nested-ty-params.rs                  |  2 +-
 tests/ui/nested-ty-params.stderr              | 16 +++++-----
 tests/ui/resolve/bad-type-env-capture.stderr  |  8 ++---
 tests/ui/resolve/issue-12796.rs               |  2 +-
 tests/ui/resolve/issue-12796.stderr           |  4 +--
 tests/ui/resolve/issue-3021-c.rs              |  4 +--
 tests/ui/resolve/issue-3021-c.stderr          | 16 +++++-----
 ...sue-65025-extern-static-parent-generics.rs |  2 +-
 ...65025-extern-static-parent-generics.stderr |  6 ++--
 ...issue-65035-static-with-parent-generics.rs | 10 +++---
 ...e-65035-static-with-parent-generics.stderr | 30 ++++++++---------
 .../resolve-type-param-in-item-in-trait.rs    |  8 ++---
 ...resolve-type-param-in-item-in-trait.stderr | 32 +++++++++----------
 tests/ui/resolve/use-self-in-inner-fn.rs      |  6 ++--
 tests/ui/resolve/use-self-in-inner-fn.stderr  |  6 ++--
 tests/ui/type/type-arg-out-of-scope.rs        |  2 +-
 tests/ui/type/type-arg-out-of-scope.stderr    | 16 +++++-----
 35 files changed, 141 insertions(+), 153 deletions(-)

diff --git a/compiler/rustc_error_codes/src/error_codes/E0401.md b/compiler/rustc_error_codes/src/error_codes/E0401.md
index 4c93053d5f8b6..45d083681e574 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0401.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0401.md
@@ -1,4 +1,4 @@
-Inner items do not inherit type or const parameters from the functions
+Inner items do not inherit the generic parameters from the items
 they are embedded in.
 
 Erroneous code example:
@@ -32,8 +32,8 @@ fn foo<T>(x: T) {
 }
 ```
 
-Items inside functions are basically just like top-level items, except
-that they can only be used from the function they are in.
+Items nested inside other items are basically just like top-level items, except
+that they can only be used from the item they are in.
 
 There are a couple of solutions for this.
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d99fc07a7cd28..a99b610ed36af 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -553,14 +553,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         resolution_error: ResolutionError<'a>,
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         match resolution_error {
-            ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
+            ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     span,
                     E0401,
-                    "can't use generic parameters from outer function",
+                    "can't use generic parameters from outer item",
                 );
-                err.span_label(span, "use of generic parameter from outer function");
+                err.span_label(span, "use of generic parameter from outer item");
 
                 let sm = self.tcx.sess.source_map();
                 let def_id = match outer_res {
@@ -573,23 +573,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             reduce_impl_span_to_impl_keyword(sm, self.def_span(def_id)),
                             "`Self` type implicitly declared here, by this `impl`",
                         );
-                        err.span_label(span, "use a type here instead");
+                        err.span_label(span, "refer to the type directly here instead");
                         return err;
                     }
                     Res::Def(DefKind::TyParam, def_id) => {
-                        err.span_label(self.def_span(def_id), "type parameter from outer function");
+                        err.span_label(self.def_span(def_id), "type parameter from outer item");
                         def_id
                     }
                     Res::Def(DefKind::ConstParam, def_id) => {
-                        err.span_label(
-                            self.def_span(def_id),
-                            "const parameter from outer function",
-                        );
+                        err.span_label(self.def_span(def_id), "const parameter from outer item");
                         def_id
                     }
                     _ => {
                         bug!(
-                            "GenericParamsFromOuterFunction should only be used with \
+                            "GenericParamsFromOuterItem should only be used with \
                             Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
                             DefKind::ConstParam"
                         );
@@ -597,9 +594,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 };
 
                 if let HasGenericParams::Yes(span) = has_generic_params {
-                    // Try to retrieve the span of the function signature and generate a new
-                    // message with a local type or const parameter.
-                    let sugg_msg = "try using a local generic parameter instead";
+                    let sugg_msg = "try introducing a local generic parameter here";
                     let name = self.tcx.item_name(def_id);
                     let (span, snippet) = if span.is_empty() {
                         let snippet = format!("<{name}>");
@@ -609,7 +604,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         let snippet = format!("{name}, ");
                         (span, snippet)
                     };
-                    // Suggest the modification to the user
                     err.span_suggestion(span, sugg_msg, snippet, Applicability::MaybeIncorrect);
                 }
 
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 61e05b65f90f5..4817484f56435 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1229,10 +1229,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     if let Some(span) = finalize {
                         self.report_error(
                             span,
-                            ResolutionError::GenericParamsFromOuterFunction(
-                                res,
-                                has_generic_params,
-                            ),
+                            ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
                         );
                     }
                     return Res::Err;
@@ -1296,10 +1293,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     if let Some(span) = finalize {
                         self.report_error(
                             span,
-                            ResolutionError::GenericParamsFromOuterFunction(
-                                res,
-                                has_generic_params,
-                            ),
+                            ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
                         );
                     }
                     return Res::Err;
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index b757f42eaa026..5bb8a21513849 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -186,8 +186,8 @@ struct BindingError {
 
 #[derive(Debug)]
 enum ResolutionError<'a> {
-    /// Error E0401: can't use type or const parameters from outer function.
-    GenericParamsFromOuterFunction(Res, HasGenericParams),
+    /// Error E0401: can't use type or const parameters from outer item.
+    GenericParamsFromOuterItem(Res, HasGenericParams),
     /// Error E0403: the name is already used for a type or const parameter in this generic
     /// parameter list.
     NameAlreadyUsedInParameterList(Symbol, Span),
diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.rs b/tests/ui/const-generics/early/const-param-from-outer-fn.rs
index c3b418ee3f8ad..ee57f3c4fc32c 100644
--- a/tests/ui/const-generics/early/const-param-from-outer-fn.rs
+++ b/tests/ui/const-generics/early/const-param-from-outer-fn.rs
@@ -1,6 +1,6 @@
 fn foo<const X: u32>() {
     fn bar() -> u32 {
-        X //~ ERROR can't use generic parameters from outer function
+        X //~ ERROR can't use generic parameters from outer item
     }
 }
 
diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr
index e3bf38b702e75..826f2657905d3 100644
--- a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr
+++ b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/const-param-from-outer-fn.rs:3:9
    |
 LL | fn foo<const X: u32>() {
-   |              - const parameter from outer function
+   |              - const parameter from outer item
 LL |     fn bar() -> u32 {
-   |           - help: try using a local generic parameter instead: `<X>`
+   |           - help: try introducing a local generic parameter here: `<X>`
 LL |         X
-   |         ^ use of generic parameter from outer function
+   |         ^ use of generic parameter from outer item
 
 error: aborting due to previous error
 
diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr
index fa4b91cacef72..928c8d11d2030 100644
--- a/tests/ui/error-codes/E0401.stderr
+++ b/tests/ui/error-codes/E0401.stderr
@@ -1,26 +1,26 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/E0401.rs:4:39
    |
 LL | fn foo<T>(x: T) {
-   |        - type parameter from outer function
+   |        - type parameter from outer item
 LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
-   |             -                         ^ use of generic parameter from outer function
+   |             -                         ^ use of generic parameter from outer item
    |             |
-   |             help: try using a local generic parameter instead: `T,`
+   |             help: try introducing a local generic parameter here: `T,`
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/E0401.rs:9:16
    |
 LL | fn foo<T>(x: T) {
-   |        - type parameter from outer function
+   |        - type parameter from outer item
 ...
 LL |     fn baz<U,
-   |            - help: try using a local generic parameter instead: `T,`
+   |            - help: try introducing a local generic parameter here: `T,`
 ...
 LL |            (y: T) {
-   |                ^ use of generic parameter from outer function
+   |                ^ use of generic parameter from outer item
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/E0401.rs:24:25
    |
 LL | impl<T> Iterator for A<T> {
@@ -29,8 +29,8 @@ LL | impl<T> Iterator for A<T> {
 LL |         fn helper(sel: &Self) -> u8 {
    |                         ^^^^
    |                         |
-   |                         use of generic parameter from outer function
-   |                         use a type here instead
+   |                         use of generic parameter from outer item
+   |                         refer to the type directly here instead
 
 error[E0282]: type annotations needed
   --> $DIR/E0401.rs:11:5
diff --git a/tests/ui/generics/issue-94432-garbage-ice.rs b/tests/ui/generics/issue-94432-garbage-ice.rs
index d0709e2d2a46c..4ddb3a7e9f86b 100644
--- a/tests/ui/generics/issue-94432-garbage-ice.rs
+++ b/tests/ui/generics/issue-94432-garbage-ice.rs
@@ -4,7 +4,7 @@
 
 fn�a<e>(){fn�p(){e}} //~ ERROR unknown start of token: \u{fffd}
 //~^ ERROR unknown start of token: \u{fffd}
-//~^^ ERROR can't use generic parameters from outer function [E0401]
+//~^^ ERROR can't use generic parameters from outer item [E0401]
 //~^^^ WARN type parameter `e` should have an upper camel case name
 
 fn main(){}
diff --git a/tests/ui/generics/issue-98432.rs b/tests/ui/generics/issue-98432.rs
index 780c50d6ffa19..c31dea76c090c 100644
--- a/tests/ui/generics/issue-98432.rs
+++ b/tests/ui/generics/issue-98432.rs
@@ -2,7 +2,7 @@ struct Struct<T>(T);
 
 impl<T> Struct<T> {
     const CONST: fn() = || {
-        struct _Obligation where T:; //~ ERROR can't use generic parameters from outer function
+        struct _Obligation where T:; //~ ERROR can't use generic parameters from outer item
     };
 }
 
diff --git a/tests/ui/generics/issue-98432.stderr b/tests/ui/generics/issue-98432.stderr
index c7b5c33618d5f..0736d94106e7d 100644
--- a/tests/ui/generics/issue-98432.stderr
+++ b/tests/ui/generics/issue-98432.stderr
@@ -1,13 +1,13 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-98432.rs:5:34
    |
 LL | impl<T> Struct<T> {
-   |      - type parameter from outer function
+   |      - type parameter from outer item
 LL |     const CONST: fn() = || {
 LL |         struct _Obligation where T:;
-   |                           -      ^ use of generic parameter from outer function
+   |                           -      ^ use of generic parameter from outer item
    |                           |
-   |                           help: try using a local generic parameter instead: `<T>`
+   |                           help: try introducing a local generic parameter here: `<T>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/inner-static-type-parameter.rs b/tests/ui/inner-static-type-parameter.rs
index c08ccd29d8011..a1994e7529cb7 100644
--- a/tests/ui/inner-static-type-parameter.rs
+++ b/tests/ui/inner-static-type-parameter.rs
@@ -4,7 +4,7 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
 
 fn foo<T>() {
     static a: Bar<T> = Bar::What;
-//~^ ERROR can't use generic parameters from outer function
+//~^ ERROR can't use generic parameters from outer item
 }
 
 fn main() {
diff --git a/tests/ui/inner-static-type-parameter.stderr b/tests/ui/inner-static-type-parameter.stderr
index e4e449e4159b6..ff6558e494b11 100644
--- a/tests/ui/inner-static-type-parameter.stderr
+++ b/tests/ui/inner-static-type-parameter.stderr
@@ -1,10 +1,10 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/inner-static-type-parameter.rs:6:19
    |
 LL | fn foo<T>() {
-   |        - type parameter from outer function
+   |        - type parameter from outer item
 LL |     static a: Bar<T> = Bar::What;
-   |                   ^ use of generic parameter from outer function
+   |                   ^ use of generic parameter from outer item
 
 error[E0392]: parameter `T` is never used
   --> $DIR/inner-static-type-parameter.rs:3:10
diff --git a/tests/ui/issues/issue-3214.rs b/tests/ui/issues/issue-3214.rs
index e3c07bb3f724f..b2c27f5be957c 100644
--- a/tests/ui/issues/issue-3214.rs
+++ b/tests/ui/issues/issue-3214.rs
@@ -1,6 +1,6 @@
 fn foo<T>() {
     struct Foo {
-        x: T, //~ ERROR can't use generic parameters from outer function
+        x: T, //~ ERROR can't use generic parameters from outer item
     }
 
     impl<T> Drop for Foo<T> {
diff --git a/tests/ui/issues/issue-3214.stderr b/tests/ui/issues/issue-3214.stderr
index 7a2d772f0a1b5..5b57c1baf90ba 100644
--- a/tests/ui/issues/issue-3214.stderr
+++ b/tests/ui/issues/issue-3214.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-3214.rs:3:12
    |
 LL | fn foo<T>() {
-   |        - type parameter from outer function
+   |        - type parameter from outer item
 LL |     struct Foo {
-   |               - help: try using a local generic parameter instead: `<T>`
+   |               - help: try introducing a local generic parameter here: `<T>`
 LL |         x: T,
-   |            ^ use of generic parameter from outer function
+   |            ^ use of generic parameter from outer item
 
 error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/issue-3214.rs:6:22
diff --git a/tests/ui/issues/issue-5997-enum.rs b/tests/ui/issues/issue-5997-enum.rs
index 3ff4e036c60be..0b1857ae3df30 100644
--- a/tests/ui/issues/issue-5997-enum.rs
+++ b/tests/ui/issues/issue-5997-enum.rs
@@ -1,6 +1,6 @@
 fn f<Z>() -> bool {
     enum E { V(Z) }
-    //~^ ERROR can't use generic parameters from outer function
+    //~^ ERROR can't use generic parameters from outer item
     true
 }
 
diff --git a/tests/ui/issues/issue-5997-enum.stderr b/tests/ui/issues/issue-5997-enum.stderr
index 3a79215d3ae9c..d07258ea7a2f9 100644
--- a/tests/ui/issues/issue-5997-enum.stderr
+++ b/tests/ui/issues/issue-5997-enum.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-5997-enum.rs:2:16
    |
 LL | fn f<Z>() -> bool {
-   |      - type parameter from outer function
+   |      - type parameter from outer item
 LL |     enum E { V(Z) }
-   |           -    ^ use of generic parameter from outer function
+   |           -    ^ use of generic parameter from outer item
    |           |
-   |           help: try using a local generic parameter instead: `<Z>`
+   |           help: try introducing a local generic parameter here: `<Z>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-5997-struct.rs b/tests/ui/issues/issue-5997-struct.rs
index 6cf510b0a9d75..19d994b0dfb7a 100644
--- a/tests/ui/issues/issue-5997-struct.rs
+++ b/tests/ui/issues/issue-5997-struct.rs
@@ -1,5 +1,5 @@
 fn f<T>() -> bool {
-    struct S(T); //~ ERROR can't use generic parameters from outer function
+    struct S(T); //~ ERROR can't use generic parameters from outer item
 
     true
 }
diff --git a/tests/ui/issues/issue-5997-struct.stderr b/tests/ui/issues/issue-5997-struct.stderr
index d2e97f767719f..83229e02c6ca0 100644
--- a/tests/ui/issues/issue-5997-struct.stderr
+++ b/tests/ui/issues/issue-5997-struct.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-5997-struct.rs:2:14
    |
 LL | fn f<T>() -> bool {
-   |      - type parameter from outer function
+   |      - type parameter from outer item
 LL |     struct S(T);
-   |             -^ use of generic parameter from outer function
+   |             -^ use of generic parameter from outer item
    |             |
-   |             help: try using a local generic parameter instead: `<T>`
+   |             help: try introducing a local generic parameter here: `<T>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/nested-ty-params.rs b/tests/ui/nested-ty-params.rs
index 85413acdb1491..25bac1ba24bd1 100644
--- a/tests/ui/nested-ty-params.rs
+++ b/tests/ui/nested-ty-params.rs
@@ -1,4 +1,4 @@
-// error-pattern:can't use generic parameters from outer function
+// error-pattern:can't use generic parameters from outer item
 fn hd<U>(v: Vec<U> ) -> U {
     fn hd1(w: [U]) -> U { return w[0]; }
 
diff --git a/tests/ui/nested-ty-params.stderr b/tests/ui/nested-ty-params.stderr
index 8f4746f5ec3bd..a9cdec667199a 100644
--- a/tests/ui/nested-ty-params.stderr
+++ b/tests/ui/nested-ty-params.stderr
@@ -1,22 +1,22 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/nested-ty-params.rs:3:16
    |
 LL | fn hd<U>(v: Vec<U> ) -> U {
-   |       - type parameter from outer function
+   |       - type parameter from outer item
 LL |     fn hd1(w: [U]) -> U { return w[0]; }
-   |           -    ^ use of generic parameter from outer function
+   |           -    ^ use of generic parameter from outer item
    |           |
-   |           help: try using a local generic parameter instead: `<U>`
+   |           help: try introducing a local generic parameter here: `<U>`
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/nested-ty-params.rs:3:23
    |
 LL | fn hd<U>(v: Vec<U> ) -> U {
-   |       - type parameter from outer function
+   |       - type parameter from outer item
 LL |     fn hd1(w: [U]) -> U { return w[0]; }
-   |           -           ^ use of generic parameter from outer function
+   |           -           ^ use of generic parameter from outer item
    |           |
-   |           help: try using a local generic parameter instead: `<U>`
+   |           help: try introducing a local generic parameter here: `<U>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/resolve/bad-type-env-capture.stderr b/tests/ui/resolve/bad-type-env-capture.stderr
index b6282c2d0703b..941b6b7a68c35 100644
--- a/tests/ui/resolve/bad-type-env-capture.stderr
+++ b/tests/ui/resolve/bad-type-env-capture.stderr
@@ -1,12 +1,12 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/bad-type-env-capture.rs:2:15
    |
 LL | fn foo<T>() {
-   |        - type parameter from outer function
+   |        - type parameter from outer item
 LL |     fn bar(b: T) { }
-   |           -   ^ use of generic parameter from outer function
+   |           -   ^ use of generic parameter from outer item
    |           |
-   |           help: try using a local generic parameter instead: `<T>`
+   |           help: try introducing a local generic parameter here: `<T>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/resolve/issue-12796.rs b/tests/ui/resolve/issue-12796.rs
index 942d6b9a5686e..de3e73437f080 100644
--- a/tests/ui/resolve/issue-12796.rs
+++ b/tests/ui/resolve/issue-12796.rs
@@ -1,7 +1,7 @@
 trait Trait {
     fn outer(&self) {
         fn inner(_: &Self) {
-            //~^ ERROR can't use generic parameters from outer function
+            //~^ ERROR can't use generic parameters from outer item
         }
     }
 }
diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr
index a01fd2d65420b..ef59d00360b88 100644
--- a/tests/ui/resolve/issue-12796.stderr
+++ b/tests/ui/resolve/issue-12796.stderr
@@ -1,10 +1,10 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-12796.rs:3:22
    |
 LL |         fn inner(_: &Self) {
    |                      ^^^^
    |                      |
-   |                      use of generic parameter from outer function
+   |                      use of generic parameter from outer item
    |                      can't use `Self` here
 
 error: aborting due to previous error
diff --git a/tests/ui/resolve/issue-3021-c.rs b/tests/ui/resolve/issue-3021-c.rs
index 94ed1fdf78191..bd21d1244235d 100644
--- a/tests/ui/resolve/issue-3021-c.rs
+++ b/tests/ui/resolve/issue-3021-c.rs
@@ -1,8 +1,8 @@
 fn siphash<T>() {
 
     trait U {
-        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
-        //~^ ERROR can't use generic parameters from outer function
+        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer item
+        //~^ ERROR can't use generic parameters from outer item
     }
 }
 
diff --git a/tests/ui/resolve/issue-3021-c.stderr b/tests/ui/resolve/issue-3021-c.stderr
index 5176efc3a6be7..537bbaf7b6a56 100644
--- a/tests/ui/resolve/issue-3021-c.stderr
+++ b/tests/ui/resolve/issue-3021-c.stderr
@@ -1,24 +1,24 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-3021-c.rs:4:24
    |
 LL | fn siphash<T>() {
-   |            - type parameter from outer function
+   |            - type parameter from outer item
 LL |
 LL |     trait U {
-   |            - help: try using a local generic parameter instead: `<T>`
+   |            - help: try introducing a local generic parameter here: `<T>`
 LL |         fn g(&self, x: T) -> T;
-   |                        ^ use of generic parameter from outer function
+   |                        ^ use of generic parameter from outer item
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-3021-c.rs:4:30
    |
 LL | fn siphash<T>() {
-   |            - type parameter from outer function
+   |            - type parameter from outer item
 LL |
 LL |     trait U {
-   |            - help: try using a local generic parameter instead: `<T>`
+   |            - help: try introducing a local generic parameter here: `<T>`
 LL |         fn g(&self, x: T) -> T;
-   |                              ^ use of generic parameter from outer function
+   |                              ^ use of generic parameter from outer item
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.rs b/tests/ui/resolve/issue-65025-extern-static-parent-generics.rs
index ce45f630e48a5..4fa3f12d024d5 100644
--- a/tests/ui/resolve/issue-65025-extern-static-parent-generics.rs
+++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.rs
@@ -1,7 +1,7 @@
 unsafe fn foo<A>() {
     extern "C" {
         static baz: *const A;
-        //~^ ERROR can't use generic parameters from outer function
+        //~^ ERROR can't use generic parameters from outer item
     }
 
     let bar: *const u64 = core::mem::transmute(&baz);
diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr
index 6bbf76dd1fbb2..3e9c3fd11b74d 100644
--- a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr
+++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr
@@ -1,11 +1,11 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-65025-extern-static-parent-generics.rs:3:28
    |
 LL | unsafe fn foo<A>() {
-   |               - type parameter from outer function
+   |               - type parameter from outer item
 LL |     extern "C" {
 LL |         static baz: *const A;
-   |                            ^ use of generic parameter from outer function
+   |                            ^ use of generic parameter from outer item
 
 error: aborting due to previous error
 
diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.rs b/tests/ui/resolve/issue-65035-static-with-parent-generics.rs
index f96c04841dd28..bc99584a8d26a 100644
--- a/tests/ui/resolve/issue-65035-static-with-parent-generics.rs
+++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.rs
@@ -1,26 +1,26 @@
 fn f<T>() {
     extern "C" {
         static a: *const T;
-        //~^ ERROR can't use generic parameters from outer function
+        //~^ ERROR can't use generic parameters from outer item
     }
 }
 
 fn g<T: Default>() {
     static a: *const T = Default::default();
-    //~^ ERROR can't use generic parameters from outer function
+    //~^ ERROR can't use generic parameters from outer item
 }
 
 fn h<const N: usize>() {
     extern "C" {
         static a: [u8; N];
-        //~^ ERROR can't use generic parameters from outer function
+        //~^ ERROR can't use generic parameters from outer item
     }
 }
 
 fn i<const N: usize>() {
     static a: [u8; N] = [0; N];
-    //~^ ERROR can't use generic parameters from outer function
-    //~| ERROR can't use generic parameters from outer function
+    //~^ ERROR can't use generic parameters from outer item
+    //~| ERROR can't use generic parameters from outer item
 }
 
 fn main() {}
diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr
index 7ed572f80b896..f1fe1a6002c93 100644
--- a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr
+++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr
@@ -1,44 +1,44 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-65035-static-with-parent-generics.rs:3:26
    |
 LL | fn f<T>() {
-   |      - type parameter from outer function
+   |      - type parameter from outer item
 LL |     extern "C" {
 LL |         static a: *const T;
-   |                          ^ use of generic parameter from outer function
+   |                          ^ use of generic parameter from outer item
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-65035-static-with-parent-generics.rs:9:22
    |
 LL | fn g<T: Default>() {
-   |      - type parameter from outer function
+   |      - type parameter from outer item
 LL |     static a: *const T = Default::default();
-   |                      ^ use of generic parameter from outer function
+   |                      ^ use of generic parameter from outer item
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-65035-static-with-parent-generics.rs:15:24
    |
 LL | fn h<const N: usize>() {
-   |            - const parameter from outer function
+   |            - const parameter from outer item
 LL |     extern "C" {
 LL |         static a: [u8; N];
-   |                        ^ use of generic parameter from outer function
+   |                        ^ use of generic parameter from outer item
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-65035-static-with-parent-generics.rs:21:20
    |
 LL | fn i<const N: usize>() {
-   |            - const parameter from outer function
+   |            - const parameter from outer item
 LL |     static a: [u8; N] = [0; N];
-   |                    ^ use of generic parameter from outer function
+   |                    ^ use of generic parameter from outer item
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/issue-65035-static-with-parent-generics.rs:21:29
    |
 LL | fn i<const N: usize>() {
-   |            - const parameter from outer function
+   |            - const parameter from outer item
 LL |     static a: [u8; N] = [0; N];
-   |                             ^ use of generic parameter from outer function
+   |                             ^ use of generic parameter from outer item
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/resolve/resolve-type-param-in-item-in-trait.rs b/tests/ui/resolve/resolve-type-param-in-item-in-trait.rs
index c77a66524f73f..2d5f34c62a6f9 100644
--- a/tests/ui/resolve/resolve-type-param-in-item-in-trait.rs
+++ b/tests/ui/resolve/resolve-type-param-in-item-in-trait.rs
@@ -6,7 +6,7 @@ trait TraitA<A> {
     fn outer(&self) {
         enum Foo<B> {
             Variance(A)
-                //~^ ERROR can't use generic parameters from outer function
+                //~^ ERROR can't use generic parameters from outer item
         }
     }
 }
@@ -14,21 +14,21 @@ trait TraitA<A> {
 trait TraitB<A> {
     fn outer(&self) {
         struct Foo<B>(A);
-                //~^ ERROR can't use generic parameters from outer function
+                //~^ ERROR can't use generic parameters from outer item
     }
 }
 
 trait TraitC<A> {
     fn outer(&self) {
         struct Foo<B> { a: A }
-                //~^ ERROR can't use generic parameters from outer function
+                //~^ ERROR can't use generic parameters from outer item
     }
 }
 
 trait TraitD<A> {
     fn outer(&self) {
         fn foo<B>(a: A) { }
-                //~^ ERROR can't use generic parameters from outer function
+                //~^ ERROR can't use generic parameters from outer item
     }
 }
 
diff --git a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr
index 0a6d1cc3bcd45..1ab56fdc50441 100644
--- a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr
+++ b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr
@@ -1,46 +1,46 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/resolve-type-param-in-item-in-trait.rs:8:22
    |
 LL | trait TraitA<A> {
-   |              - type parameter from outer function
+   |              - type parameter from outer item
 LL |     fn outer(&self) {
 LL |         enum Foo<B> {
-   |                  - help: try using a local generic parameter instead: `A,`
+   |                  - help: try introducing a local generic parameter here: `A,`
 LL |             Variance(A)
-   |                      ^ use of generic parameter from outer function
+   |                      ^ use of generic parameter from outer item
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/resolve-type-param-in-item-in-trait.rs:16:23
    |
 LL | trait TraitB<A> {
-   |              - type parameter from outer function
+   |              - type parameter from outer item
 LL |     fn outer(&self) {
 LL |         struct Foo<B>(A);
-   |                    -  ^ use of generic parameter from outer function
+   |                    -  ^ use of generic parameter from outer item
    |                    |
-   |                    help: try using a local generic parameter instead: `A,`
+   |                    help: try introducing a local generic parameter here: `A,`
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/resolve-type-param-in-item-in-trait.rs:23:28
    |
 LL | trait TraitC<A> {
-   |              - type parameter from outer function
+   |              - type parameter from outer item
 LL |     fn outer(&self) {
 LL |         struct Foo<B> { a: A }
-   |                    -       ^ use of generic parameter from outer function
+   |                    -       ^ use of generic parameter from outer item
    |                    |
-   |                    help: try using a local generic parameter instead: `A,`
+   |                    help: try introducing a local generic parameter here: `A,`
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/resolve-type-param-in-item-in-trait.rs:30:22
    |
 LL | trait TraitD<A> {
-   |              - type parameter from outer function
+   |              - type parameter from outer item
 LL |     fn outer(&self) {
 LL |         fn foo<B>(a: A) { }
-   |                -     ^ use of generic parameter from outer function
+   |                -     ^ use of generic parameter from outer item
    |                |
-   |                help: try using a local generic parameter instead: `A,`
+   |                help: try introducing a local generic parameter here: `A,`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/resolve/use-self-in-inner-fn.rs b/tests/ui/resolve/use-self-in-inner-fn.rs
index eccb315feb1e2..f4dfa4c40ab24 100644
--- a/tests/ui/resolve/use-self-in-inner-fn.rs
+++ b/tests/ui/resolve/use-self-in-inner-fn.rs
@@ -4,9 +4,9 @@ impl A {
 //~^ NOTE `Self` type implicitly declared here, by this `impl`
     fn banana(&mut self) {
         fn peach(this: &Self) {
-        //~^ ERROR can't use generic parameters from outer function
-        //~| NOTE use of generic parameter from outer function
-        //~| NOTE use a type here instead
+        //~^ ERROR can't use generic parameters from outer item
+        //~| NOTE use of generic parameter from outer item
+        //~| NOTE refer to the type directly here instead
         }
     }
 }
diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr
index 966093499241d..832aaacaf49c8 100644
--- a/tests/ui/resolve/use-self-in-inner-fn.stderr
+++ b/tests/ui/resolve/use-self-in-inner-fn.stderr
@@ -1,4 +1,4 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/use-self-in-inner-fn.rs:6:25
    |
 LL | impl A {
@@ -7,8 +7,8 @@ LL | impl A {
 LL |         fn peach(this: &Self) {
    |                         ^^^^
    |                         |
-   |                         use of generic parameter from outer function
-   |                         use a type here instead
+   |                         use of generic parameter from outer item
+   |                         refer to the type directly here instead
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type/type-arg-out-of-scope.rs b/tests/ui/type/type-arg-out-of-scope.rs
index 02aad00770793..c36f9904e5dc1 100644
--- a/tests/ui/type/type-arg-out-of-scope.rs
+++ b/tests/ui/type/type-arg-out-of-scope.rs
@@ -1,4 +1,4 @@
-// error-pattern:can't use generic parameters from outer function
+// error-pattern:can't use generic parameters from outer item
 fn foo<T>(x: T) {
     fn bar(f: Box<dyn FnMut(T) -> T>) { }
 }
diff --git a/tests/ui/type/type-arg-out-of-scope.stderr b/tests/ui/type/type-arg-out-of-scope.stderr
index 7f18b4510f4b2..8665001e24319 100644
--- a/tests/ui/type/type-arg-out-of-scope.stderr
+++ b/tests/ui/type/type-arg-out-of-scope.stderr
@@ -1,22 +1,22 @@
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/type-arg-out-of-scope.rs:3:29
    |
 LL | fn foo<T>(x: T) {
-   |        - type parameter from outer function
+   |        - type parameter from outer item
 LL |     fn bar(f: Box<dyn FnMut(T) -> T>) { }
-   |           -                 ^ use of generic parameter from outer function
+   |           -                 ^ use of generic parameter from outer item
    |           |
-   |           help: try using a local generic parameter instead: `<T>`
+   |           help: try introducing a local generic parameter here: `<T>`
 
-error[E0401]: can't use generic parameters from outer function
+error[E0401]: can't use generic parameters from outer item
   --> $DIR/type-arg-out-of-scope.rs:3:35
    |
 LL | fn foo<T>(x: T) {
-   |        - type parameter from outer function
+   |        - type parameter from outer item
 LL |     fn bar(f: Box<dyn FnMut(T) -> T>) { }
-   |           -                       ^ use of generic parameter from outer function
+   |           -                       ^ use of generic parameter from outer item
    |           |
-   |           help: try using a local generic parameter instead: `<T>`
+   |           help: try introducing a local generic parameter here: `<T>`
 
 error: aborting due to 2 previous errors
 

From 9b3625247782650d57efa141ee4378eafe0d8dee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Sun, 10 Sep 2023 23:06:28 +0200
Subject: [PATCH 7/9] Make E0401 translatable

---
 compiler/rustc_resolve/messages.ftl       | 29 ++++++++----------
 compiler/rustc_resolve/src/diagnostics.rs | 37 +++++++++++------------
 compiler/rustc_resolve/src/errors.rs      | 34 +++++++++++++++++++++
 3 files changed, 65 insertions(+), 35 deletions(-)

diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index f98918cba8800..619c30ac54a33 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -64,9 +64,6 @@ resolve_cannot_find_ident_in_this_scope =
 resolve_cannot_glob_import_possible_crates =
     cannot glob-import all possible crates
 
-resolve_cannot_use_self_type_here =
-    can't use `Self` here
-
 resolve_change_import_binding =
     you can use `as` to change the binding name of the import
 
@@ -86,9 +83,6 @@ resolve_const_not_member_of_trait =
     const `{$const_}` is not a member of trait `{$trait_}`
     .label = not a member of trait `{$trait_}`
 
-resolve_const_param_from_outer_fn =
-    const parameter from outer function
-
 resolve_const_param_in_enum_discriminant =
     const parameters may not be used in enum discriminant values
 
@@ -115,10 +109,19 @@ resolve_forward_declared_generic_param =
     generic parameters with a default cannot use forward declared identifiers
     .label = defaulted generic parameters cannot be forward declared
 
-resolve_generic_params_from_outer_function =
-    can't use generic parameters from outer function
-    .label = use of generic parameter from outer function
-    .suggestion = try using a local generic parameter instead
+resolve_generic_params_from_outer_item =
+    can't use generic parameters from outer item
+    .label = use of generic parameter from outer item
+    .refer_to_type_directly = refer to the type directly here instead
+    .suggestion = try introducing a local generic parameter here
+
+resolve_generic_params_from_outer_item_const_param = const parameter from outer item
+
+resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl`
+
+resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here
+
+resolve_generic_params_from_outer_item_ty_param = type parameter from outer item
 
 resolve_glob_import_doesnt_reexport =
     glob import doesn't reexport anything because no candidate is public enough
@@ -273,9 +276,6 @@ resolve_type_not_member_of_trait =
     type `{$type_}` is not a member of trait `{$trait_}`
     .label = not a member of trait `{$trait_}`
 
-resolve_type_param_from_outer_fn =
-    type parameter from outer function
-
 resolve_type_param_in_enum_discriminant =
     type parameters may not be used in enum discriminant values
 
@@ -311,9 +311,6 @@ resolve_unreachable_label_suggestion_use_similarly_named =
 resolve_unreachable_label_with_similar_name_exists =
     a label with a similar name exists but is unreachable
 
-resolve_use_a_type_here_instead =
-    use a type here instead
-
 resolve_variable_bound_with_different_mode =
     variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
     .label = bound in different ways
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index a99b610ed36af..bcf62d8a2f290 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -554,34 +554,34 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         match resolution_error {
             ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
+                use errs::GenericParamsFromOuterItemLabel as Label;
+                let mut err = errs::GenericParamsFromOuterItem {
                     span,
-                    E0401,
-                    "can't use generic parameters from outer item",
-                );
-                err.span_label(span, "use of generic parameter from outer item");
+                    label: None,
+                    refer_to_type_directly: None,
+                    sugg: None,
+                };
 
                 let sm = self.tcx.sess.source_map();
                 let def_id = match outer_res {
                     Res::SelfTyParam { .. } => {
-                        err.span_label(span, "can't use `Self` here");
-                        return err;
+                        err.label = Some(Label::SelfTyParam(span));
+                        return self.tcx.sess.create_err(err);
                     }
                     Res::SelfTyAlias { alias_to: def_id, .. } => {
-                        err.span_label(
-                            reduce_impl_span_to_impl_keyword(sm, self.def_span(def_id)),
-                            "`Self` type implicitly declared here, by this `impl`",
-                        );
-                        err.span_label(span, "refer to the type directly here instead");
-                        return err;
+                        err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
+                            sm,
+                            self.def_span(def_id),
+                        )));
+                        err.refer_to_type_directly = Some(span);
+                        return self.tcx.sess.create_err(err);
                     }
                     Res::Def(DefKind::TyParam, def_id) => {
-                        err.span_label(self.def_span(def_id), "type parameter from outer item");
+                        err.label = Some(Label::TyParam(self.def_span(def_id)));
                         def_id
                     }
                     Res::Def(DefKind::ConstParam, def_id) => {
-                        err.span_label(self.def_span(def_id), "const parameter from outer item");
+                        err.label = Some(Label::ConstParam(self.def_span(def_id)));
                         def_id
                     }
                     _ => {
@@ -594,7 +594,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 };
 
                 if let HasGenericParams::Yes(span) = has_generic_params {
-                    let sugg_msg = "try introducing a local generic parameter here";
                     let name = self.tcx.item_name(def_id);
                     let (span, snippet) = if span.is_empty() {
                         let snippet = format!("<{name}>");
@@ -604,10 +603,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         let snippet = format!("{name}, ");
                         (span, snippet)
                     };
-                    err.span_suggestion(span, sugg_msg, snippet, Applicability::MaybeIncorrect);
+                    err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet });
                 }
 
-                err
+                self.tcx.sess.create_err(err)
             }
             ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
                 .tcx
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index e4b89c65853d0..4f91f6aa90f79 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -32,6 +32,40 @@ pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate)
 #[diag(resolve_crate_root_imports_must_be_named_explicitly)]
 pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
 
+#[derive(Diagnostic)]
+#[diag(resolve_generic_params_from_outer_item, code = "E0401")]
+pub(crate) struct GenericParamsFromOuterItem {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    #[subdiagnostic]
+    pub(crate) label: Option<GenericParamsFromOuterItemLabel>,
+    #[label(resolve_refer_to_type_directly)]
+    pub(crate) refer_to_type_directly: Option<Span>,
+    #[subdiagnostic]
+    pub(crate) sugg: Option<GenericParamsFromOuterItemSugg>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum GenericParamsFromOuterItemLabel {
+    #[label(resolve_generic_params_from_outer_item_self_ty_param)]
+    SelfTyParam(#[primary_span] Span),
+    #[label(resolve_generic_params_from_outer_item_self_ty_alias)]
+    SelfTyAlias(#[primary_span] Span),
+    #[label(resolve_generic_params_from_outer_item_ty_param)]
+    TyParam(#[primary_span] Span),
+    #[label(resolve_generic_params_from_outer_item_const_param)]
+    ConstParam(#[primary_span] Span),
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(resolve_suggestion, code = "{snippet}", applicability = "maybe-incorrect")]
+pub(crate) struct GenericParamsFromOuterItemSugg {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) snippet: String,
+}
+
 #[derive(Diagnostic)]
 #[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
 pub(crate) struct NameAlreadyUsedInParameterList {

From daf3c45531815e8015e8a508f2650fcfa166cf29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Sun, 10 Sep 2023 22:29:37 +0200
Subject: [PATCH 8/9] Do not suggest generic const items unless enabled

---
 compiler/rustc_resolve/src/late.rs            |  6 ++-
 ...om-outer-item-in-const-item.default.stderr | 28 +++++++++++++
 ...m-in-const-item.generic_const_items.stderr | 34 ++++++++++++++++
 ...ic-params-from-outer-item-in-const-item.rs | 39 +++++++++++++++++++
 4 files changed, 106 insertions(+), 1 deletion(-)
 create mode 100644 tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr
 create mode 100644 tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr
 create mode 100644 tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 486d60eab2101..d40b1b2e3a900 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2450,7 +2450,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
                 self.with_generic_param_rib(
                     &generics.params,
-                    RibKind::Item(HasGenericParams::Yes(generics.span)),
+                    RibKind::Item(if self.r.tcx.features().generic_const_items {
+                        HasGenericParams::Yes(generics.span)
+                    } else {
+                        HasGenericParams::No
+                    }),
                     LifetimeRibKind::Generics {
                         binder: item.id,
                         kind: LifetimeBinderKind::ConstItem,
diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr
new file mode 100644
index 0000000000000..4f8538292792c
--- /dev/null
+++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr
@@ -0,0 +1,28 @@
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:12:20
+   |
+LL | fn outer<T: Tr>() { // outer function
+   |          - type parameter from outer item
+LL |     const K: u32 = T::C;
+   |                    ^^^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24
+   |
+LL | impl<T> Tr for T { // outer impl block
+   |      - type parameter from outer item
+LL |     const C: u32 = {
+LL |         const I: u32 = T::C;
+   |                        ^^^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20
+   |
+LL | struct S<T: Tr>(U32<{ // outer struct
+   |          - type parameter from outer item
+LL |     const _: u32 = T::C;
+   |                    ^^^^ use of generic parameter from outer item
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr
new file mode 100644
index 0000000000000..1cb55842bc665
--- /dev/null
+++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr
@@ -0,0 +1,34 @@
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:12:20
+   |
+LL | fn outer<T: Tr>() { // outer function
+   |          - type parameter from outer item
+LL |     const K: u32 = T::C;
+   |            -       ^^^^ use of generic parameter from outer item
+   |            |
+   |            help: try introducing a local generic parameter here: `<T>`
+
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24
+   |
+LL | impl<T> Tr for T { // outer impl block
+   |      - type parameter from outer item
+LL |     const C: u32 = {
+LL |         const I: u32 = T::C;
+   |                -       ^^^^ use of generic parameter from outer item
+   |                |
+   |                help: try introducing a local generic parameter here: `<T>`
+
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20
+   |
+LL | struct S<T: Tr>(U32<{ // outer struct
+   |          - type parameter from outer item
+LL |     const _: u32 = T::C;
+   |            -       ^^^^ use of generic parameter from outer item
+   |            |
+   |            help: try introducing a local generic parameter here: `<T>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs
new file mode 100644
index 0000000000000..e5647d72cba35
--- /dev/null
+++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs
@@ -0,0 +1,39 @@
+// Regression test for issue #115720.
+// If a const item contains generic params from an outer items, only suggest
+// turning the const item generic if the feature `generic_const_items` is enabled.
+
+// revisions: default generic_const_items
+
+#![cfg_attr(generic_const_items, feature(generic_const_items))]
+#![feature(generic_const_exprs)] // only used for the test case "outer struct"
+#![allow(incomplete_features)]
+
+fn outer<T: Tr>() { // outer function
+    const K: u32 = T::C;
+    //~^ ERROR can't use generic parameters from outer item
+    //[generic_const_items]~| HELP try introducing a local generic parameter here
+}
+
+impl<T> Tr for T { // outer impl block
+    const C: u32 = {
+        const I: u32 = T::C;
+        //~^ ERROR can't use generic parameters from outer item
+        //[generic_const_items]~| HELP try introducing a local generic parameter here
+        I
+    };
+}
+
+struct S<T: Tr>(U32<{ // outer struct
+    const _: u32 = T::C;
+    //~^ ERROR can't use generic parameters from outer item
+    //[generic_const_items]~| HELP try introducing a local generic parameter here
+    0
+}>);
+
+trait Tr {
+    const C: u32;
+}
+
+struct U32<const N: u32>;
+
+fn main() {}

From 30e6cea0ae4780bdd99e56fc85719dcb4305c900 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 10 Sep 2023 03:33:07 +0000
Subject: [PATCH 9/9] Point out if a local trait has no implementations

---
 compiler/rustc_middle/src/ty/trait_def.rs     |   4 +
 compiler/rustc_trait_selection/messages.ftl   |   2 +
 .../src/traits/error_reporting/mod.rs         |  24 +-
 .../associated-const-array-len.stderr         |   6 +
 .../ui/associated-consts/issue-105330.stderr  |  10 +
 ...ypes-ICE-when-projecting-out-of-err.stderr |   6 +
 ...ciated-types-no-suitable-supertrait.stderr |   6 +
 .../defaults-suitability.stderr               |   5 +
 tests/ui/associated-types/issue-59324.stderr  |   6 +
 tests/ui/associated-types/issue-64855.stderr  |   6 +
 ...int-at-type-on-obligation-failure-2.stderr |  15 ++
 .../coherence-unsafe-trait-object-impl.stderr |   5 +
 .../dont-evaluate-array-len-on-err-1.stderr   |   6 +
 .../generic_const_exprs/issue-85848.stderr    |   6 +-
 .../const-generics/issues/issue-86530.stderr  |   5 +
 tests/ui/cross/cross-fn-cache-hole.stderr     |   5 +
 tests/ui/dst/dst-bad-coerce1.stderr           |  10 +
 tests/ui/dyn-star/error.stderr                |   6 +
 tests/ui/error-codes/E0277.stderr             |   5 +
 .../issue-101020.stderr                       |   5 +
 .../normalize-under-binder/issue-89118.stderr |  15 ++
 tests/ui/issues/issue-18611.stderr            |   6 +
 tests/ui/issues/issue-25076.stderr            |   5 +
 tests/ui/issues/issue-35570.stderr            |   6 +
 tests/ui/issues/issue-60218.stderr            |   5 +
 tests/ui/issues/issue-66353.stderr            |  12 +
 .../lifetime-elision-return-type-trait.stderr |   6 +
 tests/ui/namespace/namespace-mix.stderr       | 220 ++++++++++++++++++
 .../feature-gate-never_type_fallback.stderr   |   5 +
 .../ui/never_type/impl_trait_fallback3.stderr |   6 +
 .../ui/never_type/impl_trait_fallback4.stderr |   6 +
 tests/ui/on-unimplemented/on-trait.stderr     |  10 +
 tests/ui/on-unimplemented/parent-label.stderr |  20 ++
 tests/ui/proc-macro/bad-projection.stderr     |   6 +
 tests/ui/span/issue-29595.stderr              |   6 +
 tests/ui/specialization/issue-38091.stderr    |   5 +
 tests/ui/suggestions/issue-89333.stderr       |   5 +
 tests/ui/trait-bounds/issue-82038.stderr      |   6 +
 .../bound/on-structs-and-enums-in-fns.stderr  |  10 +
 .../on-structs-and-enums-in-impls.stderr      |   5 +
 .../bound/on-structs-and-enums-locals.stderr  |  10 +
 .../bound/on-structs-and-enums-static.stderr  |   5 +
 .../traits/bound/on-structs-and-enums.stderr  |  20 ++
 .../deny-builtin-object-impl.current.stderr   |   5 +
 .../deny-builtin-object-impl.next.stderr      |   5 +
 ...dont-autoderef-ty-with-escaping-var.stderr |   5 +
 tests/ui/traits/impl-bounds-checking.stderr   |   5 +
 .../new-solver/projection-discr-kind.stderr   |   5 +
 .../traits/non_lifetime_binders/fail.stderr   |   5 +
 .../traits/object-does-not-impl-trait.stderr  |   5 +
 tests/ui/traits/vtable-res-trait-param.stderr |   5 +
 .../trivial-bounds/trivial-bounds-leak.stderr |  11 +
 .../projection-as-union-type-error-2.stderr   |   5 +
 .../projection-as-union-type-error.stderr     |   6 +
 tests/ui/unsized/issue-75707.stderr           |   5 +
 tests/ui/wf/hir-wf-canonicalized.stderr       |  12 +
 tests/ui/wf/issue-95665.stderr                |   5 +
 tests/ui/wf/wf-complex-assoc-type.stderr      |   5 +
 tests/ui/wf/wf-foreign-fn-decl-ret.stderr     |  11 +
 ...ked-on-proj-of-type-as-unimpl-trait.stderr |   6 +
 .../higher-ranked-fn-type.quiet.stderr        |   5 +
 .../higher-ranked-fn-type.verbose.stderr      |   5 +
 .../where-clause-method-substituion.stderr    |   5 +
 63 files changed, 658 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 6e55e7915c92d..bf9b244936fc6 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -90,6 +90,10 @@ pub struct TraitImpls {
 }
 
 impl TraitImpls {
+    pub fn is_empty(&self) -> bool {
+        self.blanket_impls.is_empty() && self.non_blanket_impls.is_empty()
+    }
+
     pub fn blanket_impls(&self) -> &[DefId] {
         self.blanket_impls.as_slice()
     }
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 2a09a7dcd89dc..2db24c43734f8 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -40,5 +40,7 @@ trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a
     .label = expected value here
     .note = eg `#[rustc_on_unimplemented(message="foo")]`
 
+trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one
+
 trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead
 trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 746a38f956ab3..e4f5c4003c911 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -3009,10 +3009,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         // Try to report a help message
         if is_fn_trait
             && let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
-            obligation.param_env,
-            trait_ref.self_ty(),
-            trait_predicate.skip_binder().polarity,
-        )
+                obligation.param_env,
+                trait_ref.self_ty(),
+                trait_predicate.skip_binder().polarity,
+            )
         {
             self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params);
         } else if !trait_ref.has_non_region_infer()
@@ -3031,6 +3031,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 None,
                 obligation.cause.body_id,
             );
+        } else if trait_ref.def_id().is_local()
+            && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty()
+            && !self.tcx.trait_is_auto(trait_ref.def_id())
+            && !self.tcx.trait_is_alias(trait_ref.def_id())
+        {
+            err.span_help(
+                self.tcx.def_span(trait_ref.def_id()),
+                crate::fluent_generated::trait_selection_trait_has_no_impls,
+            );
         } else if !suggested && !unsatisfied_const {
             // Can't show anything else useful, try to find similar impls.
             let impl_candidates = self.find_similar_impl_candidates(*trait_predicate);
@@ -3041,7 +3050,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 err,
                 true,
             ) {
-                self.report_similar_impl_candidates_for_root_obligation(&obligation, *trait_predicate, body_def_id, err);
+                self.report_similar_impl_candidates_for_root_obligation(
+                    &obligation,
+                    *trait_predicate,
+                    body_def_id,
+                    err,
+                );
             }
 
             self.suggest_convert_to_slice(
diff --git a/tests/ui/associated-consts/associated-const-array-len.stderr b/tests/ui/associated-consts/associated-const-array-len.stderr
index 0e0dec35b53ad..e3db45810fdd1 100644
--- a/tests/ui/associated-consts/associated-const-array-len.stderr
+++ b/tests/ui/associated-consts/associated-const-array-len.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
    |
 LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2];
    |                 ^^^ the trait `Foo` is not implemented for `i32`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/associated-const-array-len.rs:1:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr
index e9fe3a5e514b4..927422fa8dcaf 100644
--- a/tests/ui/associated-consts/issue-105330.stderr
+++ b/tests/ui/associated-consts/issue-105330.stderr
@@ -51,6 +51,11 @@ error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
 LL |     foo::<Demo>()();
    |           ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-105330.rs:1:1
+   |
+LL | pub trait TraitWAssocConst {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:11
    |
@@ -87,6 +92,11 @@ error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
 LL |     foo::<Demo>();
    |           ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-105330.rs:1:1
+   |
+LL | pub trait TraitWAssocConst {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:11
    |
diff --git a/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr
index 8c3463a2832e0..fbc4ccd4cf440 100644
--- a/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr
+++ b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `(): Add<A>` is not satisfied
    |
 LL |     r = r + a;
    |           ^ the trait `Add<A>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:15:1
+   |
+LL | trait Add<RHS=Self> {
+   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr
index bd3ee2abd2c76..b3f2e16ba0de8 100644
--- a/tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr
+++ b/tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `(T, U): Get` is not satisfied
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
    |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/associated-types-no-suitable-supertrait.rs:12:1
+   |
+LL | trait Get {
+   | ^^^^^^^^^
 
 error[E0277]: the trait bound `Self: Get` is not satisfied
   --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
diff --git a/tests/ui/associated-types/defaults-suitability.stderr b/tests/ui/associated-types/defaults-suitability.stderr
index 4b2094691f8cc..0a8ad0f89e212 100644
--- a/tests/ui/associated-types/defaults-suitability.stderr
+++ b/tests/ui/associated-types/defaults-suitability.stderr
@@ -58,6 +58,11 @@ error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
 LL |     type Assoc: Foo<Self> = ();
    |                             ^^ the trait `Foo<Self>` is not implemented for `()`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/defaults-suitability.rs:27:1
+   |
+LL | trait Foo<T> {
+   | ^^^^^^^^^^^^
 note: required by a bound in `Bar::Assoc`
   --> $DIR/defaults-suitability.rs:34:17
    |
diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr
index a84b599b52b68..266e22d4726d0 100644
--- a/tests/ui/associated-types/issue-59324.stderr
+++ b/tests/ui/associated-types/issue-59324.stderr
@@ -48,6 +48,12 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-59324.rs:3:1
+   |
+LL | pub trait Foo: NotFoo {
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
   --> $DIR/issue-59324.rs:19:10
diff --git a/tests/ui/associated-types/issue-64855.stderr b/tests/ui/associated-types/issue-64855.stderr
index 6ad795c11176d..f1016f0e3a191 100644
--- a/tests/ui/associated-types/issue-64855.stderr
+++ b/tests/ui/associated-types/issue-64855.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `Bar<T>: Foo` is not satisfied
    |
 LL | pub struct Bar<T>(<Self as Foo>::Type) where Self: ;
    |                   ^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar<T>`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-64855.rs:1:1
+   |
+LL | pub trait Foo {
+   | ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
index 3b4689e08ccfa..056d9201b4abb 100644
--- a/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
+++ b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `bool: Bar` is not satisfied
 LL |     type Assoc = bool;
    |                  ^^^^ the trait `Bar` is not implemented for `bool`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/point-at-type-on-obligation-failure-2.rs:1:1
+   |
+LL | trait Bar {}
+   | ^^^^^^^^^
 note: required by a bound in `Foo::Assoc`
   --> $DIR/point-at-type-on-obligation-failure-2.rs:4:17
    |
@@ -16,6 +21,11 @@ error[E0277]: the trait bound `bool: Bar` is not satisfied
 LL |     type Assoc = bool;
    |                  ^^^^ the trait `Bar` is not implemented for `bool`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/point-at-type-on-obligation-failure-2.rs:1:1
+   |
+LL | trait Bar {}
+   | ^^^^^^^^^
 note: required by a bound in `Baz::Assoc`
   --> $DIR/point-at-type-on-obligation-failure-2.rs:13:18
    |
@@ -31,6 +41,11 @@ error[E0277]: the trait bound `bool: Bar` is not satisfied
 LL |     type Assoc = bool;
    |                  ^^^^ the trait `Bar` is not implemented for `bool`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/point-at-type-on-obligation-failure-2.rs:1:1
+   |
+LL | trait Bar {}
+   | ^^^^^^^^^
 note: required by a bound in `Bat::Assoc`
   --> $DIR/point-at-type-on-obligation-failure-2.rs:24:27
    |
diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr
index 2e2dac288a1da..a3a37fd277578 100644
--- a/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr
+++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr
@@ -6,6 +6,11 @@ LL |     takes_t(t);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/coherence-unsafe-trait-object-impl.rs:6:1
+   |
+LL | trait Trait: Sized {
+   | ^^^^^^^^^^^^^^^^^^
 note: required by a bound in `takes_t`
   --> $DIR/coherence-unsafe-trait-object-impl.rs:10:15
    |
diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr
index cb51d9b1ea594..b3a2756602603 100644
--- a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr
+++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `[Adt; std::mem::size_of::<Self::Assoc>()]: Foo` i
    |
 LL |         <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar()
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::<Self::Assoc>()]`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-evaluate-array-len-on-err-1.rs:9:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr
index e50ac671eca54..9391b1c1a170a 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr
@@ -6,7 +6,11 @@ LL |     writes_to_specific_path(&cap);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Delegates<U>` is implemented for `T`
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-85848.rs:4:1
+   |
+LL | trait _Contains<T> {
+   | ^^^^^^^^^^^^^^^^^^
 note: required for `&C` to implement `Contains<(), true>`
   --> $DIR/issue-85848.rs:21:12
    |
diff --git a/tests/ui/const-generics/issues/issue-86530.stderr b/tests/ui/const-generics/issues/issue-86530.stderr
index 620ed4f0fb2cc..d02808f7c567b 100644
--- a/tests/ui/const-generics/issues/issue-86530.stderr
+++ b/tests/ui/const-generics/issues/issue-86530.stderr
@@ -6,6 +6,11 @@ LL |     z(" ");
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-86530.rs:4:1
+   |
+LL | pub trait X {
+   | ^^^^^^^^^^^
 note: required by a bound in `z`
   --> $DIR/issue-86530.rs:10:8
    |
diff --git a/tests/ui/cross/cross-fn-cache-hole.stderr b/tests/ui/cross/cross-fn-cache-hole.stderr
index 7e15562b0816b..79d1713934b3c 100644
--- a/tests/ui/cross/cross-fn-cache-hole.stderr
+++ b/tests/ui/cross/cross-fn-cache-hole.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `i32: Bar<u32>` is not satisfied
 LL |     where i32: Foo<u32, A>
    |           ^^^^^^^^^^^^^^^^ the trait `Bar<u32>` is not implemented for `i32`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/cross-fn-cache-hole.rs:11:1
+   |
+LL | trait Bar<X> { }
+   | ^^^^^^^^^^^^
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
diff --git a/tests/ui/dst/dst-bad-coerce1.stderr b/tests/ui/dst/dst-bad-coerce1.stderr
index 2c75518c298a9..455d15e935fae 100644
--- a/tests/ui/dst/dst-bad-coerce1.stderr
+++ b/tests/ui/dst/dst-bad-coerce1.stderr
@@ -15,6 +15,11 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied
 LL |     let f3: &Fat<dyn Bar> = f2;
    |                             ^^ the trait `Bar` is not implemented for `Foo`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dst-bad-coerce1.rs:10:1
+   |
+LL | trait Bar { fn bar(&self) {} }
+   | ^^^^^^^^^
    = note: required for the cast from `&Fat<Foo>` to `&Fat<dyn Bar>`
 
 error[E0308]: mismatched types
@@ -34,6 +39,11 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied
 LL |     let f3: &(dyn Bar,) = f2;
    |                           ^^ the trait `Bar` is not implemented for `Foo`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dst-bad-coerce1.rs:10:1
+   |
+LL | trait Bar { fn bar(&self) {} }
+   | ^^^^^^^^^
    = note: required for the cast from `&(Foo,)` to `&(dyn Bar,)`
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/dyn-star/error.stderr b/tests/ui/dyn-star/error.stderr
index ae54b9ca707d0..e039bb6f1c82b 100644
--- a/tests/ui/dyn-star/error.stderr
+++ b/tests/ui/dyn-star/error.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `{integer}: Foo` is not satisfied
    |
 LL |     let dyn_i: dyn* Foo = i;
    |                           ^ the trait `Foo` is not implemented for `{integer}`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/error.rs:6:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/error-codes/E0277.stderr b/tests/ui/error-codes/E0277.stderr
index 440e43dff8188..0b0d2b09720cd 100644
--- a/tests/ui/error-codes/E0277.stderr
+++ b/tests/ui/error-codes/E0277.stderr
@@ -21,6 +21,11 @@ LL |     some_func(5i32);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/E0277.rs:3:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 note: required by a bound in `some_func`
   --> $DIR/E0277.rs:7:17
    |
diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr
index 5c8db617c1731..91967fb850976 100644
--- a/tests/ui/generic-associated-types/issue-101020.stderr
+++ b/tests/ui/generic-associated-types/issue-101020.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satis
 LL |     (&mut EmptyIter).consume(());
    |                      ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-101020.rs:28:1
+   |
+LL | trait Foo<T> {}
+   | ^^^^^^^^^^^^
 note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>`
   --> $DIR/issue-101020.rs:27:20
    |
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
index edef6ccd34e61..7fe803550bddf 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
 LL |     C: StackContext,
    |        ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-89118.rs:1:1
+   |
+LL | trait BufferMut {}
+   | ^^^^^^^^^^^^^^^
 note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>`
   --> $DIR/issue-89118.rs:5:23
    |
@@ -26,6 +31,11 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
 LL | impl<C> EthernetWorker<C> {}
    |         ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-89118.rs:1:1
+   |
+LL | trait BufferMut {}
+   | ^^^^^^^^^^^^^^^
 note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>`
   --> $DIR/issue-89118.rs:5:23
    |
@@ -48,6 +58,11 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
 LL |     type Handler = Ctx<C::Dispatcher>;
    |                    ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-89118.rs:1:1
+   |
+LL | trait BufferMut {}
+   | ^^^^^^^^^^^^^^^
 note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>`
   --> $DIR/issue-89118.rs:5:23
    |
diff --git a/tests/ui/issues/issue-18611.stderr b/tests/ui/issues/issue-18611.stderr
index bd18d46223e69..784b9b984e900 100644
--- a/tests/ui/issues/issue-18611.stderr
+++ b/tests/ui/issues/issue-18611.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied
    |
 LL | fn add_state(op: <isize as HasState>::State) {
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-18611.rs:5:1
+   |
+LL | trait HasState {
+   | ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-25076.stderr b/tests/ui/issues/issue-25076.stderr
index 159cc484c5d4f..065bf7def42f8 100644
--- a/tests/ui/issues/issue-25076.stderr
+++ b/tests/ui/issues/issue-25076.stderr
@@ -6,6 +6,11 @@ LL |     do_fold(bot(), ());
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-25076.rs:3:1
+   |
+LL | trait InOut<T> { type Out; }
+   | ^^^^^^^^^^^^^^
 note: required by a bound in `do_fold`
   --> $DIR/issue-25076.rs:5:18
    |
diff --git a/tests/ui/issues/issue-35570.stderr b/tests/ui/issues/issue-35570.stderr
index 2697d46bdb2f4..197e80ac097c2 100644
--- a/tests/ui/issues/issue-35570.stderr
+++ b/tests/ui/issues/issue-35570.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
    |
 LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
    |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-35570.rs:4:1
+   |
+LL | trait Trait2<'a> {
+   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-60218.stderr b/tests/ui/issues/issue-60218.stderr
index 563690c9a5d6d..ae3c4d12025e3 100644
--- a/tests/ui/issues/issue-60218.stderr
+++ b/tests/ui/issues/issue-60218.stderr
@@ -6,6 +6,11 @@ LL |     trigger_error(vec![], |x: &u32| x)
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-60218.rs:7:1
+   |
+LL | pub trait Foo {}
+   | ^^^^^^^^^^^^^
 note: required by a bound in `trigger_error`
   --> $DIR/issue-60218.rs:13:72
    |
diff --git a/tests/ui/issues/issue-66353.stderr b/tests/ui/issues/issue-66353.stderr
index 71530f5822013..7ab7547b42dc6 100644
--- a/tests/ui/issues/issue-66353.stderr
+++ b/tests/ui/issues/issue-66353.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `(): _A` is not satisfied
    |
 LL |     _Func::< <() as _A>::AssocT >::func(());
    |               ^^ the trait `_A` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-66353.rs:7:1
+   |
+LL | trait _A {
+   | ^^^^^^^^
 
 error[E0277]: the trait bound `(): _Func<_>` is not satisfied
   --> $DIR/issue-66353.rs:12:41
@@ -11,6 +17,12 @@ LL |     _Func::< <() as _A>::AssocT >::func(());
    |     ----------------------------------- ^^ the trait `_Func<_>` is not implemented for `()`
    |     |
    |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-66353.rs:3:1
+   |
+LL | trait _Func<T> {
+   | ^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr
index ef1127c59ac4c..421ab3fcf4ebb 100644
--- a/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr
+++ b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied
    |
 LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/lifetime-elision-return-type-trait.rs:1:1
+   |
+LL | trait Future {
+   | ^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/namespace/namespace-mix.stderr b/tests/ui/namespace/namespace-mix.stderr
index 3ac5e96c5742b..4eff08ead42ce 100644
--- a/tests/ui/namespace/namespace-mix.stderr
+++ b/tests/ui/namespace/namespace-mix.stderr
@@ -114,6 +114,11 @@ LL |     check(m1::S{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -128,6 +133,11 @@ LL |     check(m2::S{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -142,6 +152,11 @@ LL |     check(m2::S);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -156,6 +171,11 @@ LL |     check(xm1::S{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -170,6 +190,11 @@ LL |     check(xm2::S{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -184,6 +209,11 @@ LL |     check(xm2::S);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -198,6 +228,11 @@ LL |     check(m3::TS{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -212,6 +247,11 @@ LL |     check(m3::TS);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -226,6 +266,11 @@ LL |     check(m4::TS{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -240,6 +285,11 @@ LL |     check(m4::TS);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -254,6 +304,11 @@ LL |     check(xm3::TS{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -268,6 +323,11 @@ LL |     check(xm3::TS);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -282,6 +342,11 @@ LL |     check(xm4::TS{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -296,6 +361,11 @@ LL |     check(xm4::TS);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -310,6 +380,11 @@ LL |     check(m5::US{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -324,6 +399,11 @@ LL |     check(m5::US);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -338,6 +418,11 @@ LL |     check(m6::US{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -352,6 +437,11 @@ LL |     check(m6::US);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -366,6 +456,11 @@ LL |     check(xm5::US{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -380,6 +475,11 @@ LL |     check(xm5::US);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -394,6 +494,11 @@ LL |     check(xm6::US{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -408,6 +513,11 @@ LL |     check(xm6::US);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -422,6 +532,11 @@ LL |     check(m7::V{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -436,6 +551,11 @@ LL |     check(m8::V{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -450,6 +570,11 @@ LL |     check(m8::V);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -464,6 +589,11 @@ LL |     check(xm7::V{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -478,6 +608,11 @@ LL |     check(xm8::V{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -492,6 +627,11 @@ LL |     check(xm8::V);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -506,6 +646,11 @@ LL |     check(m9::TV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -520,6 +665,11 @@ LL |     check(m9::TV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -534,6 +684,11 @@ LL |     check(mA::TV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -548,6 +703,11 @@ LL |     check(mA::TV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -562,6 +722,11 @@ LL |     check(xm9::TV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -576,6 +741,11 @@ LL |     check(xm9::TV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -590,6 +760,11 @@ LL |     check(xmA::TV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -604,6 +779,11 @@ LL |     check(xmA::TV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -618,6 +798,11 @@ LL |     check(mB::UV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -632,6 +817,11 @@ LL |     check(mB::UV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -646,6 +836,11 @@ LL |     check(mC::UV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -660,6 +855,11 @@ LL |     check(mC::UV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -674,6 +874,11 @@ LL |     check(xmB::UV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -688,6 +893,11 @@ LL |     check(xmB::UV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -702,6 +912,11 @@ LL |     check(xmC::UV{});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
@@ -716,6 +931,11 @@ LL |     check(xmC::UV);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/namespace-mix.rs:20:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
    |
diff --git a/tests/ui/never_type/feature-gate-never_type_fallback.stderr b/tests/ui/never_type/feature-gate-never_type_fallback.stderr
index 2db1cc4b77690..56aafbb4ce89e 100644
--- a/tests/ui/never_type/feature-gate-never_type_fallback.stderr
+++ b/tests/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -8,6 +8,11 @@ LL |     foo(panic!())
    |     |   this tail expression is of type `()`
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/feature-gate-never_type_fallback.rs:7:1
+   |
+LL | trait T {}
+   | ^^^^^^^
 note: required by a bound in `foo`
   --> $DIR/feature-gate-never_type_fallback.rs:13:16
    |
diff --git a/tests/ui/never_type/impl_trait_fallback3.stderr b/tests/ui/never_type/impl_trait_fallback3.stderr
index 5d5d216fb9bcc..821d141569ed9 100644
--- a/tests/ui/never_type/impl_trait_fallback3.stderr
+++ b/tests/ui/never_type/impl_trait_fallback3.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `(): T` is not satisfied
    |
 LL | fn a() -> Foo {
    |           ^^^ the trait `T` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/impl_trait_fallback3.rs:5:1
+   |
+LL | trait T {
+   | ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/never_type/impl_trait_fallback4.stderr b/tests/ui/never_type/impl_trait_fallback4.stderr
index f2e216e9044c0..67421ba8da757 100644
--- a/tests/ui/never_type/impl_trait_fallback4.stderr
+++ b/tests/ui/never_type/impl_trait_fallback4.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `(): T` is not satisfied
    |
 LL | fn foo() -> impl T {
    |             ^^^^^^ the trait `T` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/impl_trait_fallback4.rs:3:1
+   |
+LL | trait T {
+   | ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/on-unimplemented/on-trait.stderr b/tests/ui/on-unimplemented/on-trait.stderr
index 4b040f1ac5aa9..4847a1a5a6119 100644
--- a/tests/ui/on-unimplemented/on-trait.stderr
+++ b/tests/ui/on-unimplemented/on-trait.stderr
@@ -5,6 +5,11 @@ LL |     let y: Option<Vec<u8>> = collect(x.iter()); // this should give approxi
    |                              ^^^^^^^ a collection of type `Option<Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
    |
    = help: the trait `MyFromIterator<&u8>` is not implemented for `Option<Vec<u8>>`
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-trait.rs:17:1
+   |
+LL | trait MyFromIterator<A> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `collect`
   --> $DIR/on-trait.rs:22:39
    |
@@ -18,6 +23,11 @@ LL |     let x: String = foobar();
    |                     ^^^^^^ test error `String` with `u8` `_` `u32` in `Foo`
    |
    = help: the trait `Foo<u8, _, u32>` is not implemented for `String`
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-trait.rs:7:3
+   |
+LL |   pub trait Foo<Bar, Baz, Quux> {}
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `foobar`
   --> $DIR/on-trait.rs:12:24
    |
diff --git a/tests/ui/on-unimplemented/parent-label.stderr b/tests/ui/on-unimplemented/parent-label.stderr
index 8cd7412fd9d3d..101a41512d280 100644
--- a/tests/ui/on-unimplemented/parent-label.stderr
+++ b/tests/ui/on-unimplemented/parent-label.stderr
@@ -8,6 +8,11 @@ LL |         f(Foo {});
    |         |
    |         required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/parent-label.rs:6:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `f`
   --> $DIR/parent-label.rs:10:9
    |
@@ -24,6 +29,11 @@ LL |             f(Foo {});
    |             |
    |             required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/parent-label.rs:6:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `f`
   --> $DIR/parent-label.rs:10:9
    |
@@ -41,6 +51,11 @@ LL |             f(Foo {});
    |             |
    |             required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/parent-label.rs:6:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `f`
   --> $DIR/parent-label.rs:10:9
    |
@@ -58,6 +73,11 @@ LL |     f(Foo {});
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/parent-label.rs:6:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `f`
   --> $DIR/parent-label.rs:10:9
    |
diff --git a/tests/ui/proc-macro/bad-projection.stderr b/tests/ui/proc-macro/bad-projection.stderr
index 8a8246376fe08..8716defa17ae9 100644
--- a/tests/ui/proc-macro/bad-projection.stderr
+++ b/tests/ui/proc-macro/bad-projection.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `(): Project` is not satisfied
    |
 LL | pub fn uwu() -> <() as Project>::Assoc {}
    |                 ^^^^^^^^^^^^^^^^^^^^^^ the trait `Project` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/bad-projection.rs:9:1
+   |
+LL | trait Project {
+   | ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/span/issue-29595.stderr b/tests/ui/span/issue-29595.stderr
index 92445e4073130..7d603cdbfe5ca 100644
--- a/tests/ui/span/issue-29595.stderr
+++ b/tests/ui/span/issue-29595.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied
    |
 LL |     let a: u8 = Tr::C;
    |                 ^^^^^ the trait `Tr` is not implemented for `u8`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-29595.rs:1:1
+   |
+LL | trait Tr {
+   | ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/specialization/issue-38091.stderr b/tests/ui/specialization/issue-38091.stderr
index f2210a40719d3..4d840482b46b5 100644
--- a/tests/ui/specialization/issue-38091.stderr
+++ b/tests/ui/specialization/issue-38091.stderr
@@ -14,6 +14,11 @@ error[E0277]: the trait bound `(): Valid` is not satisfied
 LL |     default type Ty = ();
    |                       ^^ the trait `Valid` is not implemented for `()`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-38091.rs:20:1
+   |
+LL | trait Valid {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Iterate::Ty`
   --> $DIR/issue-38091.rs:5:14
    |
diff --git a/tests/ui/suggestions/issue-89333.stderr b/tests/ui/suggestions/issue-89333.stderr
index f73f1147d5d9c..4739f11ddadbf 100644
--- a/tests/ui/suggestions/issue-89333.stderr
+++ b/tests/ui/suggestions/issue-89333.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `for<'a> &'a _: Trait` is not satisfied
 LL |     test(&|| 0);
    |     ^^^^ the trait `for<'a> Trait` is not implemented for `&'a _`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-89333.rs:9:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `test`
   --> $DIR/issue-89333.rs:11:55
    |
diff --git a/tests/ui/trait-bounds/issue-82038.stderr b/tests/ui/trait-bounds/issue-82038.stderr
index f37e3286f4bf8..30bb4a0a8509d 100644
--- a/tests/ui/trait-bounds/issue-82038.stderr
+++ b/tests/ui/trait-bounds/issue-82038.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `bool: Foo` is not satisfied
    |
 LL |     <bool as Foo>::my_method();
    |      ^^^^ the trait `Foo` is not implemented for `bool`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-82038.rs:3:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr
index 61237a63e3220..530264b344ab5 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied
 LL | fn explode(x: Foo<u32>) {}
    |               ^^^^^^^^ the trait `Trait` is not implemented for `u32`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums-in-fns.rs:1:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums-in-fns.rs:3:14
    |
@@ -16,6 +21,11 @@ error[E0277]: the trait bound `f32: Trait` is not satisfied
 LL | fn kaboom(y: Bar<f32>) {}
    |              ^^^^^^^^ the trait `Trait` is not implemented for `f32`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums-in-fns.rs:1:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Bar`
   --> $DIR/on-structs-and-enums-in-fns.rs:7:12
    |
diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr
index 8a43742260bb2..372bbabbd8621 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `u16: Trait` is not satisfied
 LL | impl PolyTrait<Foo<u16>> for Struct {
    |      ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums-in-impls.rs:1:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums-in-impls.rs:3:14
    |
diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.stderr b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr
index 20bbe69c059f8..01cf76c62d540 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-locals.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `usize: Trait` is not satisfied
 LL |     let baz: Foo<usize> = loop { };
    |              ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums-locals.rs:1:1
+   |
+LL | trait Trait {
+   | ^^^^^^^^^^^
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums-locals.rs:5:14
    |
@@ -16,6 +21,11 @@ error[E0277]: the trait bound `{integer}: Trait` is not satisfied
 LL |         x: 3
    |            ^ the trait `Trait` is not implemented for `{integer}`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums-locals.rs:1:1
+   |
+LL | trait Trait {
+   | ^^^^^^^^^^^
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums-locals.rs:5:14
    |
diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.stderr b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
index fda734e857113..fa14aff684d53 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-static.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `usize: Trait` is not satisfied
 LL | static X: Foo<usize> = Foo {
    |           ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums-static.rs:1:1
+   |
+LL | trait Trait {
+   | ^^^^^^^^^^^
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums-static.rs:5:14
    |
diff --git a/tests/ui/traits/bound/on-structs-and-enums.stderr b/tests/ui/traits/bound/on-structs-and-enums.stderr
index fe05b86344be3..606f764852fed 100644
--- a/tests/ui/traits/bound/on-structs-and-enums.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums.stderr
@@ -20,6 +20,11 @@ error[E0277]: the trait bound `isize: Trait` is not satisfied
 LL |     a: Foo<isize>,
    |        ^^^^^^^^^^ the trait `Trait` is not implemented for `isize`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums.rs:1:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums.rs:3:14
    |
@@ -32,6 +37,11 @@ error[E0277]: the trait bound `usize: Trait` is not satisfied
 LL |     Quux(Bar<usize>),
    |          ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums.rs:1:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Bar`
   --> $DIR/on-structs-and-enums.rs:7:12
    |
@@ -76,6 +86,11 @@ error[E0277]: the trait bound `i32: Trait` is not satisfied
 LL |     Foo<i32>,
    |     ^^^^^^^^ the trait `Trait` is not implemented for `i32`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums.rs:1:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums.rs:3:14
    |
@@ -88,6 +103,11 @@ error[E0277]: the trait bound `u8: Trait` is not satisfied
 LL |     DictionaryLike { field: Bar<u8> },
    |                             ^^^^^^^ the trait `Trait` is not implemented for `u8`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums.rs:1:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `Bar`
   --> $DIR/on-structs-and-enums.rs:7:12
    |
diff --git a/tests/ui/traits/deny-builtin-object-impl.current.stderr b/tests/ui/traits/deny-builtin-object-impl.current.stderr
index 5c1987426f71f..8ca3d3a057fa3 100644
--- a/tests/ui/traits/deny-builtin-object-impl.current.stderr
+++ b/tests/ui/traits/deny-builtin-object-impl.current.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
 LL |     test_not_object::<dyn NotObject>();
    |                       ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/deny-builtin-object-impl.rs:10:1
+   |
+LL | trait NotObject {}
+   | ^^^^^^^^^^^^^^^
 note: required by a bound in `test_not_object`
   --> $DIR/deny-builtin-object-impl.rs:14:23
    |
diff --git a/tests/ui/traits/deny-builtin-object-impl.next.stderr b/tests/ui/traits/deny-builtin-object-impl.next.stderr
index 5c1987426f71f..8ca3d3a057fa3 100644
--- a/tests/ui/traits/deny-builtin-object-impl.next.stderr
+++ b/tests/ui/traits/deny-builtin-object-impl.next.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
 LL |     test_not_object::<dyn NotObject>();
    |                       ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/deny-builtin-object-impl.rs:10:1
+   |
+LL | trait NotObject {}
+   | ^^^^^^^^^^^^^^^
 note: required by a bound in `test_not_object`
   --> $DIR/deny-builtin-object-impl.rs:14:23
    |
diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
index 263c59ee32712..a5d0e6ab09569 100644
--- a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
+++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
@@ -10,6 +10,11 @@ error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>`
 LL |     <i32 as RefFoo<i32>>::ref_foo(unknown);
    |      ^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-autoderef-ty-with-escaping-var.rs:3:1
+   |
+LL | trait Foo<'x, T> {}
+   | ^^^^^^^^^^^^^^^^
 note: required for `i32` to implement `RefFoo<i32>`
   --> $DIR/dont-autoderef-ty-with-escaping-var.rs:9:9
    |
diff --git a/tests/ui/traits/impl-bounds-checking.stderr b/tests/ui/traits/impl-bounds-checking.stderr
index 1f969efe1141d..bfa8213abe76f 100644
--- a/tests/ui/traits/impl-bounds-checking.stderr
+++ b/tests/ui/traits/impl-bounds-checking.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `isize: Clone2` is not satisfied
 LL | impl Getter<isize> for isize {
    |                        ^^^^^ the trait `Clone2` is not implemented for `isize`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/impl-bounds-checking.rs:1:1
+   |
+LL | pub trait Clone2 {
+   | ^^^^^^^^^^^^^^^^
 note: required by a bound in `Getter`
   --> $DIR/impl-bounds-checking.rs:6:17
    |
diff --git a/tests/ui/traits/new-solver/projection-discr-kind.stderr b/tests/ui/traits/new-solver/projection-discr-kind.stderr
index 03e28f993e25d..e14953f19ff37 100644
--- a/tests/ui/traits/new-solver/projection-discr-kind.stderr
+++ b/tests/ui/traits/new-solver/projection-discr-kind.stderr
@@ -6,6 +6,11 @@ LL |     needs_bar(std::mem::discriminant(&x));
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/projection-discr-kind.rs:10:1
+   |
+LL | trait Bar {}
+   | ^^^^^^^^^
 note: required by a bound in `needs_bar`
   --> $DIR/projection-discr-kind.rs:11:22
    |
diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr
index 7bd02550fb384..240bcef7df504 100644
--- a/tests/ui/traits/non_lifetime_binders/fail.stderr
+++ b/tests/ui/traits/non_lifetime_binders/fail.stderr
@@ -13,6 +13,11 @@ error[E0277]: the trait bound `T: Trait` is not satisfied
 LL |     fail();
    |     ^^^^ the trait `Trait` is not implemented for `T`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/fail.rs:6:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
 note: required by a bound in `fail`
   --> $DIR/fail.rs:10:15
    |
diff --git a/tests/ui/traits/object-does-not-impl-trait.stderr b/tests/ui/traits/object-does-not-impl-trait.stderr
index f1dd508a46741..81d67255a0bdb 100644
--- a/tests/ui/traits/object-does-not-impl-trait.stderr
+++ b/tests/ui/traits/object-does-not-impl-trait.stderr
@@ -6,6 +6,11 @@ LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
    |                                   |
    |                                   required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/object-does-not-impl-trait.rs:4:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
 note: required by a bound in `take_foo`
   --> $DIR/object-does-not-impl-trait.rs:5:15
    |
diff --git a/tests/ui/traits/vtable-res-trait-param.stderr b/tests/ui/traits/vtable-res-trait-param.stderr
index 2b3e3de9b1ab4..4cfceefb24cd0 100644
--- a/tests/ui/traits/vtable-res-trait-param.stderr
+++ b/tests/ui/traits/vtable-res-trait-param.stderr
@@ -6,6 +6,11 @@ LL |     b.gimme_an_a(y)
    |       |
    |       required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/vtable-res-trait-param.rs:1:1
+   |
+LL | trait TraitA {
+   | ^^^^^^^^^^^^
 note: required by a bound in `TraitB::gimme_an_a`
   --> $DIR/vtable-res-trait-param.rs:6:21
    |
diff --git a/tests/ui/trivial-bounds/trivial-bounds-leak.stderr b/tests/ui/trivial-bounds/trivial-bounds-leak.stderr
index 02c5d5d248403..be472a5076913 100644
--- a/tests/ui/trivial-bounds/trivial-bounds-leak.stderr
+++ b/tests/ui/trivial-bounds/trivial-bounds-leak.stderr
@@ -27,6 +27,12 @@ LL |     Foo::test(&4i32);
    |     --------- ^^^^^ the trait `Foo` is not implemented for `i32`
    |     |
    |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/trivial-bounds-leak.rs:4:1
+   |
+LL | pub trait Foo {
+   | ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:26:22
@@ -36,6 +42,11 @@ LL |     generic_function(5i32);
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/trivial-bounds-leak.rs:4:1
+   |
+LL | pub trait Foo {
+   | ^^^^^^^^^^^^^
 note: required by a bound in `generic_function`
   --> $DIR/trivial-bounds-leak.rs:29:24
    |
diff --git a/tests/ui/union/projection-as-union-type-error-2.stderr b/tests/ui/union/projection-as-union-type-error-2.stderr
index bab226f271df7..21f4ea103ada3 100644
--- a/tests/ui/union/projection-as-union-type-error-2.stderr
+++ b/tests/ui/union/projection-as-union-type-error-2.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `u8: NotImplemented` is not satisfied
 LL |     a: <Foo as Identity>::Identity,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/projection-as-union-type-error-2.rs:9:1
+   |
+LL | trait NotImplemented {}
+   | ^^^^^^^^^^^^^^^^^^^^
 note: required for `u8` to implement `Identity`
   --> $DIR/projection-as-union-type-error-2.rs:11:25
    |
diff --git a/tests/ui/union/projection-as-union-type-error.stderr b/tests/ui/union/projection-as-union-type-error.stderr
index e4fbe9603ad45..2b0241caf98ca 100644
--- a/tests/ui/union/projection-as-union-type-error.stderr
+++ b/tests/ui/union/projection-as-union-type-error.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `u8: Identity` is not satisfied
    |
 LL |     a:  <Foo as Identity>::Identity,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Identity` is not implemented for `u8`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/projection-as-union-type-error.rs:6:1
+   |
+LL | pub trait Identity {
+   | ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/unsized/issue-75707.stderr b/tests/ui/unsized/issue-75707.stderr
index 97618ed05ed38..aa7f9c78fa84e 100644
--- a/tests/ui/unsized/issue-75707.stderr
+++ b/tests/ui/unsized/issue-75707.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `MyCall: Callback` is not satisfied
 LL |     f::<dyn Processing<Call = MyCall>>();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callback` is not implemented for `MyCall`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-75707.rs:1:1
+   |
+LL | pub trait Callback {
+   | ^^^^^^^^^^^^^^^^^^
 note: required by a bound in `f`
   --> $DIR/issue-75707.rs:9:9
    |
diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr
index 9fd0f9c81ebd8..21122e37da53d 100644
--- a/tests/ui/wf/hir-wf-canonicalized.stderr
+++ b/tests/ui/wf/hir-wf-canonicalized.stderr
@@ -3,12 +3,24 @@ error[E0277]: the trait bound `Bar<'a, T>: Foo` is not satisfied
    |
 LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar<'a, T>`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/hir-wf-canonicalized.rs:3:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 
 error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
   --> $DIR/hir-wf-canonicalized.rs:10:15
    |
 LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/hir-wf-canonicalized.rs:3:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 
 error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
   --> $DIR/hir-wf-canonicalized.rs:10:15
diff --git a/tests/ui/wf/issue-95665.stderr b/tests/ui/wf/issue-95665.stderr
index b1cda59a9165b..f80cd41a4c2d3 100644
--- a/tests/ui/wf/issue-95665.stderr
+++ b/tests/ui/wf/issue-95665.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `u8: Trait` is not satisfied
 LL |     static VAR: Struct<u8>;
    |                 ^^^^^^^^^^ the trait `Trait` is not implemented for `u8`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-95665.rs:4:1
+   |
+LL | pub trait Trait: {}
+   | ^^^^^^^^^^^^^^^
 note: required by a bound in `Struct`
   --> $DIR/issue-95665.rs:6:22
    |
diff --git a/tests/ui/wf/wf-complex-assoc-type.stderr b/tests/ui/wf/wf-complex-assoc-type.stderr
index ef613e3132d03..6a623bec815e4 100644
--- a/tests/ui/wf/wf-complex-assoc-type.stderr
+++ b/tests/ui/wf/wf-complex-assoc-type.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `bool: MyTrait` is not satisfied
 LL |     type MyItem = Option<((AssertMyTrait<bool>, u8))>;
    |                            ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `bool`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/wf-complex-assoc-type.rs:1:1
+   |
+LL | trait MyTrait {}
+   | ^^^^^^^^^^^^^
 note: required by a bound in `AssertMyTrait`
   --> $DIR/wf-complex-assoc-type.rs:2:25
    |
diff --git a/tests/ui/wf/wf-foreign-fn-decl-ret.stderr b/tests/ui/wf/wf-foreign-fn-decl-ret.stderr
index b03023b5fd14f..0e93601043a69 100644
--- a/tests/ui/wf/wf-foreign-fn-decl-ret.stderr
+++ b/tests/ui/wf/wf-foreign-fn-decl-ret.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
    |
 LL |     pub fn lint_me() -> <() as Foo>::Assoc;
    |                         ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/wf-foreign-fn-decl-ret.rs:6:1
+   |
+LL | pub trait Foo {
+   | ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
   --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
@@ -10,6 +16,11 @@ error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
 LL |     pub fn lint_me_aswell() -> Bar<u32>;
    |                                ^^^^^^^^ the trait `Unsatisfied` is not implemented for `u32`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/wf-foreign-fn-decl-ret.rs:1:1
+   |
+LL | pub trait Unsatisfied {}
+   | ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `Bar`
   --> $DIR/wf-foreign-fn-decl-ret.rs:4:19
    |
diff --git a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr
index e460cdcd3f3e5..52f46562c3716 100644
--- a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr
+++ b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr
@@ -3,6 +3,12 @@ error[E0277]: the trait bound `DefaultAllocator: Allocator` is not satisfied
    |
 LL | struct Foo(Matrix<<DefaultAllocator as Allocator>::Buffer>);
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Allocator` is not implemented for `DefaultAllocator`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/wf-packed-on-proj-of-type-as-unimpl-trait.rs:23:1
+   |
+LL | pub trait Allocator { type Buffer; }
+   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
index 191a8ca8ebcf3..29b36f44a4d12 100644
--- a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
+++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied
 LL |     called()
    |     ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/higher-ranked-fn-type.rs:6:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 note: required by a bound in `called`
   --> $DIR/higher-ranked-fn-type.rs:12:25
    |
diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
index ce409f627be20..54afeaa7edabc 100644
--- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
+++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `for<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_t
 LL |     called()
    |     ^^^^^^ the trait `for<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b))> Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/higher-ranked-fn-type.rs:6:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
 note: required by a bound in `called`
   --> $DIR/higher-ranked-fn-type.rs:12:25
    |
diff --git a/tests/ui/where-clauses/where-clause-method-substituion.stderr b/tests/ui/where-clauses/where-clause-method-substituion.stderr
index 8c47ed6d4317a..2f3b615a13bdf 100644
--- a/tests/ui/where-clauses/where-clause-method-substituion.stderr
+++ b/tests/ui/where-clauses/where-clause-method-substituion.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `X: Foo<X>` is not satisfied
 LL |     1.method::<X>();
    |                ^ the trait `Foo<X>` is not implemented for `X`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/where-clause-method-substituion.rs:1:1
+   |
+LL | trait Foo<T> {
+   | ^^^^^^^^^^^^
 note: required by a bound in `Bar::method`
   --> $DIR/where-clause-method-substituion.rs:6:34
    |