about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2023-10-30 17:33:15 +0100
committerGitHub <noreply@github.com>2023-10-30 17:33:15 +0100
commit95de91b5ceae99d451cbb9fd85ec4dc9c8f7397c (patch)
treebc2257c9a24b698f4bb374bde92ea1800f17ff54
parent824e3677c26d7fd7687d6a7a3349f3f11c534490 (diff)
parent8c04999226e4be90c46c370580c9e8cd7f0ccb05 (diff)
downloadrust-95de91b5ceae99d451cbb9fd85ec4dc9c8f7397c.tar.gz
rust-95de91b5ceae99d451cbb9fd85ec4dc9c8f7397c.zip
Rollup merge of #117132 - estebank:issue-80194, r=petrochenkov
On object safety error, mention new enum as alternative

When we encounter a `dyn Trait` that isn't object safe, look for its implementors. If there's one, mention using it directly If there are less than 9, mention the possibility of creating a new enum and using that instead.

Fix #80194.
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs64
-rw-r--r--tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr1
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr2
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.base.stderr3
-rw-r--r--tests/ui/generic-associated-types/issue-76535.base.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-79422.base.stderr6
-rw-r--r--tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr1
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety.stderr4
-rw-r--r--tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr6
-rw-r--r--tests/ui/issues/issue-19380.stderr2
-rw-r--r--tests/ui/object-safety/issue-19538.stderr2
-rw-r--r--tests/ui/object-safety/object-safety-issue-22040.stderr1
-rw-r--r--tests/ui/object-safety/object-safety-no-static.curr.stderr1
-rw-r--r--tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr1
-rw-r--r--tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr2
-rw-r--r--tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr1
-rw-r--r--tests/ui/traits/issue-38604.stderr2
-rw-r--r--tests/ui/traits/item-privacy.stderr1
-rw-r--r--tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr3
-rw-r--r--tests/ui/traits/object/safety.stderr2
-rw-r--r--tests/ui/traits/test-2.stderr9
-rw-r--r--tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr1
-rw-r--r--tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr3
-rw-r--r--tests/ui/wf/wf-convert-unsafe-trait-obj.stderr3
-rw-r--r--tests/ui/wf/wf-unsafe-trait-obj-match.stderr6
25 files changed, 130 insertions, 1 deletions
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 7a335827f37..32966011932 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -5,7 +5,8 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
 use std::fmt;
 use std::iter;
@@ -108,5 +109,66 @@ pub fn report_object_safety_error<'tcx>(
             violation.solution(&mut err);
         }
     }
+
+    let impls_of = tcx.trait_impls_of(trait_def_id);
+    let impls = if impls_of.blanket_impls().is_empty() {
+        impls_of
+            .non_blanket_impls()
+            .values()
+            .flatten()
+            .filter(|def_id| {
+                !matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..))
+            })
+            .collect::<Vec<_>>()
+    } else {
+        vec![]
+    };
+    let externally_visible = if !impls.is_empty()
+        && let Some(def_id) = trait_def_id.as_local()
+        && tcx.effective_visibilities(()).is_exported(def_id)
+    {
+        true
+    } else {
+        false
+    };
+    match &impls[..] {
+        [] => {}
+        _ if impls.len() > 9 => {}
+        [only] if externally_visible => {
+            err.help(with_no_trimmed_paths!(format!(
+                "only type `{}` is seen to implement the trait in this crate, consider using it \
+                 directly instead",
+                tcx.type_of(*only).instantiate_identity(),
+            )));
+        }
+        [only] => {
+            err.help(with_no_trimmed_paths!(format!(
+                "only type `{}` implements the trait, consider using it directly instead",
+                tcx.type_of(*only).instantiate_identity(),
+            )));
+        }
+        impls => {
+            let types = impls
+                .iter()
+                .map(|t| {
+                    with_no_trimmed_paths!(format!("  {}", tcx.type_of(*t).instantiate_identity(),))
+                })
+                .collect::<Vec<_>>();
+            err.help(format!(
+                "the following types implement the trait, consider defining an enum where each \
+                 variant holds one of these types, implementing `{}` for this new enum and using \
+                 it instead:\n{}",
+                trait_str,
+                types.join("\n"),
+            ));
+        }
+    }
+    if externally_visible {
+        err.note(format!(
+            "`{trait_str}` can be implemented in other crates; if you want to support your users \
+             passing their own types here, you can't refer to a specific type",
+        ));
+    }
+
     err
 }
diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
index 7ce2b9ac95a..b7ec657120c 100644
--- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
@@ -15,6 +15,7 @@ LL |     fn test(&self) -> [u8; bar::<Self>()];
    |        ...because method `test` references the `Self` type in its `where` clause
    = help: consider moving `test` to another trait
    = help: consider moving `test` to another trait
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error: aborting due to previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
index 303700c7ab4..00b8c0eef98 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
@@ -14,6 +14,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     fn ptr(self: Ptr<Self>);
    |                  ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
+   = help: only type `i32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:5
@@ -31,6 +32,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     fn ptr(self: Ptr<Self>);
    |                  ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
+   = help: only type `i32` implements the trait, consider using it directly instead
    = note: required for the cast from `Ptr<{integer}>` to `Ptr<dyn Trait>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
index fd54faaf37c..9013d429530 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
@@ -12,6 +12,9 @@ LL | trait Foo {
 LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
    = help: consider moving `A` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
+             Fooy
+             Fooer<T>
 
 error: aborting due to previous error
 
diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr
index 370329b9f83..bb14e297174 100644
--- a/tests/ui/generic-associated-types/issue-76535.base.stderr
+++ b/tests/ui/generic-associated-types/issue-76535.base.stderr
@@ -28,6 +28,8 @@ LL | pub trait SuperTrait {
 LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
+   = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
+   = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
 
 error[E0038]: the trait `SuperTrait` cannot be made into an object
   --> $DIR/issue-76535.rs:39:57
@@ -43,6 +45,8 @@ LL | pub trait SuperTrait {
 LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
+   = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
+   = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
    = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr
index ad704f5e9f0..bcc6382cf7c 100644
--- a/tests/ui/generic-associated-types/issue-79422.base.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.base.stderr
@@ -28,6 +28,9 @@ LL | trait MapLike<K, V> {
 LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
+             std::collections::BTreeMap<K, V>
+             Source
 
 error[E0038]: the trait `MapLike` cannot be made into an object
   --> $DIR/issue-79422.rs:44:13
@@ -43,6 +46,9 @@ LL | trait MapLike<K, V> {
 LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
+             std::collections::BTreeMap<K, V>
+             Source
    = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
index bfb2be8cbc1..f29ec95d594 100644
--- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
+++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
@@ -9,6 +9,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
    |
 LL |     fn bar(self) -> impl Deref<Target = impl Sized>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type
+   = help: only type `rpitit::Foreign` implements the trait, consider using it directly instead
 
 error: aborting due to previous error
 
diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr
index 3271cb18d9f..a7be0516cd3 100644
--- a/tests/ui/impl-trait/in-trait/object-safety.stderr
+++ b/tests/ui/impl-trait/in-trait/object-safety.stderr
@@ -12,6 +12,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/object-safety.rs:17:15
@@ -27,6 +28,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/object-safety.rs:17:13
@@ -42,6 +44,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/object-safety.rs:14:13
@@ -57,6 +60,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
+   = help: only type `u32` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
index 687dbe65e6c..37c96d9bc4e 100644
--- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
+++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
@@ -11,6 +11,9 @@ LL | trait NotObjectSafe {
    |       ------------- this trait cannot be made into an object...
 LL |     fn foo() -> Self;
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead:
+             A
+             B
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) -> Self;
@@ -33,6 +36,9 @@ LL | trait NotObjectSafe {
    |       ------------- this trait cannot be made into an object...
 LL |     fn foo() -> Self;
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead:
+             A
+             B
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) -> Self;
diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr
index 37e280fbcc7..f6244d9d44f 100644
--- a/tests/ui/issues/issue-19380.stderr
+++ b/tests/ui/issues/issue-19380.stderr
@@ -11,6 +11,7 @@ LL | trait Qiz {
    |       --- this trait cannot be made into an object...
 LL |   fn qiz();
    |      ^^^ ...because associated function `qiz` has no `self` parameter
+   = help: only type `Foo` implements the trait, consider using it directly instead
 help: consider turning `qiz` into a method by giving it a `&self` argument
    |
 LL |   fn qiz(&self);
@@ -33,6 +34,7 @@ LL | trait Qiz {
    |       --- this trait cannot be made into an object...
 LL |   fn qiz();
    |      ^^^ ...because associated function `qiz` has no `self` parameter
+   = help: only type `Foo` implements the trait, consider using it directly instead
    = note: required for the cast from `&Foo` to `&'static (dyn Qiz + 'static)`
 help: consider turning `qiz` into a method by giving it a `&self` argument
    |
diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/object-safety/issue-19538.stderr
index 183245b2322..31657501e25 100644
--- a/tests/ui/object-safety/issue-19538.stderr
+++ b/tests/ui/object-safety/issue-19538.stderr
@@ -13,6 +13,7 @@ LL |     fn foo<T>(&self, val: T);
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
    = help: consider moving `foo` to another trait
+   = help: only type `Thing` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-19538.rs:17:30
@@ -29,6 +30,7 @@ LL |     fn foo<T>(&self, val: T);
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
    = help: consider moving `foo` to another trait
+   = help: only type `Thing` implements the trait, consider using it directly instead
    = note: required for the cast from `&mut Thing` to `&mut dyn Bar`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/object-safety/object-safety-issue-22040.stderr b/tests/ui/object-safety/object-safety-issue-22040.stderr
index 0262d536246..2e59d88bdaf 100644
--- a/tests/ui/object-safety/object-safety-issue-22040.stderr
+++ b/tests/ui/object-safety/object-safety-issue-22040.stderr
@@ -11,6 +11,7 @@ LL | trait Expr: Debug + PartialEq {
    |       ----          ^^^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `SExpr<'x>` implements the trait, consider using it directly instead
 
 error: aborting due to previous error
 
diff --git a/tests/ui/object-safety/object-safety-no-static.curr.stderr b/tests/ui/object-safety/object-safety-no-static.curr.stderr
index 1b025229e54..b40470b457b 100644
--- a/tests/ui/object-safety/object-safety-no-static.curr.stderr
+++ b/tests/ui/object-safety/object-safety-no-static.curr.stderr
@@ -11,6 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo() {}
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) {}
diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
index befcef952a8..1eae9a9b9da 100644
--- a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
@@ -11,6 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo() {}
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `Bar` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
index 13591f5b635..fdd18c6b37b 100644
--- a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
+++ b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
@@ -14,6 +14,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
+   = help: only type `usize` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
@@ -31,6 +32,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
+   = help: only type `usize` implements the trait, consider using it directly instead
    = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
index 593f705353a..0a567ddcc2e 100644
--- a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
+++ b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
@@ -14,6 +14,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
+   = help: only type `usize` implements the trait, consider using it directly instead
    = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>`
 
 error: aborting due to previous error
diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr
index d5327602430..3ab9af21bc4 100644
--- a/tests/ui/traits/issue-38604.stderr
+++ b/tests/ui/traits/issue-38604.stderr
@@ -11,6 +11,7 @@ LL | trait Foo where u32: Q<Self> {
    |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/issue-38604.rs:15:9
@@ -25,6 +26,7 @@ LL | trait Foo where u32: Q<Self> {
    |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<()>` to `Box<dyn Foo>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index af2e0763212..d74be772660 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -143,6 +143,7 @@ LL |         const C: u8 = 0;
    = help: consider moving `C` to another trait
    = help: consider moving `A` to another trait
    = help: consider moving `B` to another trait
+   = help: only type `S` implements the trait, consider using it directly instead
 
 error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:115:12
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
index d56519223f4..b6e540c5ffc 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
@@ -20,6 +20,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
    = note: required for the cast from `&()` to `&dyn Foo`
 
 error[E0038]: the trait `Foo` cannot be made into an object
@@ -35,6 +36,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/supertrait-object-safety.rs:22:5
@@ -49,6 +51,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `()` implements the trait, consider using it directly instead
 
 error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr
index a51b6975938..19a46a502c2 100644
--- a/tests/ui/traits/object/safety.stderr
+++ b/tests/ui/traits/object/safety.stderr
@@ -11,6 +11,7 @@ LL | trait Tr {
    |       -- this trait cannot be made into an object...
 LL |     fn foo();
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `St` implements the trait, consider using it directly instead
    = note: required for the cast from `&St` to `&dyn Tr`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
@@ -34,6 +35,7 @@ LL | trait Tr {
    |       -- this trait cannot be made into an object...
 LL |     fn foo();
    |        ^^^ ...because associated function `foo` has no `self` parameter
+   = help: only type `St` implements the trait, consider using it directly instead
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self);
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
index 74a0fc42708..3972e539776 100644
--- a/tests/ui/traits/test-2.stderr
+++ b/tests/ui/traits/test-2.stderr
@@ -42,6 +42,9 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead:
+             i32
+             u32
 
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/test-2.rs:13:5
@@ -59,6 +62,9 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead:
+             i32
+             u32
 
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/test-2.rs:13:6
@@ -76,6 +82,9 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead:
+             i32
+             u32
    = note: required for the cast from `Box<{integer}>` to `Box<dyn bar>`
 
 error: aborting due to 5 previous errors
diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
index 8a296dc7ee6..4412c49eadd 100644
--- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
+++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
@@ -24,6 +24,7 @@ LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
    |       |
    |       this trait cannot be made into an object...
    = help: consider moving `add` to another trait
+   = help: only type `i32` implements the trait, consider using it directly instead
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
index 40a25c7df6b..85f5073364f 100644
--- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
+++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
@@ -11,6 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<S>` to `Box<dyn Trait>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -26,6 +27,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<S>` to `Box<(dyn Trait + 'static)>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -41,6 +43,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `Box<S>` to `Box<dyn Trait>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
index e2c71df2feb..a2a19631649 100644
--- a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
+++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
@@ -11,6 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -26,6 +27,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -41,6 +43,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: only type `S` implements the trait, consider using it directly instead
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
index d5b23572ff5..a0279774abe 100644
--- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -29,6 +29,9 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
+             S
+             R
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -48,6 +51,9 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
+             S
+             R
    = note: required for the cast from `&R` to `&dyn Trait`
 
 error: aborting due to 3 previous errors