about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-20 09:37:27 +0100
committerGitHub <noreply@github.com>2024-01-20 09:37:27 +0100
commit177d51372cf1b6bedc634f18a74c2052d8921d9b (patch)
tree9c15067f1f383632b043ec619a543ac45c915ac1
parent2de5ca25d2aa658553e75eedcdb6968a0d53d969 (diff)
parent7edbc95c27664428ba22c448ca85ee4bd4de05dc (diff)
downloadrust-177d51372cf1b6bedc634f18a74c2052d8921d9b.tar.gz
rust-177d51372cf1b6bedc634f18a74c2052d8921d9b.zip
Rollup merge of #119752 - estebank:ice-ice, r=fmease
Avoid ICEs in trait names without `dyn`

Check diagnostic is error before downgrading. Fix #119633.

 Account for traits using self-trait by name without `dyn`. Fix #119652.
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs32
-rw-r--r--tests/ui/object-safety/avoid-ice-on-warning-2.rs9
-rw-r--r--tests/ui/object-safety/avoid-ice-on-warning-2.stderr50
-rw-r--r--tests/ui/object-safety/avoid-ice-on-warning-3.rs17
-rw-r--r--tests/ui/object-safety/avoid-ice-on-warning-3.stderr148
-rw-r--r--tests/ui/object-safety/avoid-ice-on-warning.rs6
-rw-r--r--tests/ui/object-safety/avoid-ice-on-warning.stderr29
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs23
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr168
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs17
-rw-r--r--tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr65
11 files changed, 553 insertions, 11 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index 3761d529517..b5f42e98127 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -78,14 +78,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool {
         let tcx = self.tcx();
         let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
-        let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. })
-        | hir::Node::TraitItem(hir::TraitItem {
-            kind: hir::TraitItemKind::Fn(sig, _),
-            generics,
-            ..
-        })) = tcx.hir_node_by_def_id(parent_id)
-        else {
-            return false;
+        let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
+                (sig, generics, None)
+            }
+            hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(sig, _),
+                generics,
+                owner_id,
+                ..
+            }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
+            _ => return false,
         };
         let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
             return false;
@@ -94,6 +97,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let is_object_safe = match self_ty.kind {
             hir::TyKind::TraitObject(objects, ..) => {
                 objects.iter().all(|o| match o.trait_ref.path.res {
+                    Res::Def(DefKind::Trait, id) if Some(id) == owner => {
+                        // When we're dealing with a recursive trait, we don't want to downgrade
+                        // the error, so we consider them to be object safe always. (#119652)
+                        true
+                    }
                     Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
                     _ => false,
                 })
@@ -122,7 +130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     ],
                     Applicability::MachineApplicable,
                 );
-            } else {
+            } else if diag.is_error() {
                 // We'll emit the object safety error already, with a structured suggestion.
                 diag.downgrade_to_delayed_bug();
             }
@@ -148,8 +156,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             if !is_object_safe {
                 diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
-                // We'll emit the object safety error already, with a structured suggestion.
-                diag.downgrade_to_delayed_bug();
+                if diag.is_error() {
+                    // We'll emit the object safety error already, with a structured suggestion.
+                    diag.downgrade_to_delayed_bug();
+                }
             } else {
                 let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
                     // There are more than one trait bound, we need surrounding parentheses.
diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/object-safety/avoid-ice-on-warning-2.rs
new file mode 100644
index 00000000000..cd34362d3dd
--- /dev/null
+++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs
@@ -0,0 +1,9 @@
+fn id<F>(f: Copy) -> usize {
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+//~| WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+//~| ERROR the trait `Copy` cannot be made into an object
+    f()
+}
+fn main() {}
diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr
new file mode 100644
index 00000000000..2755eee6f35
--- /dev/null
+++ b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr
@@ -0,0 +1,50 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-2.rs:1:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `Copy` it is not object safe, so it can't be `dyn`
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: use a new generic type parameter, constrained by `Copy`
+   |
+LL | fn id<F, T: Copy>(f: T) -> usize {
+   |        +++++++++     ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | fn id<F>(f: impl Copy) -> usize {
+   |             ++++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-2.rs:1:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `Copy` it is not object safe, so it can't be `dyn`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: use a new generic type parameter, constrained by `Copy`
+   |
+LL | fn id<F, T: Copy>(f: T) -> usize {
+   |        +++++++++     ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | fn id<F>(f: impl Copy) -> usize {
+   |             ++++
+
+error[E0038]: the trait `Copy` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-2.rs:1:13
+   |
+LL | fn id<F>(f: Copy) -> usize {
+   |             ^^^^ `Copy` cannot be made into an object
+   |
+   = note: the trait cannot be made into an object because it requires `Self: Sized`
+   = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+
+error: aborting due to 1 previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/object-safety/avoid-ice-on-warning-3.rs
new file mode 100644
index 00000000000..caaf4d0fd99
--- /dev/null
+++ b/tests/ui/object-safety/avoid-ice-on-warning-3.rs
@@ -0,0 +1,17 @@
+trait B { fn f(a: A) -> A; }
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+//~| ERROR the trait `A` cannot be made into an object
+trait A { fn g(b: B) -> B; }
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+//~| WARN this is accepted in the current edition
+//~| ERROR the trait `B` cannot be made into an object
+fn main() {}
diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr
new file mode 100644
index 00000000000..0fc67770b96
--- /dev/null
+++ b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr
@@ -0,0 +1,148 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:9:19
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `B` it is not object safe, so it can't be `dyn`
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: use a new generic type parameter, constrained by `B`
+   |
+LL | trait A { fn g<T: B>(b: T) -> B; }
+   |               ++++++    ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | trait A { fn g(b: impl B) -> B; }
+   |                   ++++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:9:25
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                         ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type
+   |
+LL | trait A { fn g(b: B) -> impl B; }
+   |                         ++++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:1:19
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `A` it is not object safe, so it can't be `dyn`
+help: use a new generic type parameter, constrained by `A`
+   |
+LL | trait B { fn f<T: A>(a: T) -> A; }
+   |               ++++++    ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | trait B { fn f(a: impl A) -> A; }
+   |                   ++++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:1:25
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                         ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type
+   |
+LL | trait B { fn f(a: A) -> impl A; }
+   |                         ++++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:1:19
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `A` it is not object safe, so it can't be `dyn`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: use a new generic type parameter, constrained by `A`
+   |
+LL | trait B { fn f<T: A>(a: T) -> A; }
+   |               ++++++    ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | trait B { fn f(a: impl A) -> A; }
+   |                   ++++
+
+error[E0038]: the trait `A` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-3.rs:1:19
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |                   ^ `A` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/avoid-ice-on-warning-3.rs:9:14
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |       -      ^ ...because associated function `g` has no `self` parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider turning `g` into a method by giving it a `&self` argument
+   |
+LL | trait A { fn g(&self, b: B) -> B; }
+   |                ++++++
+help: alternatively, consider constraining `g` so it does not apply to trait objects
+   |
+LL | trait A { fn g(b: B) -> B where Self: Sized; }
+   |                           +++++++++++++++++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning-3.rs:9:19
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                   ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `B` it is not object safe, so it can't be `dyn`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: use a new generic type parameter, constrained by `B`
+   |
+LL | trait A { fn g<T: B>(b: T) -> B; }
+   |               ++++++    ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | trait A { fn g(b: impl B) -> B; }
+   |                   ++++
+
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/avoid-ice-on-warning-3.rs:9:19
+   |
+LL | trait A { fn g(b: B) -> B; }
+   |                   ^ `B` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/avoid-ice-on-warning-3.rs:1:14
+   |
+LL | trait B { fn f(a: A) -> A; }
+   |       -      ^ ...because associated function `f` has no `self` parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider turning `f` into a method by giving it a `&self` argument
+   |
+LL | trait B { fn f(&self, a: A) -> A; }
+   |                ++++++
+help: alternatively, consider constraining `f` so it does not apply to trait objects
+   |
+LL | trait B { fn f(a: A) -> A where Self: Sized; }
+   |                           +++++++++++++++++
+
+error: aborting due to 2 previous errors; 6 warnings emitted
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs
new file mode 100644
index 00000000000..d2a1eeb5286
--- /dev/null
+++ b/tests/ui/object-safety/avoid-ice-on-warning.rs
@@ -0,0 +1,6 @@
+fn call_this<F>(f: F) : Fn(&str) + call_that {}
+//~^ ERROR return types are denoted using `->`
+//~| ERROR cannot find trait `call_that` in this scope
+//~| WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+fn main() {}
diff --git a/tests/ui/object-safety/avoid-ice-on-warning.stderr b/tests/ui/object-safety/avoid-ice-on-warning.stderr
new file mode 100644
index 00000000000..1046f177e82
--- /dev/null
+++ b/tests/ui/object-safety/avoid-ice-on-warning.stderr
@@ -0,0 +1,29 @@
+error: return types are denoted using `->`
+  --> $DIR/avoid-ice-on-warning.rs:1:23
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                       ^ help: use `->` instead
+
+error[E0405]: cannot find trait `call_that` in this scope
+  --> $DIR/avoid-ice-on-warning.rs:1:36
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                                    ^^^^^^^^^ not found in this scope
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/avoid-ice-on-warning.rs:1:25
+   |
+LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
+   |                         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: `Fn(&str) + call_that` is not object safe, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type
+   |
+LL | fn call_this<F>(f: F) : impl Fn(&str) + call_that {}
+   |                         ++++
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs
new file mode 100644
index 00000000000..f48c3d124dd
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs
@@ -0,0 +1,23 @@
+// edition:2021
+#![allow(bare_trait_objects)]
+trait A: Sized {
+    fn f(a: A) -> A;
+    //~^ ERROR trait objects must include the `dyn` keyword
+    //~| ERROR trait objects must include the `dyn` keyword
+    //~| ERROR associated item referring to unboxed trait object for its own trait
+    //~| ERROR the trait `A` cannot be made into an object
+}
+trait B {
+    fn f(a: B) -> B;
+    //~^ ERROR trait objects must include the `dyn` keyword
+    //~| ERROR trait objects must include the `dyn` keyword
+    //~| ERROR associated item referring to unboxed trait object for its own trait
+    //~| ERROR the trait `B` cannot be made into an object
+}
+trait C {
+    fn f(&self, a: C) -> C;
+    //~^ ERROR trait objects must include the `dyn` keyword
+    //~| ERROR trait objects must include the `dyn` keyword
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr
new file mode 100644
index 00000000000..73d5a24f831
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr
@@ -0,0 +1,168 @@
+error: associated item referring to unboxed trait object for its own trait
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
+   |
+LL | trait A: Sized {
+   |       - in this trait
+LL |     fn f(a: A) -> A;
+   |             ^     ^
+   |
+help: you might have meant to use `Self` to refer to the implementing type
+   |
+LL |     fn f(a: Self) -> Self;
+   |             ~~~~     ~~~~
+
+error[E0038]: the trait `A` cannot be made into an object
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
+   |
+LL |     fn f(a: A) -> A;
+   |             ^ `A` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:3:10
+   |
+LL | trait A: Sized {
+   |       -  ^^^^^ ...because it requires `Self: Sized`
+   |       |
+   |       this trait cannot be made into an object...
+
+error: associated item referring to unboxed trait object for its own trait
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
+   |
+LL | trait B {
+   |       - in this trait
+LL |     fn f(a: B) -> B;
+   |             ^     ^
+   |
+help: you might have meant to use `Self` to refer to the implementing type
+   |
+LL |     fn f(a: Self) -> Self;
+   |             ~~~~     ~~~~
+
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
+   |
+LL |     fn f(a: B) -> B;
+   |             ^ `B` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8
+   |
+LL | trait B {
+   |       - this trait cannot be made into an object...
+LL |     fn f(a: B) -> B;
+   |        ^ ...because associated function `f` has no `self` parameter
+help: consider turning `f` into a method by giving it a `&self` argument
+   |
+LL |     fn f(&self, a: B) -> B;
+   |          ++++++
+help: alternatively, consider constraining `f` so it does not apply to trait objects
+   |
+LL |     fn f(a: B) -> B where Self: Sized;
+   |                     +++++++++++++++++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
+   |
+LL |     fn f(a: A) -> A;
+   |             ^
+   |
+help: use a new generic type parameter, constrained by `A`
+   |
+LL |     fn f<T: A>(a: T) -> A;
+   |         ++++++    ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn f(a: impl A) -> A;
+   |             ++++
+help: alternatively, use a trait object to accept any type that implements `A`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn f(a: &dyn A) -> A;
+   |             ++++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19
+   |
+LL |     fn f(a: A) -> A;
+   |                   ^
+   |
+help: use `impl A` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn f(a: A) -> impl A;
+   |                   ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn f(a: A) -> Box<dyn A>;
+   |                   +++++++  +
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
+   |
+LL |     fn f(a: B) -> B;
+   |             ^
+   |
+help: use a new generic type parameter, constrained by `B`
+   |
+LL |     fn f<T: B>(a: T) -> B;
+   |         ++++++    ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn f(a: impl B) -> B;
+   |             ++++
+help: alternatively, use a trait object to accept any type that implements `B`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn f(a: &dyn B) -> B;
+   |             ++++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19
+   |
+LL |     fn f(a: B) -> B;
+   |                   ^
+   |
+help: use `impl B` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn f(a: B) -> impl B;
+   |                   ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn f(a: B) -> Box<dyn B>;
+   |                   +++++++  +
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
+   |
+LL |     fn f(&self, a: C) -> C;
+   |                    ^
+   |
+help: use a new generic type parameter, constrained by `C`
+   |
+LL |     fn f<T: C>(&self, a: T) -> C;
+   |         ++++++           ~
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL |     fn f(&self, a: impl C) -> C;
+   |                    ++++
+help: alternatively, use a trait object to accept any type that implements `C`, accessing its methods at runtime using dynamic dispatch
+   |
+LL |     fn f(&self, a: &dyn C) -> C;
+   |                    ++++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26
+   |
+LL |     fn f(&self, a: C) -> C;
+   |                          ^
+   |
+help: use `impl C` to return an opaque type, as long as you return a single underlying type
+   |
+LL |     fn f(&self, a: C) -> impl C;
+   |                          ++++
+help: alternatively, you can return an owned trait object
+   |
+LL |     fn f(&self, a: C) -> Box<dyn C>;
+   |                          +++++++  +
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0038, E0782.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs
new file mode 100644
index 00000000000..a598e883f3f
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs
@@ -0,0 +1,17 @@
+// edition:2021
+#![allow(bare_trait_objects)]
+trait A: Sized {
+    fn f(a: dyn A) -> dyn A;
+    //~^ ERROR associated item referring to unboxed trait object for its own trait
+    //~| ERROR the trait `A` cannot be made into an object
+}
+trait B {
+    fn f(a: dyn B) -> dyn B;
+    //~^ ERROR associated item referring to unboxed trait object for its own trait
+    //~| ERROR the trait `B` cannot be made into an object
+}
+trait C {
+    fn f(&self, a: dyn C) -> dyn C;
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr
new file mode 100644
index 00000000000..d6376be9c04
--- /dev/null
+++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr
@@ -0,0 +1,65 @@
+error: associated item referring to unboxed trait object for its own trait
+  --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13
+   |
+LL | trait A: Sized {
+   |       - in this trait
+LL |     fn f(a: dyn A) -> dyn A;
+   |             ^^^^^     ^^^^^
+   |
+help: you might have meant to use `Self` to refer to the implementing type
+   |
+LL |     fn f(a: Self) -> Self;
+   |             ~~~~     ~~~~
+
+error[E0038]: the trait `A` cannot be made into an object
+  --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13
+   |
+LL |     fn f(a: dyn A) -> dyn A;
+   |             ^^^^^ `A` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-unsafe-trait-should-use-self-2021.rs:3:10
+   |
+LL | trait A: Sized {
+   |       -  ^^^^^ ...because it requires `Self: Sized`
+   |       |
+   |       this trait cannot be made into an object...
+
+error: associated item referring to unboxed trait object for its own trait
+  --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13
+   |
+LL | trait B {
+   |       - in this trait
+LL |     fn f(a: dyn B) -> dyn B;
+   |             ^^^^^     ^^^^^
+   |
+help: you might have meant to use `Self` to refer to the implementing type
+   |
+LL |     fn f(a: Self) -> Self;
+   |             ~~~~     ~~~~
+
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13
+   |
+LL |     fn f(a: dyn B) -> dyn B;
+   |             ^^^^^ `B` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:8
+   |
+LL | trait B {
+   |       - this trait cannot be made into an object...
+LL |     fn f(a: dyn B) -> dyn B;
+   |        ^ ...because associated function `f` has no `self` parameter
+help: consider turning `f` into a method by giving it a `&self` argument
+   |
+LL |     fn f(&self, a: dyn B) -> dyn B;
+   |          ++++++
+help: alternatively, consider constraining `f` so it does not apply to trait objects
+   |
+LL |     fn f(a: dyn B) -> dyn B where Self: Sized;
+   |                             +++++++++++++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0038`.