From b1688b48d2841a1421cb7ed0afd32ce0c3eeb20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 8 Jan 2024 23:00:06 +0000 Subject: [PATCH 1/3] Avoid ICE: Check diagnostic is error before downgrading Fix #119633. --- .../rustc_hir_analysis/src/astconv/lint.rs | 8 +-- .../object-safety/avoid-ice-on-warning-2.rs | 9 ++++ .../avoid-ice-on-warning-2.stderr | 50 +++++++++++++++++++ .../ui/object-safety/avoid-ice-on-warning.rs | 6 +++ .../object-safety/avoid-ice-on-warning.stderr | 29 +++++++++++ 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-2.rs create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-2.stderr create mode 100644 tests/ui/object-safety/avoid-ice-on-warning.rs create mode 100644 tests/ui/object-safety/avoid-ice-on-warning.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 3761d52951709..bf668f311cc61 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -122,7 +122,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 +148,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 0000000000000..cd34362d3dd52 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs @@ -0,0 +1,9 @@ +fn id(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 0000000000000..2755eee6f3529 --- /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: 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 + = 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) -> 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: 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: 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 + = 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) -> 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: 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: 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 + +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.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs new file mode 100644 index 0000000000000..d2a1eeb5286b0 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.rs @@ -0,0 +1,6 @@ +fn call_this(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 0000000000000..1046f177e8296 --- /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) : 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) : 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) : 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 + = 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) : 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`. From 6b7e6ea590ad0179e9c61c5e007220ae1e4b9644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 9 Jan 2024 00:22:35 +0000 Subject: [PATCH 2/3] Account for traits using self-trait by name without `dyn` Fix #119652. --- .../rustc_hir_analysis/src/astconv/lint.rs | 24 ++-- ...-trait-should-use-self-2021-without-dyn.rs | 19 ++++ ...it-should-use-self-2021-without-dyn.stderr | 105 ++++++++++++++++++ ...bject-unsafe-trait-should-use-self-2021.rs | 17 +++ ...t-unsafe-trait-should-use-self-2021.stderr | 65 +++++++++++ 5 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index bf668f311cc61..b5f42e98127ee 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, }) 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 0000000000000..6382480b7e335 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs @@ -0,0 +1,19 @@ +// 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 +} +trait B { + fn f(a: B) -> B; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword +} +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 0000000000000..1d8ed54804626 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr @@ -0,0 +1,105 @@ +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(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; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:9:13 + | +LL | fn f(a: B) -> B; + | ^ + | +help: use a new generic type parameter, constrained by `B` + | +LL | fn f(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:9: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; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:14:20 + | +LL | fn f(&self, a: C) -> C; + | ^ + | +help: use a new generic type parameter, constrained by `C` + | +LL | fn f(&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:14: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; + | +++++++ + + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0782`. 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 0000000000000..a598e883f3fdd --- /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 0000000000000..d6376be9c046c --- /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 + --> $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 + --> $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`. From 7edbc95c27664428ba22c448ca85ee4bd4de05dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 19 Jan 2024 23:49:40 +0000 Subject: [PATCH 3/3] Update tests after rebase Fix #119652. --- .../object-safety/avoid-ice-on-warning-3.rs | 17 ++ .../avoid-ice-on-warning-3.stderr | 148 ++++++++++++++++++ ...-trait-should-use-self-2021-without-dyn.rs | 4 + ...it-should-use-self-2021-without-dyn.stderr | 75 ++++++++- 4 files changed, 238 insertions(+), 6 deletions(-) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-3.rs create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-3.stderr 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 0000000000000..caaf4d0fd99aa --- /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 0000000000000..0fc67770b96dd --- /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 + = 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(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 +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 + = 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(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 +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 + = 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(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 + --> $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 + = 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(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 + --> $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/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 index 6382480b7e335..f48c3d124ddac 100644 --- 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 @@ -4,11 +4,15 @@ 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; 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 index 1d8ed54804626..73d5a24f83137 100644 --- 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 @@ -1,3 +1,65 @@ +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 + --> $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 + --> $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 | @@ -33,7 +95,7 @@ LL | fn f(a: A) -> Box; | +++++++ + error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:9:13 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | fn f(a: B) -> B; | ^ @@ -52,7 +114,7 @@ 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:9:19 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19 | LL | fn f(a: B) -> B; | ^ @@ -67,7 +129,7 @@ LL | fn f(a: B) -> Box; | +++++++ + error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:14:20 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | fn f(&self, a: C) -> C; | ^ @@ -86,7 +148,7 @@ 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:14:26 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26 | LL | fn f(&self, a: C) -> C; | ^ @@ -100,6 +162,7 @@ help: alternatively, you can return an owned trait object LL | fn f(&self, a: C) -> Box; | +++++++ + -error: aborting due to 6 previous errors +error: aborting due to 10 previous errors -For more information about this error, try `rustc --explain E0782`. +Some errors have detailed explanations: E0038, E0782. +For more information about an error, try `rustc --explain E0038`.