From 26cfeb185d3816f7b1a685cd69b1f15b2a815d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 30 May 2024 18:40:30 +0000 Subject: [PATCH 01/26] Silence errors in experssions caused by bare traits in paths Address #51077 in editions>=2021 by treating `` as a `<{type error}>` instead of ``, silencing subsequent errors. We new emit a single error ("missing `dyn`"). ``` error[E0782]: trait objects must include the `dyn` keyword --> f800.rs:2:15 | 2 | let x: u32 = ::default(); | ^^^^^^^ | help: add `dyn` keyword before this trait | 2 | let x: u32 = ::default(); | +++ ``` instead of 6 ``` error[E0782]: trait objects must include the `dyn` keyword --> f800.rs:2:15 | 2 | let x: u32 = ::default(); | ^^^^^^^ | help: add `dyn` keyword before this trait | 2 | let x: u32 = ::default(); | +++ error[E0038]: the trait `Default` cannot be made into an object --> f800.rs:2:15 | 2 | let x: u32 = ::default(); | ^^^^^^^ `Default` 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[E0277]: the size for values of type `dyn Default` cannot be known at compilation time --> f800.rs:2:15 | 2 | let x: u32 = ::default(); | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Default` note: required by a bound in `default` --> /home/gh-estebank/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/default.rs:104:20 | 104 | pub trait Default: Sized { | ^^^^^ required by this bound in `Default::default` ... 136 | fn default() -> Self; | ------- required by a bound in this associated function error[E0308]: mismatched types --> f800.rs:2:14 | 2 | let x: u32 = ::default(); | --- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `dyn Default` | | | expected due to this | = note: expected type `u32` found trait object `dyn Default` = help: `u32` implements `Default` so you could change the expected type to `Box` error[E0038]: the trait `Default` cannot be made into an object --> f800.rs:2:14 | 2 | let x: u32 = ::default(); | ^^^^^^^^^^^^^^^^^^^^ `Default` 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[E0277]: the size for values of type `dyn Default` cannot be known at compilation time --> f800.rs:2:14 | 2 | let x: u32 = ::default(); | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Default` = note: the return type of a function must have a statically known size ``` --- .../src/hir_ty_lowering/lint.rs | 9 +-- .../src/hir_ty_lowering/mod.rs | 13 +++- .../suggest-assoc-ty-bound-on-eq-bound.rs | 4 -- .../suggest-assoc-ty-bound-on-eq-bound.stderr | 42 ++---------- ...to-be-a-closure-or-coroutine-ice-113776.rs | 4 +- ...e-a-closure-or-coroutine-ice-113776.stderr | 27 +------- ...g-dyn-in-qualified-path.edition2018.stderr | 67 +++++++++++++++++++ ...g-dyn-in-qualified-path.edition2021.stderr | 14 ++++ .../trait-missing-dyn-in-qualified-path.rs | 14 ++++ ...plicit-hrtb-without-dyn.edition2021.stderr | 11 +-- .../generic-with-implicit-hrtb-without-dyn.rs | 1 - tests/ui/resolve/issue-111312.rs | 5 +- tests/ui/resolve/issue-111312.stderr | 22 ++---- tests/ui/resolve/issue-111727.rs | 1 - tests/ui/resolve/issue-111727.stderr | 11 +-- 15 files changed, 131 insertions(+), 114 deletions(-) create mode 100644 tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr create mode 100644 tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr create mode 100644 tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 240a749de96a6..482940343cd58 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -1,5 +1,5 @@ use rustc_ast::TraitObjectSyntax; -use rustc_errors::{codes::*, Diag, EmissionGuarantee, StashKey}; +use rustc_errors::{codes::*, Diag, EmissionGuarantee, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; @@ -17,13 +17,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, self_ty: &hir::Ty<'_>, in_path: bool, - ) { + ) -> Option { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = self_ty.kind else { - return; + return None; }; let needs_bracket = in_path @@ -70,7 +70,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); + diag.stash(self_ty.span, StashKey::TraitMissingMethod) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); @@ -83,6 +83,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } self.maybe_suggest_blanket_trait_impl(self_ty, lint); }); + None } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7ec64f1feda24..24a25acb61eea 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2069,7 +2069,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path); + if let Some(guard) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path) { + if let hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) = + tcx.parent_hir_node(hir_ty.hir_id) + { + // `tests/ui/suggestions/issue-116434-2021.rs` and others would otherwise + // fail with no error beign emitted. We restrict the silencing only to + // expressions, as those *will* emit the error *and* also produce further + // knock-down errors. + } else { + return Ty::new_error(tcx, guard); + } + } let repr = match repr { TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs index 7df042d5f88e6..23f89eb28eb38 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs @@ -5,15 +5,11 @@ fn f(_: impl Trait) {} //~^ ERROR trait objects must include the `dyn` keyword //~| HELP add `dyn` keyword before this trait //~| HELP you might have meant to write a bound here -//~| ERROR the trait `Copy` cannot be made into an object fn g(_: impl Trait) {} //~^ ERROR trait objects must include the `dyn` keyword //~| HELP add `dyn` keyword before this trait //~| HELP you might have meant to write a bound here -//~| ERROR only auto traits can be used as additional traits in a trait object -//~| HELP consider creating a new trait -//~| ERROR the trait `Eq` cannot be made into an object fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} //~^ ERROR trait objects must include the `dyn` keyword diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr index 13be2162c52b1..990aae8cfe38b 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr @@ -1,34 +1,3 @@ -error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:20 - | -LL | fn f(_: impl Trait) {} - | ^^^^^^^^ `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[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:42 - | -LL | fn g(_: impl Trait) {} - | --------------- ^^ additional non-auto trait - | | - | first non-auto trait - | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Debug + Eq {}` - = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit - -error[E0038]: the trait `Eq` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 - | -LL | fn g(_: impl Trait) {} - | ^^^^^^^^^^^^^^^^^^^^ `Eq` 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 - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - error[E0782]: trait objects must include the `dyn` keyword --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:24 | @@ -45,7 +14,7 @@ LL | fn f(_: impl Trait) {} | ~ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:9:24 | LL | fn g(_: impl Trait) {} | ^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +29,7 @@ LL | fn g(_: impl Trait) {} | ~ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26 + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:14:26 | LL | fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +44,7 @@ LL | fn h(_: impl Trait: 'static + for<'a> Fn(&'a ())>) {} | ~ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:24:26 + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:20:26 | LL | type Obj = dyn Trait; | ^^^^^ @@ -85,7 +54,6 @@ help: add `dyn` keyword before this trait LL | type Obj = dyn Trait; | +++ -error: aborting due to 7 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0038, E0225, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs index 4bea3ad87f5ed..6fa23527febf2 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs @@ -14,10 +14,8 @@ fn f( 1 }], ) -> impl Iterator { -//~^ ERROR the type parameter `Rhs` must be explicitly specified -//~| ERROR `()` is not an iterator +//~^ ERROR `()` is not an iterator //~| ERROR trait objects must include the `dyn` keyword -//~| ERROR the type parameter `Rhs` must be explicitly specified [E0393] } pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr index be79450a3ce31..2f61bfe788392 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr @@ -16,29 +16,6 @@ help: you might be missing a type parameter LL | fn f( | +++ -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ help: set the type parameter to the desired type: `SubAssign` - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types - -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ help: set the type parameter to the desired type: `SubAssign` - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0277]: `()` is not an iterator --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:6 | @@ -62,7 +39,7 @@ help: you might have meant to write a bound here LL | ) -> impl Iterator { | ~ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0393, E0412, E0782. +Some errors have detailed explanations: E0277, E0412, E0782. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr new file mode 100644 index 0000000000000..5ee6fd8accff4 --- /dev/null +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr @@ -0,0 +1,67 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 + | +LL | let x: u32 = ::default(); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: if this is an object-safe trait, use `dyn` + | +LL | let x: u32 = ::default(); + | +++ + +error[E0038]: the trait `Default` cannot be made into an object + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 + | +LL | let x: u32 = ::default(); + | ^^^^^^^ `Default` 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[E0277]: the size for values of type `dyn Default` cannot be known at compilation time + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 + | +LL | let x: u32 = ::default(); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Default` +note: required by a bound in `default` + --> $SRC_DIR/core/src/default.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 + | +LL | let x: u32 = ::default(); + | --- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `dyn Default` + | | + | expected due to this + | + = note: expected type `u32` + found trait object `dyn Default` + = help: `u32` implements `Default` so you could change the expected type to `Box` + +error[E0038]: the trait `Default` cannot be made into an object + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 + | +LL | let x: u32 = ::default(); + | ^^^^^^^^^^^^^^^^^^^^ `Default` 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[E0277]: the size for values of type `dyn Default` cannot be known at compilation time + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 + | +LL | let x: u32 = ::default(); + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Default` + = note: the return type of a function must have a statically known size + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0038, E0277, E0308. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr new file mode 100644 index 0000000000000..2222cecbaa185 --- /dev/null +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr @@ -0,0 +1,14 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 + | +LL | let x: u32 = ::default(); + | ^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | let x: u32 = ::default(); + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs new file mode 100644 index 0000000000000..53aaaee2cb834 --- /dev/null +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs @@ -0,0 +1,14 @@ +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +fn main() { + let x: u32 = ::default(); + //[edition2021]~^ ERROR trait objects must include the `dyn` keyword + //[edition2018]~^^ WARNING trait objects without an explicit `dyn` are deprecated + //[edition2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + //[edition2018]~| ERROR trait `Default` cannot be made into an object + //[edition2018]~| ERROR trait `Default` cannot be made into an object + //[edition2018]~| ERROR the size for values of type `dyn Default` cannot be known at compilation time + //[edition2018]~| ERROR the size for values of type `dyn Default` cannot be known at compilation time + //[edition2018]~| ERROR mismatched types +} diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr index 7917fa991ee32..2e13ca753fc29 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -1,9 +1,3 @@ -error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied - --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` - error[E0782]: trait objects must include the `dyn` keyword --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24 | @@ -15,7 +9,6 @@ help: add `dyn` keyword before this trait LL | fn ice() -> impl AsRef { | +++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 582386aa7596a..df29961b3ebe7 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -6,7 +6,6 @@ fn ice() -> impl AsRef { //[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] //[edition2021]~^^ ERROR: trait objects must include the `dyn` keyword [E0782] - //[edition2021]~| ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] todo!() } diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs index 79c6f67dadd39..c8de1570cd093 100644 --- a/tests/ui/resolve/issue-111312.rs +++ b/tests/ui/resolve/issue-111312.rs @@ -7,7 +7,6 @@ trait Has { trait HasNot {} fn main() { - HasNot::has(); - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `has` found for trait `HasNot` + ::has(); + //~^ ERROR no function or associated item named `has` found for trait `HasNot` } diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr index 431802ead30c4..99bc1c4437728 100644 --- a/tests/ui/resolve/issue-111312.stderr +++ b/tests/ui/resolve/issue-111312.stderr @@ -1,19 +1,8 @@ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/issue-111312.rs:10:5 - | -LL | HasNot::has(); - | ^^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | ::has(); - | ++++ + - error[E0599]: no function or associated item named `has` found for trait `HasNot` - --> $DIR/issue-111312.rs:10:13 + --> $DIR/issue-111312.rs:10:19 | -LL | HasNot::has(); - | ^^^ function or associated item not found in `HasNot` +LL | ::has(); + | ^^^ function or associated item not found in `HasNot` | note: `Has` defines an item `has` --> $DIR/issue-111312.rs:3:1 @@ -21,7 +10,6 @@ note: `Has` defines an item `has` LL | trait Has { | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs index fcab924b80977..b698c1dc1b167 100644 --- a/tests/ui/resolve/issue-111727.rs +++ b/tests/ui/resolve/issue-111727.rs @@ -3,5 +3,4 @@ fn main() { std::any::Any::create(); //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `create` found for trait `Any` } diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr index 1ef5a1a1d5efb..4cb280cfed950 100644 --- a/tests/ui/resolve/issue-111727.stderr +++ b/tests/ui/resolve/issue-111727.stderr @@ -9,13 +9,6 @@ help: add `dyn` keyword before this trait LL | ::create(); | ++++ + -error[E0599]: no function or associated item named `create` found for trait `Any` - --> $DIR/issue-111727.rs:4:20 - | -LL | std::any::Any::create(); - | ^^^^^^ function or associated item not found in `Any` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0782`. From 936b6920446c62434632a844ef8342102ef12d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 31 May 2024 00:13:55 +0000 Subject: [PATCH 02/26] Silence unsized types errors in some expressions When encountering an unsized E0277 error on a method that returns `Self` silence that error as it a prior unsized error will have been emitted when constructing the value of `Self`. On E0227 unsized error caused on a bare trait associated function with object safety violations, silence it. --- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- .../error_reporting/type_err_ctxt_ext.rs | 28 ++++++++++++++++++- ...g-dyn-in-qualified-path.edition2018.stderr | 23 ++------------- .../trait-missing-dyn-in-qualified-path.rs | 2 -- tests/ui/traits/bad-sized.rs | 1 - tests/ui/traits/bad-sized.stderr | 12 +------- 8 files changed, 33 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d5d360ca0479f..5b8689a73176d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -591,7 +591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized_deferred( output, call.map_or(expr.span, |e| e.span), - ObligationCauseCode::SizedCallReturnType, + ObligationCauseCode::SizedCallReturnType(did), ); } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 202d587f0ad21..74328ee32a10c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -284,7 +284,7 @@ pub enum ObligationCauseCode<'tcx> { /// Return type must be `Sized`. SizedReturnType, /// Return type of a call expression must be `Sized`. - SizedCallReturnType, + SizedCallReturnType(DefId), /// Yield type must be `Sized`. SizedYieldType, /// Inline asm operand type must be `Sized`. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c7da85bd1cc47..0af557b6b9f4e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3081,7 +3081,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.help("unsized fn params are gated as an unstable feature"); } } - ObligationCauseCode::SizedReturnType | ObligationCauseCode::SizedCallReturnType => { + ObligationCauseCode::SizedReturnType | ObligationCauseCode::SizedCallReturnType(_) => { err.note("the return type of a function must have a statically known size"); } ObligationCauseCode::SizedYieldType => { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 46b137881866e..62cba3fec830c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -48,7 +48,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; -use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, ExpnKind, Span, Symbol, DUMMY_SP}; use std::borrow::Cow; use std::fmt; @@ -638,6 +638,32 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.span_label(span, explanation); } + if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { + if !self.tcx.object_safety_violations(trait_ref.def_id()).is_empty() { + match ( + obligation.cause.code(), + trait_ref.skip_binder().self_ty().kind(), + ) { + ( + ObligationCauseCode::WhereClauseInExpr(..), + ty::Dynamic(..), + ) => { + return err.delay_as_bug(); + } + (ObligationCauseCode::SizedCallReturnType(did), _) => { + let fn_sig = self.tcx.fn_sig(did); + let ret_kind = + fn_sig.skip_binder().output().skip_binder().kind(); + if let ty::Param(param_ty) = ret_kind + && param_ty.name == kw::SelfUpper + { + return err.delay_as_bug(); + } + } + _ => {} + } + } + } if let ObligationCauseCode::Coercion { source, target } = *obligation.cause.code().peel_derives() { diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr index 5ee6fd8accff4..c4400ff5978c1 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr @@ -21,16 +21,6 @@ LL | let x: u32 = ::default(); = 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[E0277]: the size for values of type `dyn Default` cannot be known at compilation time - --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 - | -LL | let x: u32 = ::default(); - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `dyn Default` -note: required by a bound in `default` - --> $SRC_DIR/core/src/default.rs:LL:COL - error[E0308]: mismatched types --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 | @@ -52,16 +42,7 @@ LL | let x: u32 = ::default(); = 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[E0277]: the size for values of type `dyn Default` cannot be known at compilation time - --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 - | -LL | let x: u32 = ::default(); - | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `dyn Default` - = note: the return type of a function must have a statically known size - -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted -Some errors have detailed explanations: E0038, E0277, E0308. +Some errors have detailed explanations: E0038, E0308. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs index 53aaaee2cb834..90bfc5f5b8963 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs @@ -8,7 +8,5 @@ fn main() { //[edition2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! //[edition2018]~| ERROR trait `Default` cannot be made into an object //[edition2018]~| ERROR trait `Default` cannot be made into an object - //[edition2018]~| ERROR the size for values of type `dyn Default` cannot be known at compilation time - //[edition2018]~| ERROR the size for values of type `dyn Default` cannot be known at compilation time //[edition2018]~| ERROR mismatched types } diff --git a/tests/ui/traits/bad-sized.rs b/tests/ui/traits/bad-sized.rs index a15219679788d..b899c59ff2ea7 100644 --- a/tests/ui/traits/bad-sized.rs +++ b/tests/ui/traits/bad-sized.rs @@ -5,5 +5,4 @@ pub fn main() { //~^ ERROR only auto traits can be used as additional traits in a trait object //~| ERROR the size for values of type //~| ERROR the size for values of type - //~| ERROR the size for values of type } diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr index 4c1835dfed085..4cd7a192fca7c 100644 --- a/tests/ui/traits/bad-sized.stderr +++ b/tests/ui/traits/bad-sized.stderr @@ -19,16 +19,6 @@ LL | let x: Vec = Vec::new(); note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time - --> $DIR/bad-sized.rs:4:37 - | -LL | let x: Vec = Vec::new(); - | ^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `dyn Trait` -note: required by a bound in `Vec::::new` - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:37 | @@ -39,7 +29,7 @@ LL | let x: Vec = Vec::new(); note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0225, E0277. For more information about an error, try `rustc --explain E0225`. From 5028c3076b79d656ad235688b7cd66626eaa9f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 31 May 2024 23:09:32 +0000 Subject: [PATCH 03/26] Avoid potential for ICE by not stashing delayed as bug error and silence more redundant errors Instead of calling `dowgrade_to_delayed_bug` and then stashing a diagnostic, we either stash the diagnostic or we `delay_as_bug` it. Remove unnecessary restriction of silencing of knock down errors on bare trait objects in edition >=2021. --- .../src/hir_ty_lowering/lint.rs | 46 +++++++++---- .../src/hir_ty_lowering/mod.rs | 11 +-- ...-trait-should-use-self-2021-without-dyn.rs | 3 - ...it-should-use-self-2021-without-dyn.stderr | 69 +++---------------- .../ui/traits/bound/not-on-bare-trait-2021.rs | 2 - .../bound/not-on-bare-trait-2021.stderr | 43 ++---------- tests/ui/traits/issue-106072.rs | 6 +- tests/ui/traits/issue-106072.stderr | 27 ++------ 8 files changed, 51 insertions(+), 156 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 482940343cd58..b42dc96f7b78f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -61,16 +61,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let label = "add `dyn` keyword before this trait"; let mut diag = rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); - if self_ty.span.can_be_used_for_suggestions() - && !self.maybe_suggest_impl_trait(self_ty, &mut diag) - { - // FIXME: Only emit this suggestion if the trait is object safe. - diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable); + let mut downgrade = false; + if self_ty.span.can_be_used_for_suggestions() { + let (non_object_safe, should_downgrade) = + self.maybe_suggest_impl_trait(self_ty, &mut diag); + downgrade = should_downgrade; + if !non_object_safe { + // Only emit this suggestion if the trait is object safe. + diag.multipart_suggestion_verbose( + label, + sugg, + Applicability::MachineApplicable, + ); + } } // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod) + if downgrade { + // FIXME: Delayed bugs and stashing are not compatible, so we paper over it here by + // consuming the diagnostic without emitting it, instead of downgrading it. + diag.delay_as_bug(); + None + } else { + diag.stash(self_ty.span, StashKey::TraitMissingMethod) + } } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); @@ -153,7 +168,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Make sure that we are in the condition to suggest `impl Trait`. - fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool { + /// + /// Returns whether a suggestion was provided and whether the error itself should not be emitted + fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> (bool, bool) { let tcx = self.tcx(); let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0` @@ -168,13 +185,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { owner_id, .. }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), - _ => return false, + _ => return (false, false), }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { - return false; + return (false, false); }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; let mut is_downgradable = true; + let mut downgrade = false; let is_object_safe = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|o| match o.trait_ref.path.res { @@ -214,9 +232,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } else if is_downgradable { // We'll emit the object safety error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); + downgrade = true; } - return true; + return (true, downgrade); } for ty in sig.decl.inputs { if ty.hir_id != self_ty.hir_id { @@ -240,7 +258,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); if is_downgradable { // We'll emit the object safety error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); + downgrade = true; } } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { @@ -261,9 +279,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MachineApplicable, ); } - return true; + return (true, downgrade); } - false + (false, downgrade) } fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 24a25acb61eea..2ebb0ce3dfb36 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2070,16 +2070,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } hir::TyKind::TraitObject(bounds, lifetime, repr) => { if let Some(guard) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path) { - if let hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) = - tcx.parent_hir_node(hir_ty.hir_id) - { - // `tests/ui/suggestions/issue-116434-2021.rs` and others would otherwise - // fail with no error beign emitted. We restrict the silencing only to - // expressions, as those *will* emit the error *and* also produce further - // knock-down errors. - } else { - return Ty::new_error(tcx, guard); - } + return Ty::new_error(tcx, guard); } let repr = match repr { 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 37afab6b643ca..6519e13bbb7ba 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 @@ -5,21 +5,18 @@ trait A: Sized { //~^ 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(b: 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, c: C) -> C; //~^ 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 `C` cannot be made into an object } 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 index 60eb72ab4f768..45289785af55c 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 @@ -11,22 +11,8 @@ 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 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | trait B { | - in this trait @@ -38,30 +24,8 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(b: 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(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/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(b: 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, b: B) -> B; - | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects - | -LL | fn f(b: B) -> B where Self: Sized; - | +++++++++++++++++ - error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | trait C { | - in this trait @@ -73,22 +37,6 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(&self, c: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `C` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 - | -LL | fn f(&self, c: C) -> C; - | ----- ^ `C` cannot be made into an object - | | - | help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self` - | -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:18:10 - | -LL | trait C { - | - this trait cannot be made into an object... -LL | fn f(&self, c: C) -> C; - | ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on - error[E0782]: trait objects must include the `dyn` keyword --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 | @@ -117,7 +65,7 @@ LL | fn f(a: A) -> impl A; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | fn f(b: B) -> B; | ^ @@ -133,7 +81,7 @@ LL | fn f(b: impl B) -> B; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:10:19 | LL | fn f(b: B) -> B; | ^ @@ -144,7 +92,7 @@ LL | fn f(b: B) -> impl B; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | fn f(&self, c: C) -> C; | ^ @@ -160,7 +108,7 @@ LL | fn f(&self, c: impl C) -> C; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26 + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:16:26 | LL | fn f(&self, c: C) -> C; | ^ @@ -170,7 +118,6 @@ help: `C` is not object safe, use `impl C` to return an opaque type, as long as LL | fn f(&self, c: C) -> impl C; | ++++ -error: aborting due to 12 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0038, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.rs b/tests/ui/traits/bound/not-on-bare-trait-2021.rs index 07b866cb4a65b..0f2099be6ec3a 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.rs +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.rs @@ -7,12 +7,10 @@ trait Foo { fn foo(_x: Foo + Send) { //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type } fn bar(x: Foo) -> Foo { //~^ ERROR trait objects must include the `dyn` keyword //~| ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type x } diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr index 57d3bc8f10948..6f41f872e4cf6 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr @@ -1,37 +1,3 @@ -error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:8:8 - | -LL | fn foo(_x: Foo + Send) { - | ^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn foo(_x: impl Foo + Send) { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn foo(_x: &(dyn Foo + Send)) { - | +++++ + - -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:12:8 - | -LL | fn bar(x: Foo) -> Foo { - | ^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn bar(x: impl Foo) -> Foo { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn bar(x: &dyn Foo) -> Foo { - | ++++ - error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:8:12 | @@ -52,7 +18,7 @@ LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:11 + --> $DIR/not-on-bare-trait-2021.rs:11:11 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -71,7 +37,7 @@ LL | fn bar(x: &dyn Foo) -> Foo { | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:19 + --> $DIR/not-on-bare-trait-2021.rs:11:19 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -85,7 +51,6 @@ help: alternatively, you can return an owned trait object LL | fn bar(x: Foo) -> Box { | +++++++ + -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index 8adbac46a5bd8..7122b60d478d5 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] //~ trait objects must include the `dyn` keyword -//~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known -//~| ERROR: return type cannot have an unboxed trait object +#[derive(Clone)] //~ERROR trait objects must include the `dyn` keyword struct Foo; -trait Foo {} //~ the name `Foo` is defined multiple times +trait Foo {} //~ERROR the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 6476c8b3237ac..1037603ceb777 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-106072.rs:5:1 + --> $DIR/issue-106072.rs:3:1 | LL | struct Foo; | ----------- previous definition of the type `Foo` here @@ -8,25 +8,6 @@ LL | trait Foo {} | = note: `Foo` must be defined only once in the type namespace of this module -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` -note: required by a bound in `Clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0746]: return type cannot have an unboxed trait object - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0782]: trait objects must include the `dyn` keyword --> $DIR/issue-106072.rs:1:10 | @@ -35,7 +16,7 @@ LL | #[derive(Clone)] | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0428, E0746, E0782. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0428, E0782. +For more information about an error, try `rustc --explain E0428`. From f1f9842adf528084c99e060dcce50fbc5ab34f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Jun 2024 05:40:44 +0000 Subject: [PATCH 04/26] Do not silence some sized errors as they would cause ICEs --- .../error_reporting/type_err_ctxt_ext.rs | 29 +++++++------------ ...g-dyn-in-qualified-path.edition2018.stderr | 14 +++++++-- .../trait-missing-dyn-in-qualified-path.rs | 1 + tests/ui/traits/bad-sized.rs | 1 + tests/ui/traits/bad-sized.stderr | 12 +++++++- 5 files changed, 35 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 62cba3fec830c..fd5ef77809e5f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -640,30 +640,21 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { if !self.tcx.object_safety_violations(trait_ref.def_id()).is_empty() { - match ( - obligation.cause.code(), - trait_ref.skip_binder().self_ty().kind(), - ) { - ( - ObligationCauseCode::WhereClauseInExpr(..), - ty::Dynamic(..), - ) => { + if let ObligationCauseCode::SizedCallReturnType(did) + = obligation.cause.code() + { + let fn_sig = self.tcx.fn_sig(did); + let ret_kind = + fn_sig.skip_binder().output().skip_binder().kind(); + if let ty::Param(param_ty) = ret_kind + && param_ty.name == kw::SelfUpper + { return err.delay_as_bug(); } - (ObligationCauseCode::SizedCallReturnType(did), _) => { - let fn_sig = self.tcx.fn_sig(did); - let ret_kind = - fn_sig.skip_binder().output().skip_binder().kind(); - if let ty::Param(param_ty) = ret_kind - && param_ty.name == kw::SelfUpper - { - return err.delay_as_bug(); - } - } - _ => {} } } } + if let ObligationCauseCode::Coercion { source, target } = *obligation.cause.code().peel_derives() { diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr index c4400ff5978c1..df5d36ca301f0 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr @@ -21,6 +21,16 @@ LL | let x: u32 = ::default(); = 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[E0277]: the size for values of type `dyn Default` cannot be known at compilation time + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 + | +LL | let x: u32 = ::default(); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Default` +note: required by a bound in `default` + --> $SRC_DIR/core/src/default.rs:LL:COL + error[E0308]: mismatched types --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 | @@ -42,7 +52,7 @@ LL | let x: u32 = ::default(); = 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 3 previous errors; 1 warning emitted +error: aborting due to 4 previous errors; 1 warning emitted -Some errors have detailed explanations: E0038, E0308. +Some errors have detailed explanations: E0038, E0277, E0308. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs index 90bfc5f5b8963..d15b17993e45f 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs @@ -9,4 +9,5 @@ fn main() { //[edition2018]~| ERROR trait `Default` cannot be made into an object //[edition2018]~| ERROR trait `Default` cannot be made into an object //[edition2018]~| ERROR mismatched types + //[edition2018]~| ERROR the size for values of type `dyn Default` cannot be known at compilation time } diff --git a/tests/ui/traits/bad-sized.rs b/tests/ui/traits/bad-sized.rs index b899c59ff2ea7..a15219679788d 100644 --- a/tests/ui/traits/bad-sized.rs +++ b/tests/ui/traits/bad-sized.rs @@ -5,4 +5,5 @@ pub fn main() { //~^ ERROR only auto traits can be used as additional traits in a trait object //~| ERROR the size for values of type //~| ERROR the size for values of type + //~| ERROR the size for values of type } diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr index 4cd7a192fca7c..4c1835dfed085 100644 --- a/tests/ui/traits/bad-sized.stderr +++ b/tests/ui/traits/bad-sized.stderr @@ -19,6 +19,16 @@ LL | let x: Vec = Vec::new(); note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/bad-sized.rs:4:37 + | +LL | let x: Vec = Vec::new(); + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Vec::::new` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:37 | @@ -29,7 +39,7 @@ LL | let x: Vec = Vec::new(); note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0225, E0277. For more information about an error, try `rustc --explain E0225`. From 5441f7187a1b49f3cc972a6abd2b39ec02794f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Jun 2024 05:50:38 +0000 Subject: [PATCH 05/26] Add more tracking for the HIR source of well-formedness requirement --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 6 +++++- compiler/rustc_hir_typeck/src/callee.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 6 +++++- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 18 +++++++++++++----- .../rustc_hir_typeck/src/method/confirm.rs | 8 +++++++- compiler/rustc_middle/src/traits/mod.rs | 2 ++ .../error_reporting/type_err_ctxt_ext.rs | 8 +++++++- .../consts/const_refs_to_static-ice-121413.rs | 2 ++ .../const_refs_to_static-ice-121413.stderr | 16 +++++++++++++++- 10 files changed, 58 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b206d8046ee9c..22d95611c9bf5 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1270,7 +1270,7 @@ fn check_item_type( traits::ObligationCause::new( ty_span, wfcx.body_def_id, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id))), ), wfcx.param_env, item_ty, diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 13993a1992b7c..39c7e7d17e802 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -25,6 +25,7 @@ fn diagnostic_hir_wf_check<'tcx>( let def_id = match loc { WellFormedLoc::Ty(def_id) => def_id, WellFormedLoc::Param { function, param_idx: _ } => function, + WellFormedLoc::Expr(_) => return None, }; let hir_id = tcx.local_def_id_to_hir_id(def_id); @@ -79,7 +80,9 @@ fn diagnostic_hir_wf_check<'tcx>( let cause = traits::ObligationCause::new( ty.span, self.def_id, - traits::ObligationCauseCode::WellFormed(None), + traits::ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr( + ty.hir_id, + ))), ); ocx.register_obligation(traits::Obligation::new( @@ -191,6 +194,7 @@ fn diagnostic_hir_wf_check<'tcx>( vec![&fn_decl.inputs[param_idx as usize]] } } + WellFormedLoc::Expr(_) => return None, }; for ty in tys { visitor.visit_ty(ty); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 9736c8b89204e..995f5f26374b2 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_wf_obligation( output.into(), call_expr.span, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr(call_expr.hir_id))), ); output diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 5b8689a73176d..6f82fc8aefb7b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1517,7 +1517,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = Ty::new_array_with_const_len(tcx, t, count); - self.register_wf_obligation(ty.into(), expr.span, ObligationCauseCode::WellFormed(None)); + self.register_wf_obligation( + ty.into(), + expr.span, + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr(expr.hir_id))), + ); ty } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 85c6d4dc12c55..15f93b093710b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -405,7 +405,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> LoweredTy<'tcx> { let ty = self.lowerer().lower_ty(hir_ty); - self.register_wf_obligation(ty.into(), hir_ty.span, ObligationCauseCode::WellFormed(None)); + self.register_wf_obligation( + ty.into(), + hir_ty.span, + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr(hir_ty.hir_id))), + ); LoweredTy::from_raw(self, hir_ty.span, ty) } @@ -516,7 +520,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for arg in args.iter().filter(|arg| { matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) }) { - self.register_wf_obligation(arg, expr.span, ObligationCauseCode::WellFormed(None)); + self.register_wf_obligation( + arg, + expr.span, + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr(expr.hir_id))), + ); } } @@ -770,7 +778,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_wf_obligation( ty.raw.into(), qself.span, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr(hir_id))), ); // Return directly on cache hit. This is useful to avoid doubly reporting // errors with default match binding modes. See #44614. @@ -810,7 +818,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_wf_obligation( ty.raw.into(), qself.span, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr(hir_id))), ); } @@ -844,7 +852,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_wf_obligation( ty.raw.into(), qself.span, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr(hir_id))), ); } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 3c9a49e91a3f9..75556840236cd 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -583,7 +583,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // the function type must also be well-formed (this is not // implied by the args being well-formed because of inherent // impls and late-bound regions - see issue #28609). - self.register_wf_obligation(fty.into(), self.span, ObligationCauseCode::WellFormed(None)); + self.register_wf_obligation( + fty.into(), + self.span, + ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Expr( + self.call_expr.hir_id, + ))), + ); } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 74328ee32a10c..1f75c71d2a52f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -486,6 +486,8 @@ pub enum WellFormedLoc { /// being the last 'parameter' param_idx: usize, }, + /// The HIR node for the expression that introduced this obligation. + Expr(HirId), } #[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index fd5ef77809e5f..a4c0a312fb0a6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -870,8 +870,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::ObjectSafe(trait_def_id) => { + let mut hir_id = None; + if let ObligationCauseCode::WellFormed(Some( + crate::traits::WellFormedLoc::Expr(id), + )) = root_obligation.cause.code() { + hir_id = Some(*id); + } let violations = self.tcx.object_safety_violations(trait_def_id); - report_object_safety_error(self.tcx, span, None, trait_def_id, violations) + report_object_safety_error(self.tcx, span, hir_id, trait_def_id, violations) } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => { diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.rs b/tests/ui/consts/const_refs_to_static-ice-121413.rs index 8a24fb799b6b8..c95be778272c9 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.rs +++ b/tests/ui/consts/const_refs_to_static-ice-121413.rs @@ -8,9 +8,11 @@ const REF_INTERIOR_MUT: &usize = { static FOO: Sync = AtomicUsize::new(0); //~^ ERROR failed to resolve: use of undeclared type `AtomicUsize` //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN trait objects without an explicit `dyn` are deprecated //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! unsafe { &*(&FOO as *const _ as *const usize) } }; pub fn main() {} diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr index c977c698a92e9..e41f352282a88 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr @@ -23,6 +23,20 @@ help: if this is an object-safe trait, use `dyn` LL | static FOO: dyn Sync = AtomicUsize::new(0); | +++ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/const_refs_to_static-ice-121413.rs:8:17 + | +LL | static FOO: Sync = AtomicUsize::new(0); + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: if this is an object-safe trait, use `dyn` + | +LL | static FOO: dyn Sync = AtomicUsize::new(0); + | +++ + error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time --> $DIR/const_refs_to_static-ice-121413.rs:8:17 | @@ -40,7 +54,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` = note: constant expressions must have a statically known size -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 2 warnings emitted Some errors have detailed explanations: E0277, E0433. For more information about an error, try `rustc --explain E0277`. From 9a8f3439b70f4d72be645a1727c8bf3e8f2e887c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Jun 2024 05:56:54 +0000 Subject: [PATCH 06/26] Add tests for various `dyn Trait` in path cases --- ...ype-in-qualified-path-for-with-one-impl.rs | 10 +++ ...in-qualified-path-for-with-one-impl.stderr | 17 +++++ ...-for-object-safe-function-with-one-impl.rs | 9 +++ ...-object-safe-function-with-one-impl.stderr | 26 ++++++++ ...qualified-path-for-object-safe-function.rs | 14 ++++ ...-qualified-path-for-object-unsafe-trait.rs | 13 ++++ ...lified-path-for-object-unsafe-trait.stderr | 64 +++++++++++++++++++ ...it-dyn-in-qualified-path-with-collision.rs | 11 ++++ ...yn-in-qualified-path-with-collision.stderr | 22 +++++++ .../trait-dyn-in-qualified-path.rs | 8 +++ .../trait-dyn-in-qualified-path.stderr | 33 ++++++++++ 11 files changed, 227 insertions(+) create mode 100644 tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.rs create mode 100644 tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.stderr create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.rs create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function.rs create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.rs create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path.rs create mode 100644 tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr diff --git a/tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.rs b/tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.rs new file mode 100644 index 0000000000000..c1487e816955c --- /dev/null +++ b/tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.rs @@ -0,0 +1,10 @@ +trait Trait { + fn function() {} +} + +impl Trait for () {} + +fn main() { + Trait::function(); + //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type +} diff --git a/tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.stderr b/tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.stderr new file mode 100644 index 0000000000000..84f144d191e45 --- /dev/null +++ b/tests/ui/dyn-keyword/inferred-type-in-qualified-path-for-with-one-impl.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/inferred-type-in-qualified-path-for-with-one-impl.rs:8:5 + | +LL | fn function() {} + | ---------------- `Trait::function` defined here +... +LL | Trait::function(); + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | <() as Trait>::function(); + | ++++++ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.rs b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.rs new file mode 100644 index 0000000000000..36697d7225e43 --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.rs @@ -0,0 +1,9 @@ +trait Trait { + fn function() {} +} + +impl Trait for () {} + +fn main() { + ::function(); //~ ERROR the trait `Trait` cannot be made into an object +} diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr new file mode 100644 index 0000000000000..20aa02b06942f --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr @@ -0,0 +1,26 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.rs:8:6 + | +LL | ::function(); + | ^^^^^^^^^ `Trait` 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/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.rs:2:8 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | fn function() {} + | ^^^^^^^^ ...because associated function `function` has no `self` parameter + = help: only type `()` implements the trait, consider using it directly instead +help: consider turning `function` into a method by giving it a `&self` argument + | +LL | fn function(&self) {} + | +++++ +help: alternatively, consider constraining `function` so it does not apply to trait objects + | +LL | fn function() where Self: Sized {} + | +++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function.rs b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function.rs new file mode 100644 index 0000000000000..fe2c28672eb91 --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function.rs @@ -0,0 +1,14 @@ +//@ run-pass + +trait Trait { + fn function(&self) {} +} + +impl dyn Trait { +} + +impl Trait for () {} + +fn main() { + Trait::function(&()); +} diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs new file mode 100644 index 0000000000000..9dccc4c26d7fd --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs @@ -0,0 +1,13 @@ +trait Trait: Sized {} + +impl dyn Trait { //~ ERROR the trait `Trait` cannot be made into an object + fn function(&self) {} //~ ERROR the trait `Trait` cannot be made into an object +} + +impl Trait for () {} + +fn main() { + ::function(&()); + //~^ ERROR the trait `Trait` cannot be made into an object + //~| ERROR the trait `Trait` cannot be made into an object +} diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr new file mode 100644 index 0000000000000..6a5b3915d76af --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr @@ -0,0 +1,64 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:3:6 + | +LL | impl dyn Trait { + | ^^^^^^^^^ `Trait` 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/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:1:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = help: only type `()` implements the trait, consider using it directly instead + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:4:18 + | +LL | fn function(&self) {} + | ^^^^ `Trait` 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/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:1:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = help: only type `()` implements the trait, consider using it directly instead + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:10:27 + | +LL | ::function(&()); + | ^^^ `Trait` 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/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:1:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | 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 Trait + 'static)` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:10:6 + | +LL | ::function(&()); + | ^^^^^^^^^ `Trait` 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/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:1:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = help: only type `()` implements the trait, consider using it directly instead + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.rs b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.rs new file mode 100644 index 0000000000000..bb9f3a09d55ec --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.rs @@ -0,0 +1,11 @@ +trait Trait { + fn function(&self) {} +} +impl dyn Trait { + fn function(&self) {} +} +impl Trait for () {} +fn main() { + ::function(&()); + //~^ ERROR multiple applicable items in scope +} diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr new file mode 100644 index 0000000000000..07107c78fc4ce --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr @@ -0,0 +1,22 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/trait-dyn-in-qualified-path-with-collision.rs:9:18 + | +LL | ::function(&()); + | -------------^^^^^^^^ multiple `function` found + | | + | help: use fully-qualified syntax to disambiguate: `Trait::` + | +note: candidate #1 is defined in the trait `Trait` + --> $DIR/trait-dyn-in-qualified-path-with-collision.rs:2:5 + | +LL | fn function(&self) {} + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `(dyn Trait + 'static)` + --> $DIR/trait-dyn-in-qualified-path-with-collision.rs:5:5 + | +LL | fn function(&self) {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.rs b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.rs new file mode 100644 index 0000000000000..8f9d587de26ed --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.rs @@ -0,0 +1,8 @@ +trait Trait: Sized { + fn function() {} +} +fn main() { + ::function(); + //~^ ERROR trait `Trait` cannot be made into an object + //~| ERROR the size for values of type `dyn Trait` cannot be known at compilation time +} diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr new file mode 100644 index 0000000000000..9cb3b11f10cfb --- /dev/null +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/trait-dyn-in-qualified-path.rs:5:6 + | +LL | ::function(); + | ^^^^^^^^^ `Trait` 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/trait-dyn-in-qualified-path.rs:1:14 + | +LL | trait Trait: Sized { + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/trait-dyn-in-qualified-path.rs:5:6 + | +LL | ::function(); + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Trait::function` + --> $DIR/trait-dyn-in-qualified-path.rs:1:14 + | +LL | trait Trait: Sized { + | ^^^^^ required by this bound in `Trait::function` +LL | fn function() {} + | -------- required by a bound in this associated function + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. From 9ada8bcdcf924af0eea33f08f29bcb89a82b8d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Jun 2024 05:59:34 +0000 Subject: [PATCH 07/26] Add more HIR tracking information to `ObligationCauseCode` This data will help with extending E0038 object safety errors. --- compiler/rustc_hir_typeck/src/coercion.rs | 19 +++++++++---------- compiler/rustc_middle/src/traits/mod.rs | 4 +++- .../src/traits/error_reporting/suggestions.rs | 4 ++-- .../error_reporting/type_err_ctxt_ext.rs | 2 +- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index dbaa6e398c886..16f5fe9611507 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -487,7 +487,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceResult<'tcx> { source = self.shallow_resolve(source); target = self.shallow_resolve(target); - debug!(?source, ?target); + debug!(?source, ?target, ?self.cause); // We don't apply any coercions incase either the source or target // aren't sufficiently well known but tend to instead just equate @@ -565,11 +565,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mut selcx = traits::SelectionContext::new(self); // Create an obligation for `Source: CoerceUnsized`. - let cause = ObligationCause::new( - self.cause.span, - self.body_id, - ObligationCauseCode::Coercion { source, target }, - ); + let mut cause = + ObligationCause::new(self.cause.span, self.body_id, self.cause.code().clone()); + cause.map_code(|parent_code| ObligationCauseCode::Coercion { source, target, parent_code }); // Use a FIFO queue for this custom fulfillment procedure. // @@ -993,8 +991,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); - let cause = - cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable)); + let cause = cause.unwrap_or_else(|| { + self.cause(expr.span, ObligationCauseCode::ExprAssignable(Some(expr.hir_id))) + }); let coerce = Coerce::new(self, cause, allow_two_phase); let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?; @@ -1016,7 +1015,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let source = self.resolve_vars_with_obligations(expr_ty); debug!("coercion::can_with_predicates({:?} -> {:?})", source, target); - let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); + let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable(None)); // We don't ever need two-phase here since we throw out the result of the coercion let coerce = Coerce::new(self, cause, AllowTwoPhase::No); self.probe(|_| { @@ -1033,7 +1032,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// how many dereference steps needed to achieve `expr_ty <: target`. If /// it's not possible, return `None`. pub fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option { - let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); + let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable(None)); // We don't ever need two-phase here since we throw out the result of the coercion let coerce = Coerce::new(self, cause, AllowTwoPhase::No); coerce diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 1f75c71d2a52f..9c7131e92887a 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -268,6 +268,8 @@ pub enum ObligationCauseCode<'tcx> { Coercion { source: Ty<'tcx>, target: Ty<'tcx>, + /// The obligation introduced by this argument. + parent_code: InternedObligationCauseCode<'tcx>, }, /// Various cases where expressions must be `Sized` / `Copy` / etc. @@ -355,7 +357,7 @@ pub enum ObligationCauseCode<'tcx> { }, /// Checking that this expression can be assigned to its target. - ExprAssignable, + ExprAssignable(Option), /// Computing common supertype in the arms of a match expression MatchExpressionArm(Box>), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 0af557b6b9f4e..cc9cc39cf8517 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2707,7 +2707,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let tcx = self.tcx; let predicate = predicate.upcast(tcx); match *cause_code { - ObligationCauseCode::ExprAssignable + ObligationCauseCode::ExprAssignable(_) | ObligationCauseCode::MatchExpressionArm { .. } | ObligationCauseCode::Pattern { .. } | ObligationCauseCode::IfExpression { .. } @@ -2886,7 +2886,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // We hold the `DefId` of the item introducing the obligation, but displaying it // doesn't add user usable information. It always point at an associated item. } - ObligationCauseCode::Coercion { source, target } => { + ObligationCauseCode::Coercion { source, target, .. } => { let source = tcx.short_ty_string(self.resolve_vars_if_possible(source), &mut long_ty_file); let target = diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index a4c0a312fb0a6..7f39f9c9e05a2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -655,7 +655,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - if let ObligationCauseCode::Coercion { source, target } = + if let ObligationCauseCode::Coercion { source, target, .. } = *obligation.cause.code().peel_derives() { if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { From 5d85ffa89f58d69f11b680e2edbe0b049ba3bad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Jun 2024 06:08:23 +0000 Subject: [PATCH 08/26] On object safety errors, point at specific object unsafe trait in path We use the new HIR node tracking for well-formedness obligations to point at the specific trait object in a path/type (`dyn T` instead of a whole `Box`, for example). ``` error[E0038]: the trait `MapLike` cannot be made into an object --> $DIR/file.rs:47:16 | LL | as Box; | ^^^^^^^^^ `Trait` cannot be made into an object ``` We also provide a structured suggestion for `::assoc`: ``` = help: when writing `::function` you are requiring `Trait` be "object safe", which it isn't help: you might have meant to access the associated function of a specific `impl` to avoid requiring "object safety" from `Trait`, either with some explicit type... | LL | ::function(); | ~~~~~~~~~~~~~ help: ...or rely on inference if the compiler has enough context to identify the desired type on its own... | LL - ::function(); LL + Trait::function(); | help: ...which is equivalent to | LL | <_ as Trait>::function(); | ~~~~ ``` --- Cargo.lock | 1 + compiler/rustc_infer/Cargo.toml | 1 + .../src/traits/error_reporting/mod.rs | 204 ++++++++++++++++-- .../async-await/in-trait/object-safety.stderr | 4 +- ...reference-without-parens-suggestion.stderr | 4 +- ...-object-safe-function-with-one-impl.stderr | 6 +- ...lified-path-for-object-unsafe-trait.stderr | 6 +- .../trait-dyn-in-qualified-path.stderr | 14 ++ ...g-dyn-in-qualified-path.edition2018.stderr | 23 +- ...gate-dispatch-from-dyn-missing-impl.stderr | 4 +- .../issue-76535.base.stderr | 4 +- .../issue-78671.base.stderr | 4 +- .../issue-79422.base.stderr | 4 +- .../trait-bounds/span-bug-issue-121597.stderr | 4 +- .../in-trait/foreign-dyn-error.stderr | 4 +- .../impl-trait/in-trait/object-safety.stderr | 4 +- tests/ui/issues/issue-18959.stderr | 4 +- .../kindck-inherited-copy-bound.curr.stderr | 4 +- tests/ui/object-safety/issue-19538.stderr | 4 +- .../object-safety-generics.curr.stderr | 4 +- .../object-safety-no-static.curr.stderr | 4 +- ...ary-self-types-not-object-safe.curr.stderr | 4 +- tests/ui/traits/issue-20692.stderr | 4 +- tests/ui/traits/issue-38604.stderr | 4 +- tests/ui/traits/item-privacy.stderr | 6 +- .../supertrait-object-safety.stderr | 4 +- ...alize-fresh-infer-vars-issue-103626.stderr | 4 +- tests/ui/traits/object/safety.stderr | 4 +- tests/ui/traits/test-2.stderr | 9 +- tests/ui/wf/wf-object-safe.stderr | 4 +- 30 files changed, 283 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54b1bf593e0a2..d6d06b6d0a21e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4200,6 +4200,7 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ + "rustc_ast", "rustc_ast_ir", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 5136ab79a0f84..0842fde15ff26 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 890e25368bc75..843f92132620c 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -1,10 +1,12 @@ use super::ObjectSafetyViolation; use crate::infer::InferCtxt; +use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::Visitor; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; @@ -39,6 +41,23 @@ impl<'tcx> InferCtxt<'tcx> { } } +struct TraitObjectFinder<'tcx> { + trait_def_id: DefId, + result: Vec<&'tcx hir::Ty<'tcx>>, +} + +impl<'v> Visitor<'v> for TraitObjectFinder<'v> { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + if let hir::TyKind::TraitObject(traits, _, _) = ty.kind + && traits.iter().any(|t| t.trait_ref.trait_def_id() == Some(self.trait_def_id)) + { + self.result.push(ty); + } + hir::intravisit::walk_ty(self, ty); + } +} + +#[tracing::instrument(level = "debug", skip(tcx))] pub fn report_object_safety_error<'tcx>( tcx: TyCtxt<'tcx>, span: Span, @@ -51,33 +70,79 @@ pub fn report_object_safety_error<'tcx>( hir::Node::Item(item) => Some(item.ident.span), _ => None, }); + let mut visitor = TraitObjectFinder { trait_def_id, result: vec![] }; + if let Some(hir_id) = hir_id { + match tcx.hir_node(hir_id) { + hir::Node::Expr(expr) => { + visitor.visit_expr(&expr); + if visitor.result.is_empty() { + match tcx.parent_hir_node(hir_id) { + hir::Node::Expr(expr) if let hir::ExprKind::Cast(_, ty) = expr.kind => { + // Special case for ` as `, as we're given the `expr` instead + // of the whole cast expression. This will let us point at `dyn Trait` + // instead of `x` in `x as Box`. + visitor.visit_ty(ty); + } + hir::Node::LetStmt(stmt) if let Some(ty) = stmt.ty => { + // Special case for `let : = ;`, as we're given the + // `expr` instead of the whole cast expression. This will let us point + // at `dyn Trait` instead of `x` in `let y: Box = x;`. + visitor.visit_ty(ty); + } + _ => {} + } + } + } + hir::Node::Ty(ty) => { + visitor.visit_ty(&ty); + } + _ => {} + } + } + let mut label_span = span; + let mut dyn_trait_spans = vec![]; + let mut trait_spans = vec![]; + let spans: MultiSpan = if visitor.result.is_empty() { + span.into() + } else { + for ty in &visitor.result { + let hir::TyKind::TraitObject(traits, ..) = ty.kind else { continue }; + dyn_trait_spans.push(ty.span); + trait_spans.extend( + traits + .iter() + .filter(|t| t.trait_ref.trait_def_id() == Some(trait_def_id)) + .map(|t| t.trait_ref.path.span), + ); + } + match (&dyn_trait_spans[..], &trait_spans[..]) { + ([], []) => span.into(), + ([only], [_]) => { + // There is a single `dyn Trait` for the expression or type that was stored in the + // `WellFormedLoc`. We point at the whole `dyn Trait`. + label_span = *only; + (*only).into() + } + (_, [.., last]) => { + // There are more than one trait in `dyn A + A` in the expression or type that was + // stored in the `WellFormedLoc` that points at the relevant trait, or there are + // more than one `dyn A`. We apply the primary span label to the last one of these. + label_span = *last; + trait_spans.into() + } + // Should be unreachable, as if one is empty, the other must be too. + _ => span.into(), + } + }; let mut err = struct_span_code_err!( tcx.dcx(), - span, + spans, E0038, "the trait `{}` cannot be made into an object", trait_str ); - err.span_label(span, format!("`{trait_str}` cannot be made into an object")); + err.span_label(label_span, format!("`{trait_str}` cannot be made into an object")); - if let Some(hir_id) = hir_id - && let hir::Node::Ty(ty) = tcx.hir_node(hir_id) - && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind - { - let mut hir_id = hir_id; - while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) { - hir_id = ty.hir_id; - } - if tcx.parent_hir_node(hir_id).fn_sig().is_some() { - // Do not suggest `impl Trait` when dealing with things like super-traits. - err.span_suggestion_verbose( - ty.span.until(trait_ref.span), - "consider using an opaque type instead", - "impl ", - Applicability::MaybeIncorrect, - ); - } - } let mut reported_violations = FxIndexSet::default(); let mut multi_span = vec![]; let mut messages = vec![]; @@ -160,7 +225,106 @@ pub fn report_object_safety_error<'tcx>( } else { false }; + let mut has_suggested = false; + if let Some(hir_id) = hir_id { + let node = tcx.hir_node(hir_id); + if let hir::Node::Ty(ty) = node + && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind + { + let mut hir_id = hir_id; + while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) { + hir_id = ty.hir_id; + } + if tcx.parent_hir_node(hir_id).fn_sig().is_some() { + // Do not suggest `impl Trait` when dealing with things like super-traits. + err.span_suggestion_verbose( + ty.span.until(trait_ref.span), + "consider using an opaque type instead", + "impl ", + Applicability::MaybeIncorrect, + ); + has_suggested = true; + } + } + if let hir::Node::Expr(expr) = node + && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, path_segment)) = expr.kind + && let hir::TyKind::TraitObject([trait_ref, ..], _, trait_object_syntax) = ty.kind + { + if let TraitObjectSyntax::None = trait_object_syntax + && !expr.span.edition().at_least_rust_2021() + { + err.span_note( + trait_ref.trait_ref.path.span, + format!( + "`{trait_str}` is the type for the trait in editions 2015 and 2018 and is \ + equivalent to writing `dyn {trait_str}`", + ), + ); + } + let segment = path_segment.ident; + err.help(format!( + "when writing `::{segment}` you are requiring `{trait_str}` be \ + \"object safe\", which it isn't", + )); + let (only, msg, sugg, appl) = if let [only] = &impls[..] { + // We know there's a single implementation for this trait, so we can be explicit on + // the type they should have used. + let ty = tcx.type_of(*only).instantiate_identity(); + ( + true, + format!( + "specify the specific `impl` for type `{ty}` to avoid requiring \"object \ + safety\" from `{trait_str}`", + ), + with_no_trimmed_paths!(format!("{ty} as ")), + Applicability::MachineApplicable, + ) + } else { + ( + false, + format!( + "you might have meant to access the associated function of a specific \ + `impl` to avoid requiring \"object safety\" from `{trait_str}`, either \ + with some explicit type...", + ), + "/* Type */ as ".to_string(), + Applicability::HasPlaceholders, + ) + }; + // `::segment()` or `::segment()` to `::segment()` + let sp = ty.span.until(trait_ref.trait_ref.path.span); + err.span_suggestion_verbose(sp, msg, sugg, appl); + if !only { + // `::segment()` or `::segment()` to `Trait::segment()` + err.multipart_suggestion_verbose( + "...or rely on inference if the compiler has enough context to identify the \ + desired type on its own...", + vec![ + (expr.span.until(trait_ref.trait_ref.path.span), String::new()), + ( + path_segment + .ident + .span + .shrink_to_lo() + .with_lo(trait_ref.trait_ref.path.span.hi()), + "::".to_string(), + ), + ], + Applicability::MaybeIncorrect, + ); + // `::segment()` or `::segment()` to `<_ as Trait>::segment()` + err.span_suggestion_verbose( + ty.span.until(trait_ref.trait_ref.path.span), + "...which is equivalent to", + format!("_ as "), + Applicability::MaybeIncorrect, + ); + } + has_suggested = true; + } + } match &impls[..] { + _ if has_suggested => {} [] => {} _ if impls.len() > 9 => {} [only] if externally_visible => { diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/object-safety.stderr index f45e6a2c8bb51..9651252080ad8 100644 --- a/tests/ui/async-await/in-trait/object-safety.stderr +++ b/tests/ui/async-await/in-trait/object-safety.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:9:12 + --> $DIR/object-safety.rs:9:13 | LL | let x: &dyn Foo = todo!(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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-safety.rs:5:14 diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 68734cd4ccd6b..abf57b49feb6e 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -11,10 +11,10 @@ LL | let _: &'static Copy + 'static; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'static (Copy + 'static)` error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12 + --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:13 | LL | let _: &Copy + 'static; - | ^^^^^ `Copy` cannot be made into an object + | ^^^^ `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 diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr index 20aa02b06942f..7b7a6d119fd19 100644 --- a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-safe-function-with-one-impl.stderr @@ -11,7 +11,7 @@ LL | trait Trait { | ----- this trait cannot be made into an object... LL | fn function() {} | ^^^^^^^^ ...because associated function `function` has no `self` parameter - = help: only type `()` implements the trait, consider using it directly instead + = help: when writing `::function` you are requiring `Trait` be "object safe", which it isn't help: consider turning `function` into a method by giving it a `&self` argument | LL | fn function(&self) {} @@ -20,6 +20,10 @@ help: alternatively, consider constraining `function` so it does not apply to tr | LL | fn function() where Self: Sized {} | +++++++++++++++++ +help: specify the specific `impl` for type `()` to avoid requiring "object safety" from `Trait` + | +LL | <() as Trait>::function(); + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr index 6a5b3915d76af..6f12e3f780c56 100644 --- a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr @@ -57,7 +57,11 @@ LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... - = help: only type `()` implements the trait, consider using it directly instead + = help: when writing `::function` you are requiring `Trait` be "object safe", which it isn't +help: specify the specific `impl` for type `()` to avoid requiring "object safety" from `Trait` + | +LL | <() as Trait>::function(&()); + | ~~~~~ error: aborting due to 4 previous errors diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr index 9cb3b11f10cfb..02d148473d15a 100644 --- a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path.stderr @@ -11,6 +11,20 @@ LL | trait Trait: Sized { | ----- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... + = help: when writing `::function` you are requiring `Trait` be "object safe", which it isn't +help: you might have meant to access the associated function of a specific `impl` to avoid requiring "object safety" from `Trait`, either with some explicit type... + | +LL | ::function(); + | ~~~~~~~~~~~~~ +help: ...or rely on inference if the compiler has enough context to identify the desired type on its own... + | +LL - ::function(); +LL + Trait::function(); + | +help: ...which is equivalent to + | +LL | <_ as Trait>::function(); + | ~~~~ error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/trait-dyn-in-qualified-path.rs:5:6 diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr index df5d36ca301f0..c5a0bb2fda36c 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr @@ -20,6 +20,25 @@ LL | let x: u32 = ::default(); | = 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 +note: `Default` is the type for the trait in editions 2015 and 2018 and is equivalent to writing `dyn Default` + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 + | +LL | let x: u32 = ::default(); + | ^^^^^^^ + = help: when writing `::default` you are requiring `Default` be "object safe", which it isn't +help: you might have meant to access the associated function of a specific `impl` to avoid requiring "object safety" from `Default`, either with some explicit type... + | +LL | let x: u32 = ::default(); + | +++++++++++++ +help: ...or rely on inference if the compiler has enough context to identify the desired type on its own... + | +LL - let x: u32 = ::default(); +LL + let x: u32 = Default::default(); + | +help: ...which is equivalent to + | +LL | let x: u32 = <_ as Default>::default(); + | ++++ error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 @@ -44,10 +63,10 @@ LL | let x: u32 = ::default(); = help: `u32` implements `Default` so you could change the expected type to `Box` error[E0038]: the trait `Default` cannot be made into an object - --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 | LL | let x: u32 = ::default(); - | ^^^^^^^^^^^^^^^^^^^^ `Default` cannot be made into an object + | ^^^^^^^ `Default` 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 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 00b8c0eef989a..faa369e79e18d 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 @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:25 + --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:29 | LL | fn ptr(self: Ptr); | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` ... LL | Ptr(Box::new(4)) as Ptr; - | ^^^^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` 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/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr index bb14e297174a6..fd23f5d3ab046 100644 --- a/tests/ui/generic-associated-types/issue-76535.base.stderr +++ b/tests/ui/generic-associated-types/issue-76535.base.stderr @@ -15,10 +15,10 @@ LL | let sub: Box = SubStruct>> = Box::new(SuperS | ++++ error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/issue-76535.rs:39:14 + --> $DIR/issue-76535.rs:39:18 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` 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/issue-76535.rs:9:10 diff --git a/tests/ui/generic-associated-types/issue-78671.base.stderr b/tests/ui/generic-associated-types/issue-78671.base.stderr index bad8c1c9dba7b..b4ee0093b9641 100644 --- a/tests/ui/generic-associated-types/issue-78671.base.stderr +++ b/tests/ui/generic-associated-types/issue-78671.base.stderr @@ -15,10 +15,10 @@ LL | Box::new(Family) as &dyn CollectionFamily=usize> | +++ error[E0038]: the trait `CollectionFamily` cannot be made into an object - --> $DIR/issue-78671.rs:10:25 + --> $DIR/issue-78671.rs:10:26 | LL | Box::new(Family) as &dyn CollectionFamily - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` 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/issue-78671.rs:7:10 diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr index 7f58f82570220..0667ce62c4d9a 100644 --- a/tests/ui/generic-associated-types/issue-79422.base.stderr +++ b/tests/ui/generic-associated-types/issue-79422.base.stderr @@ -15,10 +15,10 @@ LL | as Box = dyn RefCont<'_, u8>>>; | ++++ error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:47:12 + --> $DIR/issue-79422.rs:47:16 | LL | as Box>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` 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/issue-79422.rs:23:10 diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr index 27f82563aae7d..8eefd6fa0a547 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr @@ -14,10 +14,10 @@ LL | trait Foo: for Bar {} = note: required for the cast from `&()` to `&dyn Foo` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/span-bug-issue-121597.rs:14:12 + --> $DIR/span-bug-issue-121597.rs:14:13 | LL | let x: &dyn Foo = &(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/span-bug-issue-121597.rs:4:12 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 9cc4c4b2f9e53..5ef5018dd4e5d 100644 --- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/foreign-dyn-error.rs:6:12 + --> $DIR/foreign-dyn-error.rs:6:13 | LL | let _: &dyn rpitit::Foo = todo!(); - | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^ `Foo` 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/auxiliary/rpitit.rs:6:21 diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr index a7be0516cd32b..7cd27f736eb2a 100644 --- a/tests/ui/impl-trait/in-trait/object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/object-safety.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:14:33 + --> $DIR/object-safety.rs:14:37 | LL | let i = Box::new(42_u32) as Box; - | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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-safety.rs:4:22 diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr index 83d46f0331ca7..228760d6664b6 100644 --- a/tests/ui/issues/issue-18959.stderr +++ b/tests/ui/issues/issue-18959.stderr @@ -29,10 +29,10 @@ LL | pub trait Bar: Foo { } = help: consider moving `foo` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-18959.rs:19:15 + --> $DIR/issue-18959.rs:19:16 | LL | let test: &dyn Bar = &mut thing; - | ^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` 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/issue-18959.rs:1:20 diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr index 979525ff40735..e4b892a24be8d 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -20,10 +20,10 @@ LL | fn take_param(foo: &T) { } | ^^^ required by this bound in `take_param` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:19 + --> $DIR/kindck-inherited-copy-bound.rs:28:20 | LL | let z = &x as &dyn Foo; - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/kindck-inherited-copy-bound.rs:10:13 diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/object-safety/issue-19538.stderr index 31657501e2586..8c615a6df6487 100644 --- a/tests/ui/object-safety/issue-19538.stderr +++ b/tests/ui/object-safety/issue-19538.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-19538.rs:17:15 + --> $DIR/issue-19538.rs:17:20 | LL | let test: &mut dyn Bar = &mut thing; - | ^^^^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` 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/issue-19538.rs:2:8 diff --git a/tests/ui/object-safety/object-safety-generics.curr.stderr b/tests/ui/object-safety/object-safety-generics.curr.stderr index 85adeace3c7f0..b5f0b01e035d4 100644 --- a/tests/ui/object-safety/object-safety-generics.curr.stderr +++ b/tests/ui/object-safety/object-safety-generics.curr.stderr @@ -45,10 +45,10 @@ LL | fn bar(&self, t: T); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:10 + --> $DIR/object-safety-generics.rs:27:11 | LL | t as &dyn Bar - | ^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` 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-safety-generics.rs:10:8 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 8e5b0cbf9ddcb..32518881f7c27 100644 --- a/tests/ui/object-safety/object-safety-no-static.curr.stderr +++ b/tests/ui/object-safety/object-safety-no-static.curr.stderr @@ -22,10 +22,10 @@ LL | fn foo() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:12 + --> $DIR/object-safety-no-static.rs:22:16 | LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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-safety-no-static.rs:9:8 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 fdd18c6b37b5c..7b380e7f8cd90 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 @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:32 + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:35 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc; - | ^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/arbitrary-self-types-not-object-safe.rs:8:18 diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr index 30e3c9da1a03e..eaf704d83991c 100644 --- a/tests/ui/traits/issue-20692.stderr +++ b/tests/ui/traits/issue-20692.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Array` cannot be made into an object - --> $DIR/issue-20692.rs:7:5 + --> $DIR/issue-20692.rs:7:6 | LL | &dyn Array; - | ^^^^^^^^^^ `Array` cannot be made into an object + | ^^^^^^^^^ `Array` 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/issue-20692.rs:1:14 diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr index 3ab9af21bc457..2c2976d9a1300 100644 --- a/tests/ui/traits/issue-38604.stderr +++ b/tests/ui/traits/issue-38604.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/issue-38604.rs:14:13 + --> $DIR/issue-38604.rs:14:17 | LL | let _f: Box = - | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/issue-38604.rs:2:22 diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index 50b561dfd165d..ade1fb139a394 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -167,7 +167,11 @@ 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 + = help: when writing `::A` you are requiring `assoc_const::C` be "object safe", which it isn't +help: specify the specific `impl` for type `S` to avoid requiring "object safety" from `assoc_const::C` + | +LL | ::A; + | ~~~~ 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 b6e540c5ffcb0..6025591b52a74 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr @@ -24,10 +24,10 @@ LL | trait Foo: for Bar {} = note: required for the cast from `&()` to `&dyn Foo` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:12 + --> $DIR/supertrait-object-safety.rs:19:13 | LL | let x: &dyn Foo = &(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/supertrait-object-safety.rs:4:12 diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index d5e9b1be63b0b..88dad77e359f6 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -7,10 +7,10 @@ LL | let b: &dyn FromResidual = &(); = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause error[E0038]: the trait `FromResidual` cannot be made into an object - --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12 + --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:13 | LL | let b: &dyn FromResidual = &(); - | ^^^^^^^^^^^^^^^^^ `FromResidual` cannot be made into an object + | ^^^^^^^^^^^^^^^^ `FromResidual` 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/canonicalize-fresh-infer-vars-issue-103626.rs:2:8 diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr index 19a46a502c2e7..a31cb9655f3d3 100644 --- a/tests/ui/traits/object/safety.stderr +++ b/tests/ui/traits/object/safety.stderr @@ -23,10 +23,10 @@ LL | fn foo() where Self: Sized; | +++++++++++++++++ error[E0038]: the trait `Tr` cannot be made into an object - --> $DIR/safety.rs:15:12 + --> $DIR/safety.rs:15:13 | LL | let _: &dyn Tr = &St; - | ^^^^^^^ `Tr` cannot be made into an object + | ^^^^^^ `Tr` 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/safety.rs:4:8 diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr index 3972e539776c4..cb03a8a8a2474 100644 --- a/tests/ui/traits/test-2.stderr +++ b/tests/ui/traits/test-2.stderr @@ -27,10 +27,10 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | ^^^^ - error[E0038]: the trait `bar` cannot be made into an object - --> $DIR/test-2.rs:13:22 + --> $DIR/test-2.rs:13:26 | LL | (Box::new(10) as Box).dup(); - | ^^^^^^^^^^^^ `bar` cannot be made into an object + | ^^^^^^^ `bar` 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/test-2.rs:4:30 @@ -47,10 +47,10 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } u32 error[E0038]: the trait `bar` cannot be made into an object - --> $DIR/test-2.rs:13:5 + --> $DIR/test-2.rs:13:26 | LL | (Box::new(10) as Box).dup(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` cannot be made into an object + | ^^^^^^^ `bar` 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/test-2.rs:4:30 @@ -65,6 +65,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `bar` cannot be made into an object --> $DIR/test-2.rs:13:6 diff --git a/tests/ui/wf/wf-object-safe.stderr b/tests/ui/wf/wf-object-safe.stderr index cc5351346b35a..49370b266c967 100644 --- a/tests/ui/wf/wf-object-safe.stderr +++ b/tests/ui/wf/wf-object-safe.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/wf-object-safe.rs:9:13 + --> $DIR/wf-object-safe.rs:9:14 | LL | let _x: &dyn A; - | ^^^^^^ `A` cannot be made into an object + | ^^^^^ `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/wf-object-safe.rs:5:23 From e2f21510328835587c77baa351117653e1b5be60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Jun 2024 06:19:08 +0000 Subject: [PATCH 09/26] Move `FnCtxt::get_fn_decl` to `TyCtxt` --- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 82 +------------------ .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_middle/src/ty/error.rs | 80 ++++++++++++++++++ 7 files changed, 87 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index a599e8d05fd3c..046935a1e285a 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -387,7 +387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // check that the `if` expr without `else` is the fn body's expr if expr.span == sp { - return self.get_fn_decl(hir_id).map(|(_, fn_decl, _)| { + return self.tcx.get_fn_decl(hir_id).map(|(_, fn_decl, _)| { let (ty, span) = match fn_decl.output { hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span), hir::FnRetTy::Return(ty) => (ty_to_string(&self.tcx, ty), ty.span), diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 16f5fe9611507..1ad7856a6c3b1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1860,7 +1860,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { }; // If this is due to an explicit `return`, suggest adding a return type. - if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(parent_id) + if let Some((fn_id, fn_decl, can_suggest)) = fcx.tcx.get_fn_decl(parent_id) && !due_to_block { fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, can_suggest, fn_id); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 6f82fc8aefb7b..253fb238fcef9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -774,7 +774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.ret_coercion_span.set(Some(expr.span)); } let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); - if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) { + if let Some((_, fn_decl, _)) = self.tcx.get_fn_decl(expr.hir_id) { coercion.coerce_forced_unit( self, &cause, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 15f93b093710b..5fa765012d7da 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath}; +use rustc_hir::{ExprKind, GenericArg, HirId, QPath}; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, @@ -34,7 +34,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::kw; use rustc_span::Span; use rustc_target::abi::FieldIdx; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; @@ -865,84 +865,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a - /// suggestion can be made, `None` otherwise. - pub fn get_fn_decl( - &self, - blk_id: HirId, - ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> { - // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or - // `while` before reaching it, as block tail returns are not available in them. - self.tcx.hir().get_fn_id_for_return_block(blk_id).and_then(|item_id| { - match self.tcx.hir_node(item_id) { - Node::Item(&hir::Item { - ident, - kind: hir::ItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => { - // This is less than ideal, it will not suggest a return type span on any - // method called `main`, regardless of whether it is actually the entry point, - // but it will still present it as the reason for the expected type. - Some((owner_id.def_id, sig.decl, ident.name != sym::main)) - } - Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => Some((owner_id.def_id, sig.decl, true)), - // FIXME: Suggestable if this is not a trait implementation - Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => Some((owner_id.def_id, sig.decl, false)), - Node::Expr(&hir::Expr { - hir_id, - kind: hir::ExprKind::Closure(&hir::Closure { def_id, kind, fn_decl, .. }), - .. - }) => { - match kind { - hir::ClosureKind::CoroutineClosure(_) => { - // FIXME(async_closures): Implement this. - return None; - } - hir::ClosureKind::Closure => Some((def_id, fn_decl, true)), - hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( - _, - hir::CoroutineSource::Fn, - )) => { - let (ident, sig, owner_id) = match self.tcx.parent_hir_node(hir_id) { - Node::Item(&hir::Item { - ident, - kind: hir::ItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => (ident, sig, owner_id), - Node::TraitItem(&hir::TraitItem { - ident, - kind: hir::TraitItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => (ident, sig, owner_id), - Node::ImplItem(&hir::ImplItem { - ident, - kind: hir::ImplItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => (ident, sig, owner_id), - _ => return None, - }; - Some((owner_id.def_id, sig.decl, ident.name != sym::main)) - } - _ => None, - } - } - _ => None, - } - }) - } - pub(crate) fn note_internal_mutation_in_method( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index b8333d4749378..ba7425ea73d5d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1774,7 +1774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // that highlight errors inline. let mut sp = blk.span; let mut fn_span = None; - if let Some((fn_def_id, decl, _)) = self.get_fn_decl(blk.hir_id) { + if let Some((fn_def_id, decl, _)) = self.tcx.get_fn_decl(blk.hir_id) { let ret_sp = decl.output.span(); if let Some(block_sp) = self.parent_item_span(blk.hir_id) { // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 9ab89f3444c9c..56294519a0e72 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -79,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `break` type mismatches provide better context for tail `loop` expressions. return false; } - if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { + if let Some((fn_id, fn_decl, can_suggest)) = self.tcx.get_fn_decl(blk_id) { pointing_at_return_type = self.suggest_missing_return_type(err, fn_decl, expected, found, can_suggest, fn_id); self.suggest_missing_break_or_return_expr( diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 32dc9fa5fc621..b869209c8e3dd 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -4,7 +4,9 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_errors::pluralize; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; +use rustc_hir::def_id::LocalDefId; use rustc_macros::extension; +use rustc_span::symbol::sym; pub use rustc_type_ir::error::ExpectedFound; use std::borrow::Cow; @@ -273,4 +275,82 @@ impl<'tcx> TyCtxt<'tcx> { Err(_) => regular, } } + + /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a + /// suggestion can be made, `None` otherwise. + pub fn get_fn_decl( + self, + blk_id: hir::HirId, + ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> { + // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or + // `while` before reaching it, as block tail returns are not available in them. + self.hir().get_fn_id_for_return_block(blk_id).and_then(|item_id| { + match self.hir_node(item_id) { + hir::Node::Item(&hir::Item { + ident, + kind: hir::ItemKind::Fn(ref sig, ..), + owner_id, + .. + }) => { + // This is less than ideal, it will not suggest a return type span on any + // method called `main`, regardless of whether it is actually the entry point, + // but it will still present it as the reason for the expected type. + Some((owner_id.def_id, sig.decl, ident.name != sym::main)) + } + hir::Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Fn(ref sig, ..), + owner_id, + .. + }) => Some((owner_id.def_id, sig.decl, true)), + // FIXME: Suggestable if this is not a trait implementation + hir::Node::ImplItem(&hir::ImplItem { + kind: hir::ImplItemKind::Fn(ref sig, ..), + owner_id, + .. + }) => Some((owner_id.def_id, sig.decl, false)), + hir::Node::Expr(&hir::Expr { + hir_id, + kind: hir::ExprKind::Closure(&hir::Closure { def_id, kind, fn_decl, .. }), + .. + }) => { + match kind { + hir::ClosureKind::CoroutineClosure(_) => { + // FIXME(async_closures): Implement this. + return None; + } + hir::ClosureKind::Closure => Some((def_id, fn_decl, true)), + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Fn, + )) => { + let (ident, sig, owner_id) = match self.parent_hir_node(hir_id) { + hir::Node::Item(&hir::Item { + ident, + kind: hir::ItemKind::Fn(ref sig, ..), + owner_id, + .. + }) => (ident, sig, owner_id), + hir::Node::TraitItem(&hir::TraitItem { + ident, + kind: hir::TraitItemKind::Fn(ref sig, ..), + owner_id, + .. + }) => (ident, sig, owner_id), + hir::Node::ImplItem(&hir::ImplItem { + ident, + kind: hir::ImplItemKind::Fn(ref sig, ..), + owner_id, + .. + }) => (ident, sig, owner_id), + _ => return None, + }; + Some((owner_id.def_id, sig.decl, ident.name != sym::main)) + } + _ => None, + } + } + _ => None, + } + }) + } } From 230a7878e194e6b376e1d85f0959749df758b308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Jun 2024 06:27:19 +0000 Subject: [PATCH 10/26] Deduplicate more E0038 object safety errors by pointing at type more often On casts to `dyn Trait` caused by explicit `as` or return type, we point at the type instead of the expression. Silence note with context about the cast when we'd point at the type, which allows automatic deduplication to happen. --- .../error_reporting/type_err_ctxt_ext.rs | 41 ++++++++++++++++++- ...lified-path-for-object-unsafe-trait.stderr | 1 - ...gate-dispatch-from-dyn-missing-impl.stderr | 6 +-- .../gat-in-trait-path.base.stderr | 2 +- .../issue-76535.base.stderr | 6 +-- .../issue-79422.base.stderr | 12 +++--- .../issue-79422.extended.stderr | 2 +- .../generic-associated-types/issue-79422.rs | 5 +-- .../trait-bounds/span-bug-issue-121597.stderr | 6 +-- .../impl-trait/in-trait/object-safety.stderr | 6 +-- ...safe-trait-in-return-position-dyn-trait.rs | 9 ++-- ...-trait-in-return-position-dyn-trait.stderr | 16 ++++---- tests/ui/issues/issue-18959.stderr | 6 +-- .../kindck-inherited-copy-bound.curr.stderr | 6 +-- ...copy-bound.object_safe_for_dispatch.stderr | 5 +-- tests/ui/object-safety/issue-19538.stderr | 6 +-- ...bject-safety-associated-consts.curr.stderr | 8 ++-- ...ted-consts.object_safe_for_dispatch.stderr | 7 ++-- .../object-safety-associated-consts.rs | 4 +- .../object-safety-generics.curr.stderr | 14 +++---- ...y-generics.object_safe_for_dispatch.stderr | 12 +++--- .../object-safety/object-safety-generics.rs | 4 +- .../object-safety-mentions-Self.curr.stderr | 16 ++++---- ...tions-Self.object_safe_for_dispatch.stderr | 14 +++---- .../object-safety-mentions-Self.rs | 8 ++-- .../object-safety-no-static.curr.stderr | 6 +-- ...-no-static.object_safe_for_dispatch.stderr | 5 +-- .../object-safety-sized-2.curr.stderr | 8 ++-- ...ty-sized-2.object_safe_for_dispatch.stderr | 7 ++-- .../ui/object-safety/object-safety-sized-2.rs | 4 +- .../object-safety-sized.curr.stderr | 8 ++-- ...fety-sized.object_safe_for_dispatch.stderr | 7 ++-- tests/ui/object-safety/object-safety-sized.rs | 4 +- ...ary-self-types-not-object-safe.curr.stderr | 6 +-- ...bject-safe.object_safe_for_dispatch.stderr | 5 +-- tests/ui/traits/issue-20692.rs | 2 +- tests/ui/traits/issue-20692.stderr | 10 ++--- tests/ui/traits/issue-38604.rs | 2 +- tests/ui/traits/issue-38604.stderr | 8 ++-- .../supertrait-object-safety.stderr | 6 +-- tests/ui/traits/object/safety.stderr | 6 +-- tests/ui/traits/test-2.stderr | 6 +-- .../wf/wf-convert-unsafe-trait-obj-box.stderr | 11 ++--- .../ui/wf/wf-convert-unsafe-trait-obj.stderr | 11 ++--- 44 files changed, 184 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 7f39f9c9e05a2..fb64ea0e9e653 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -954,7 +954,46 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); - report_object_safety_error(self.tcx, span, None, did, violations) + let (hir_id, early) = match root_obligation.cause.code() { + ObligationCauseCode::Coercion { parent_code, .. } => { + match &**parent_code { + ObligationCauseCode::ExprAssignable(hir_id) => (*hir_id, true), + ObligationCauseCode::ReturnValue(_) => { + let node = self.tcx.hir_node(self.tcx.local_def_id_to_hir_id(root_obligation.cause.body_id)); + if let Some(decl) = node.fn_decl() + && let hir::FnRetTy::Return(ty) = decl.output + { + // We'll point at the return type on type safety errors. + (Some(ty.hir_id), true) + } else { + (None, false) + } + } + ObligationCauseCode::BlockTailExpression(hir_id, _) => { + if let Some((_, decl, _)) = self.tcx.get_fn_decl(*hir_id) + && let hir::FnRetTy::Return(ty) = decl.output + { + // We'll point at the return type on type safety errors. + (Some(ty.hir_id), true) + } else { + (None, false) + } + } + _ => (None, false), + } + } + _ => (None, false), + }; + let mut err = report_object_safety_error(self.tcx, span, hir_id, did, violations); + if early { + // We want to skip `note_obligation_cause` because we don't want to note that + // the requirement came from a cast, because that note causes the error + // deduplication to not trigger and we'll have two errors instead of one. + self.point_at_returns_when_relevant(&mut err, &obligation); + return err.emit(); + } else { + err + } } SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr index 6f12e3f780c56..22b84259b5429 100644 --- a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-for-object-unsafe-trait.stderr @@ -42,7 +42,6 @@ LL | trait Trait: Sized {} | | | 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 Trait + 'static)` error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/trait-dyn-in-qualified-path-for-object-unsafe-trait.rs:10:6 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 faa369e79e18d..40cf1396ab332 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 @@ -17,13 +17,13 @@ LL | fn ptr(self: Ptr); = 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 + --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:29 | LL | fn ptr(self: Ptr); | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` ... LL | Ptr(Box::new(4)) as Ptr; - | ^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` 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/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 @@ -33,7 +33,7 @@ LL | trait Trait { LL | fn ptr(self: Ptr); | ^^^^^^^^^ ...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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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 4205c5c5ef779..4932a74abea2a 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 @@ -51,7 +51,7 @@ LL | type A<'a> where Self: 'a; = 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: Fooer Fooy - = note: required for the cast from `Box>` to `Box<(dyn Foo + 'static)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr index fd23f5d3ab046..05e4bad89779d 100644 --- a/tests/ui/generic-associated-types/issue-76535.base.stderr +++ b/tests/ui/generic-associated-types/issue-76535.base.stderr @@ -32,10 +32,10 @@ LL | type SubType<'a>: SubTrait where Self: 'a; = 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 + --> $DIR/issue-76535.rs:39:18 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` 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/issue-76535.rs:9:10 @@ -47,7 +47,7 @@ LL | type SubType<'a>: SubTrait where Self: 'a; = 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` to `Box>>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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 0667ce62c4d9a..bebf3c0aa2983 100644 --- a/tests/ui/generic-associated-types/issue-79422.base.stderr +++ b/tests/ui/generic-associated-types/issue-79422.base.stderr @@ -1,5 +1,5 @@ error[E0107]: missing generics for associated type `MapLike::VRefCont` - --> $DIR/issue-79422.rs:47:36 + --> $DIR/issue-79422.rs:45:36 | LL | as Box>>; | ^^^^^^^^ expected 1 lifetime argument @@ -15,7 +15,7 @@ LL | as Box = dyn RefCont<'_, u8>>>; | ++++ error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:47:16 + --> $DIR/issue-79422.rs:45:16 | LL | as Box>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object @@ -33,10 +33,10 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; std::collections::BTreeMap error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:44:13 + --> $DIR/issue-79422.rs:45:16 | -LL | let m = Box::new(std::collections::BTreeMap::::new()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object +LL | as Box>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` 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/issue-79422.rs:23:10 @@ -49,7 +49,7 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; = 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: Source std::collections::BTreeMap - = note: required for the cast from `Box>` to `Box + 'static)>>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr index ae1526296a795..96a06a8c6c99a 100644 --- a/tests/ui/generic-associated-types/issue-79422.extended.stderr +++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr @@ -1,5 +1,5 @@ error[E0107]: missing generics for associated type `MapLike::VRefCont` - --> $DIR/issue-79422.rs:47:36 + --> $DIR/issue-79422.rs:45:36 | LL | as Box>>; | ^^^^^^^^ expected 1 lifetime argument diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs index bf61dcaee3a52..c63ba2d5c9349 100644 --- a/tests/ui/generic-associated-types/issue-79422.rs +++ b/tests/ui/generic-associated-types/issue-79422.rs @@ -41,10 +41,9 @@ impl MapLike for Source { } fn main() { - let m = Box::new(std::collections::BTreeMap::::new()) - //[base]~^ ERROR the trait - //[extended]~^^ type mismatch + let m = Box::new(std::collections::BTreeMap::::new()) //[extended]~ type mismatch as Box>>; //~^ ERROR missing generics for associated type //[base]~^^ ERROR the trait + //[base]~| ERROR the trait } diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr index 8eefd6fa0a547..3c9dd27a866ef 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/span-bug-issue-121597.rs:14:23 + --> $DIR/span-bug-issue-121597.rs:14:13 | LL | let x: &dyn Foo = &(); - | ^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/span-bug-issue-121597.rs:4:12 @@ -11,7 +11,6 @@ LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables | | | this trait cannot be made into an object... - = note: required for the cast from `&()` to `&dyn Foo` error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/span-bug-issue-121597.rs:14:13 @@ -26,6 +25,7 @@ LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables | | | this trait cannot be made into an object... + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types --> $DIR/span-bug-issue-121597.rs:18:15 diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr index 7cd27f736eb2a..a08d7e1182ccc 100644 --- a/tests/ui/impl-trait/in-trait/object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/object-safety.stderr @@ -47,10 +47,10 @@ LL | fn baz(&self) -> impl Debug; = 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 + --> $DIR/object-safety.rs:14:37 | LL | let i = Box::new(42_u32) as Box; - | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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-safety.rs:4:22 @@ -61,7 +61,7 @@ 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` to `Box` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs index 068f7d3eea6da..5189cb9b4a14e 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs +++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs @@ -26,11 +26,14 @@ fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be ma B } -fn cat() -> Box { //~ ERROR the trait `NotObjectSafe` cannot be made into an +fn cat() -> Box { + //~^ ERROR cannot be made into an object + //~| ERROR cannot be made into an object + //~| ERROR cannot be made into an object if true { - return Box::new(A); //~ ERROR cannot be made into an object + return Box::new(A); } - Box::new(B) //~ ERROR cannot be made into an object + Box::new(B) } fn main() {} 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 fc9c30abf1336..c519e54a9f7d6 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 @@ -69,10 +69,10 @@ LL ~ Box::new(B) | error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:31:16 + --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:29:17 | -LL | return Box::new(A); - | ^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object +LL | fn cat() -> Box { + | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` 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-in-return-position-dyn-trait.rs:3:8 @@ -84,7 +84,7 @@ LL | fn foo() -> Self; = 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 - = note: required for the cast from `Box` to `Box<(dyn NotObjectSafe + 'static)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) -> Self; @@ -95,10 +95,10 @@ LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:33:5 + --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:29:17 | -LL | Box::new(B) - | ^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object +LL | fn cat() -> Box { + | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` 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-in-return-position-dyn-trait.rs:3:8 @@ -110,7 +110,7 @@ LL | fn foo() -> Self; = 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 - = note: required for the cast from `Box` to `Box<(dyn NotObjectSafe + 'static)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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-18959.stderr b/tests/ui/issues/issue-18959.stderr index 228760d6664b6..86f1b01e50c21 100644 --- a/tests/ui/issues/issue-18959.stderr +++ b/tests/ui/issues/issue-18959.stderr @@ -44,10 +44,10 @@ LL | pub trait Bar: Foo { } = help: consider moving `foo` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-18959.rs:19:26 + --> $DIR/issue-18959.rs:19:16 | LL | let test: &dyn Bar = &mut thing; - | ^^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` 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/issue-18959.rs:1:20 @@ -57,7 +57,7 @@ LL | pub trait Foo { fn foo(&self, ext_thing: &T); } LL | pub trait Bar: Foo { } | --- this trait cannot be made into an object... = help: consider moving `foo` to another trait - = note: required for the cast from `&mut Thing` to `&dyn Bar` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-18959.rs:22:9 diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr index e4b892a24be8d..e471c4d7303e1 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -34,10 +34,10 @@ LL | trait Foo : Copy { | this trait cannot be made into an object... error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:13 + --> $DIR/kindck-inherited-copy-bound.rs:28:20 | LL | let z = &x as &dyn Foo; - | ^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/kindck-inherited-copy-bound.rs:10:13 @@ -46,7 +46,7 @@ LL | trait Foo : Copy { | --- ^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... - = note: required for the cast from `&Box<{integer}>` to `&dyn Foo` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr index 30f90b88160e5..8a072a44b3e71 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -20,10 +20,10 @@ LL | fn take_param(foo: &T) { } | ^^^ required by this bound in `take_param` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:13 + --> $DIR/kindck-inherited-copy-bound.rs:28:20 | LL | let z = &x as &dyn Foo; - | ^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/kindck-inherited-copy-bound.rs:10:13 @@ -32,7 +32,6 @@ LL | trait Foo : Copy { | --- ^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... - = note: required for the cast from `&Box` to `&dyn Foo` error: aborting due to 2 previous errors diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/object-safety/issue-19538.stderr index 8c615a6df6487..179113c3669fd 100644 --- a/tests/ui/object-safety/issue-19538.stderr +++ b/tests/ui/object-safety/issue-19538.stderr @@ -16,10 +16,10 @@ LL | trait Bar: Foo { } = 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 + --> $DIR/issue-19538.rs:17:20 | LL | let test: &mut dyn Bar = &mut thing; - | ^^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` 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/issue-19538.rs:2:8 @@ -31,7 +31,7 @@ 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr b/tests/ui/object-safety/object-safety-associated-consts.curr.stderr index bd558d36f73fc..188b2d5a79e60 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr +++ b/tests/ui/object-safety/object-safety-associated-consts.curr.stderr @@ -14,10 +14,10 @@ LL | const X: usize; = help: consider moving `X` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 + --> $DIR/object-safety-associated-consts.rs:12:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-associated-consts.rs:9:11 @@ -27,7 +27,7 @@ LL | trait Bar { LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait - = note: required for the cast from `&T` to `&dyn Bar` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr index d0c78f9cd699e..462d3d95f13ee 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 + --> $DIR/object-safety-associated-consts.rs:12:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-associated-consts.rs:9:11 @@ -12,7 +12,6 @@ LL | trait Bar { LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait - = note: required for the cast from `&T` to `&dyn Bar` error: aborting due to 1 previous error diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/object-safety/object-safety-associated-consts.rs index a090214bbb404..16ad42abb5629 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.rs +++ b/tests/ui/object-safety/object-safety-associated-consts.rs @@ -10,9 +10,9 @@ trait Bar { } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 - t //~^ ERROR E0038 + //[curr]~^^ ERROR E0038 + t } fn main() { diff --git a/tests/ui/object-safety/object-safety-generics.curr.stderr b/tests/ui/object-safety/object-safety-generics.curr.stderr index b5f0b01e035d4..8e5d632fad3f1 100644 --- a/tests/ui/object-safety/object-safety-generics.curr.stderr +++ b/tests/ui/object-safety/object-safety-generics.curr.stderr @@ -29,10 +29,10 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 + --> $DIR/object-safety-generics.rs:18:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-generics.rs:10:8 @@ -42,7 +42,7 @@ LL | trait Bar { LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:27:11 @@ -60,10 +60,10 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 + --> $DIR/object-safety-generics.rs:27:11 | LL | t as &dyn Bar - | ^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` 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-safety-generics.rs:10:8 @@ -73,7 +73,7 @@ LL | trait Bar { LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 5 previous errors diff --git a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr index 498ad0d8a5e01..f204ff0393490 100644 --- a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 + --> $DIR/object-safety-generics.rs:18:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-generics.rs:10:8 @@ -12,13 +12,12 @@ LL | trait Bar { LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 + --> $DIR/object-safety-generics.rs:27:11 | LL | t as &dyn Bar - | ^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` 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-safety-generics.rs:10:8 @@ -28,7 +27,6 @@ LL | trait Bar { LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/object-safety/object-safety-generics.rs index f005a689ac45c..c93c64ff8de7e 100644 --- a/tests/ui/object-safety/object-safety-generics.rs +++ b/tests/ui/object-safety/object-safety-generics.rs @@ -17,9 +17,9 @@ trait Quux { fn make_bar(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 + //[curr]~| ERROR E0038 + //[object_safe_for_dispatch]~^^^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 - //[curr]~^^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { diff --git a/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr b/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr index 28c9c9d64a06c..125859bd0479c 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr +++ b/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr @@ -29,10 +29,10 @@ LL | fn baz(&self) -> Self; = help: consider moving `baz` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 + --> $DIR/object-safety-mentions-Self.rs:22:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-mentions-Self.rs:11:22 @@ -42,13 +42,13 @@ LL | trait Bar { LL | fn bar(&self, x: &Self); | ^^^^^ ...because method `bar` references the `Self` type in this parameter = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 + --> $DIR/object-safety-mentions-Self.rs:28:31 | -LL | t - | ^ `Baz` cannot be made into an object +LL | fn make_baz(t: &T) -> &dyn Baz { + | ^^^^^^^ `Baz` 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-safety-mentions-Self.rs:15:22 @@ -58,7 +58,7 @@ LL | trait Baz { LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type = help: consider moving `baz` to another trait - = note: required for the cast from `&T` to `&dyn Baz` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr index 414614d8d0bf0..de430a89bf82b 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 + --> $DIR/object-safety-mentions-Self.rs:22:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-mentions-Self.rs:11:22 @@ -12,13 +12,12 @@ LL | trait Bar { LL | fn bar(&self, x: &Self); | ^^^^^ ...because method `bar` references the `Self` type in this parameter = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 + --> $DIR/object-safety-mentions-Self.rs:28:31 | -LL | t - | ^ `Baz` cannot be made into an object +LL | fn make_baz(t: &T) -> &dyn Baz { + | ^^^^^^^ `Baz` 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-safety-mentions-Self.rs:15:22 @@ -28,7 +27,6 @@ LL | trait Baz { LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type = help: consider moving `baz` to another trait - = note: required for the cast from `&T` to `&dyn Baz` error: aborting due to 2 previous errors diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/object-safety/object-safety-mentions-Self.rs index 1311faf97bc36..348eb2a51cd3e 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.rs +++ b/tests/ui/object-safety/object-safety-mentions-Self.rs @@ -20,15 +20,15 @@ trait Quux { } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 - t //~^ ERROR E0038 + //[curr]~^^ ERROR E0038 + t } fn make_baz(t: &T) -> &dyn Baz { - //[curr]~^ ERROR E0038 - t //~^ ERROR E0038 + //[curr]~^^ ERROR E0038 + t } fn make_quux(t: &T) -> &dyn Quux { 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 32518881f7c27..4b496679e5716 100644 --- a/tests/ui/object-safety/object-safety-no-static.curr.stderr +++ b/tests/ui/object-safety/object-safety-no-static.curr.stderr @@ -45,10 +45,10 @@ LL | fn foo() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 + --> $DIR/object-safety-no-static.rs:22:16 | LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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-safety-no-static.rs:9:8 @@ -58,7 +58,7 @@ LL | trait Foo { 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` to `Box` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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 e155a350f8947..172d48b9a3218 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 @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 + --> $DIR/object-safety-no-static.rs:22:16 | LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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-safety-no-static.rs:9:8 @@ -12,7 +12,6 @@ LL | trait Foo { 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` to `Box` 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-sized-2.curr.stderr b/tests/ui/object-safety/object-safety-sized-2.curr.stderr index 03b078c2a44e2..c85f1c05cddd5 100644 --- a/tests/ui/object-safety/object-safety-sized-2.curr.stderr +++ b/tests/ui/object-safety/object-safety-sized-2.curr.stderr @@ -13,10 +13,10 @@ LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 + --> $DIR/object-safety-sized-2.rs:14:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-sized-2.rs:9:18 @@ -25,7 +25,7 @@ LL | trait Bar | --- this trait cannot be made into an object... LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` - = note: required for the cast from `&T` to `&dyn Bar` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr index 69af9bfe92b9f..7b91c4d665cfe 100644 --- a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 + --> $DIR/object-safety-sized-2.rs:14:31 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-sized-2.rs:9:18 @@ -11,7 +11,6 @@ LL | trait Bar | --- this trait cannot be made into an object... LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` - = note: required for the cast from `&T` to `&dyn Bar` error: aborting due to 1 previous error diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/object-safety/object-safety-sized-2.rs index cfb5d588d70df..dc10506cfdb0f 100644 --- a/tests/ui/object-safety/object-safety-sized-2.rs +++ b/tests/ui/object-safety/object-safety-sized-2.rs @@ -12,9 +12,9 @@ trait Bar } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 - t //~^ ERROR E0038 + //[curr]~^^ ERROR E0038 + t } fn main() { diff --git a/tests/ui/object-safety/object-safety-sized.curr.stderr b/tests/ui/object-safety/object-safety-sized.curr.stderr index 0513780a81f1d..91d2f8c707afc 100644 --- a/tests/ui/object-safety/object-safety-sized.curr.stderr +++ b/tests/ui/object-safety/object-safety-sized.curr.stderr @@ -13,10 +13,10 @@ LL | trait Bar: Sized { | this trait cannot be made into an object... error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 + --> $DIR/object-safety-sized.rs:12:32 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-sized.rs:8:12 @@ -25,7 +25,7 @@ LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... - = note: required for the cast from `&T` to `&dyn Bar` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr index d988293c0e9a2..6594a6db0f470 100644 --- a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 + --> $DIR/object-safety-sized.rs:12:32 | -LL | t - | ^ `Bar` cannot be made into an object +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` 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-safety-sized.rs:8:12 @@ -11,7 +11,6 @@ LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... - = note: required for the cast from `&T` to `&dyn Bar` error: aborting due to 1 previous error diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/object-safety/object-safety-sized.rs index f4d6c945b33d5..e853cdeedc4ff 100644 --- a/tests/ui/object-safety/object-safety-sized.rs +++ b/tests/ui/object-safety/object-safety-sized.rs @@ -10,9 +10,9 @@ trait Bar: Sized { } fn make_bar(t: &T) -> &dyn Bar { - //[curr]~^ ERROR E0038 - t //~^ ERROR E0038 + //[curr]~^^ ERROR E0038 + t } fn main() {} 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 7b380e7f8cd90..ea6f0c6f3050f 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 @@ -17,13 +17,13 @@ LL | fn foo(self: &Rc) -> usize; = 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 + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:35 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc; - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/arbitrary-self-types-not-object-safe.rs:8:18 @@ -33,7 +33,7 @@ LL | trait Foo { LL | fn foo(self: &Rc) -> 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` to `Rc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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 363ba072c8169..3da83d1d59ca3 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 @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:35 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc; - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/arbitrary-self-types-not-object-safe.rs:8:18 @@ -15,7 +15,6 @@ LL | trait Foo { LL | fn foo(self: &Rc) -> 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` to `Rc` error: aborting due to 1 previous error diff --git a/tests/ui/traits/issue-20692.rs b/tests/ui/traits/issue-20692.rs index 1cb2d8c7302a0..b014dc739bc22 100644 --- a/tests/ui/traits/issue-20692.rs +++ b/tests/ui/traits/issue-20692.rs @@ -2,10 +2,10 @@ trait Array: Sized + Copy {} fn f(x: &T) { let _ = x - //~^ ERROR `Array` cannot be made into an object as &dyn Array; //~^ ERROR `Array` cannot be made into an object + //~| ERROR `Array` cannot be made into an object } fn main() {} diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr index eaf704d83991c..788a4c43b1679 100644 --- a/tests/ui/traits/issue-20692.stderr +++ b/tests/ui/traits/issue-20692.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Array` cannot be made into an object - --> $DIR/issue-20692.rs:7:6 + --> $DIR/issue-20692.rs:6:6 | LL | &dyn Array; | ^^^^^^^^^ `Array` cannot be made into an object @@ -14,10 +14,10 @@ LL | trait Array: Sized + Copy {} | this trait cannot be made into an object... error[E0038]: the trait `Array` cannot be made into an object - --> $DIR/issue-20692.rs:4:13 + --> $DIR/issue-20692.rs:6:6 | -LL | let _ = x - | ^ `Array` cannot be made into an object +LL | &dyn Array; + | ^^^^^^^^^ `Array` 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/issue-20692.rs:1:14 @@ -27,7 +27,7 @@ LL | trait Array: Sized + Copy {} | | | | | ...because it requires `Self: Sized` | this trait cannot be made into an object... - = note: required for the cast from `&T` to `&dyn Array` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-38604.rs b/tests/ui/traits/issue-38604.rs index 002a3c43fcba6..52502e9d1a0bd 100644 --- a/tests/ui/traits/issue-38604.rs +++ b/tests/ui/traits/issue-38604.rs @@ -12,5 +12,5 @@ impl Foo for () { fn main() { let _f: Box = //~ ERROR `Foo` cannot be made into an object - Box::new(()); //~ ERROR `Foo` cannot be made into an object + Box::new(()); //~^ ERROR `Foo` cannot be made into an object } diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr index 2c2976d9a1300..46375428b5409 100644 --- a/tests/ui/traits/issue-38604.stderr +++ b/tests/ui/traits/issue-38604.stderr @@ -14,10 +14,10 @@ LL | trait Foo where u32: Q { = 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 + --> $DIR/issue-38604.rs:14:17 | -LL | Box::new(()); - | ^^^^^^^^^^^^ `Foo` cannot be made into an object +LL | let _f: Box = + | ^^^^^^^ `Foo` 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/issue-38604.rs:2:22 @@ -27,7 +27,7 @@ LL | trait Foo where u32: Q { | | | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors 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 6025591b52a74..f862b7aba5742 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr @@ -8,10 +8,10 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:23 + --> $DIR/supertrait-object-safety.rs:19:13 | LL | let x: &dyn Foo = &(); - | ^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` 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/supertrait-object-safety.rs:4:12 @@ -21,7 +21,6 @@ LL | trait Foo: for Bar {} | | | 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 --> $DIR/supertrait-object-safety.rs:19:13 @@ -37,6 +36,7 @@ LL | trait Foo: for Bar {} | | | this trait cannot be made into an object... = help: only type `()` implements the trait, consider using it directly instead + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/supertrait-object-safety.rs:22:5 diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr index a31cb9655f3d3..53e309d5afe6e 100644 --- a/tests/ui/traits/object/safety.stderr +++ b/tests/ui/traits/object/safety.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Tr` cannot be made into an object - --> $DIR/safety.rs:15:22 + --> $DIR/safety.rs:15:13 | LL | let _: &dyn Tr = &St; - | ^^^ `Tr` cannot be made into an object + | ^^^^^^ `Tr` 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/safety.rs:4:8 @@ -12,7 +12,6 @@ LL | trait Tr { 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 | LL | fn foo(&self); @@ -36,6 +35,7 @@ LL | trait Tr { LL | fn foo(); | ^^^ ...because associated function `foo` has no `self` parameter = help: only type `St` implements the trait, consider using it directly instead + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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 cb03a8a8a2474..dad0af85d7203 100644 --- a/tests/ui/traits/test-2.stderr +++ b/tests/ui/traits/test-2.stderr @@ -68,10 +68,10 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `bar` cannot be made into an object - --> $DIR/test-2.rs:13:6 + --> $DIR/test-2.rs:13:26 | LL | (Box::new(10) as Box).dup(); - | ^^^^^^^^^^^^ `bar` cannot be made into an object + | ^^^^^^^ `bar` 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/test-2.rs:4:30 @@ -86,7 +86,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } = 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 5 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 85f5073364ffb..61aef86b4ccd1 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:20 | LL | let t_box: Box = Box::new(S); - | ^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` 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/wf-convert-unsafe-trait-obj-box.rs:6:14 @@ -12,7 +12,6 @@ LL | trait Trait: 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` to `Box` error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 @@ -28,13 +27,12 @@ LL | trait Trait: 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` to `Box<(dyn Trait + 'static)>` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:24 | LL | Box::new(S) as Box; - | ^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` 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/wf-convert-unsafe-trait-obj-box.rs:6:14 @@ -44,7 +42,6 @@ LL | trait Trait: 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` to `Box` 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 a2a196316495c..f05ecbb73df2d 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 + --> $DIR/wf-convert-unsafe-trait-obj.rs:16:13 | LL | let t: &dyn Trait = &S; - | ^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` 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/wf-convert-unsafe-trait-obj.rs:6:14 @@ -12,7 +12,6 @@ LL | trait Trait: 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 --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 @@ -28,13 +27,12 @@ LL | trait Trait: 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 - --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 + --> $DIR/wf-convert-unsafe-trait-obj.rs:15:12 | LL | &S as &dyn Trait; - | ^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` 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/wf-convert-unsafe-trait-obj.rs:6:14 @@ -44,7 +42,6 @@ LL | trait Trait: 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 From e55ab931ef814b0e63e43117f06469c0a946fbb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Jun 2024 19:26:59 +0000 Subject: [PATCH 11/26] Move suggestions out of main error logic --- .../src/traits/error_reporting/mod.rs | 224 ++++++++++-------- ...g-dyn-in-qualified-path.edition2018.stderr | 2 +- 2 files changed, 132 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 843f92132620c..762149c3d127f 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -5,6 +5,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan}; use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -228,100 +229,10 @@ pub fn report_object_safety_error<'tcx>( let mut has_suggested = false; if let Some(hir_id) = hir_id { let node = tcx.hir_node(hir_id); - if let hir::Node::Ty(ty) = node - && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind - { - let mut hir_id = hir_id; - while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) { - hir_id = ty.hir_id; - } - if tcx.parent_hir_node(hir_id).fn_sig().is_some() { - // Do not suggest `impl Trait` when dealing with things like super-traits. - err.span_suggestion_verbose( - ty.span.until(trait_ref.span), - "consider using an opaque type instead", - "impl ", - Applicability::MaybeIncorrect, - ); - has_suggested = true; - } - } - if let hir::Node::Expr(expr) = node - && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, path_segment)) = expr.kind - && let hir::TyKind::TraitObject([trait_ref, ..], _, trait_object_syntax) = ty.kind - { - if let TraitObjectSyntax::None = trait_object_syntax - && !expr.span.edition().at_least_rust_2021() - { - err.span_note( - trait_ref.trait_ref.path.span, - format!( - "`{trait_str}` is the type for the trait in editions 2015 and 2018 and is \ - equivalent to writing `dyn {trait_str}`", - ), - ); - } - let segment = path_segment.ident; - err.help(format!( - "when writing `::{segment}` you are requiring `{trait_str}` be \ - \"object safe\", which it isn't", - )); - let (only, msg, sugg, appl) = if let [only] = &impls[..] { - // We know there's a single implementation for this trait, so we can be explicit on - // the type they should have used. - let ty = tcx.type_of(*only).instantiate_identity(); - ( - true, - format!( - "specify the specific `impl` for type `{ty}` to avoid requiring \"object \ - safety\" from `{trait_str}`", - ), - with_no_trimmed_paths!(format!("{ty} as ")), - Applicability::MachineApplicable, - ) - } else { - ( - false, - format!( - "you might have meant to access the associated function of a specific \ - `impl` to avoid requiring \"object safety\" from `{trait_str}`, either \ - with some explicit type...", - ), - "/* Type */ as ".to_string(), - Applicability::HasPlaceholders, - ) - }; - // `::segment()` or `::segment()` to `::segment()` - let sp = ty.span.until(trait_ref.trait_ref.path.span); - err.span_suggestion_verbose(sp, msg, sugg, appl); - if !only { - // `::segment()` or `::segment()` to `Trait::segment()` - err.multipart_suggestion_verbose( - "...or rely on inference if the compiler has enough context to identify the \ - desired type on its own...", - vec![ - (expr.span.until(trait_ref.trait_ref.path.span), String::new()), - ( - path_segment - .ident - .span - .shrink_to_lo() - .with_lo(trait_ref.trait_ref.path.span.hi()), - "::".to_string(), - ), - ], - Applicability::MaybeIncorrect, - ); - // `::segment()` or `::segment()` to `<_ as Trait>::segment()` - err.span_suggestion_verbose( - ty.span.until(trait_ref.trait_ref.path.span), - "...which is equivalent to", - format!("_ as "), - Applicability::MaybeIncorrect, - ); - } - has_suggested = true; + if let hir::Node::Ty(ty) = node { + has_suggested |= suggest_impl_trait_on_bare_trait(tcx, &mut err, ty); } + has_suggested |= suggest_path_on_bare_trait(tcx, &mut err, node); } match &impls[..] { _ if has_suggested => {} @@ -366,3 +277,130 @@ pub fn report_object_safety_error<'tcx>( err } + +pub fn suggest_impl_trait_on_bare_trait( + tcx: TyCtxt<'_>, + err: &mut Diag<'_>, + ty: &hir::Ty<'_>, +) -> bool { + let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind else { return false }; + let mut hir_id = ty.hir_id; + while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) { + hir_id = ty.hir_id; + } + if tcx.parent_hir_node(hir_id).fn_sig().is_none() { + return false; + } + // Do not suggest `impl Trait` when dealing with things like super-traits. + err.span_suggestion_verbose( + ty.span.until(trait_ref.span), + "consider using an opaque type instead", + "impl ", + Applicability::MaybeIncorrect, + ); + true +} + +pub fn suggest_path_on_bare_trait( + tcx: TyCtxt<'_>, + err: &mut Diag<'_>, + node: hir::Node<'_>, +) -> bool { + let hir::Node::Expr(expr) = node else { return false }; + let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, path_segment)) = expr.kind else { + return false; + }; + let hir::TyKind::TraitObject([trait_ref, ..], _, trait_object_syntax) = ty.kind else { + return false; + }; + let trait_def_id = match trait_ref.trait_ref.path.res { + Res::Def(DefKind::Trait, def_id) => def_id, + _ => return false, + }; + let trait_str = tcx.def_path_str(trait_def_id); + if let TraitObjectSyntax::None = trait_object_syntax + && !expr.span.edition().at_least_rust_2021() + { + err.span_note( + trait_ref.trait_ref.path.span, + format!( + "`{trait_str}` is the type for the trait in editions 2015 and 2018 and is \ + equivalent to writing `dyn {trait_str}`", + ), + ); + } + let segment = path_segment.ident; + err.help(format!( + "when writing `<{}{trait_str}>::{segment}` you are requiring `{trait_str}` be \"object \ + safe\", which it isn't", + if let TraitObjectSyntax::None = trait_object_syntax { "" } else { "dyn " }, + )); + 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::>() + } else { + vec![] + }; + let (only, msg, sugg, appl) = if let [only] = &impls[..] { + // We know there's a single implementation for this trait, so we can be explicit on + // the type they should have used. + let ty = tcx.type_of(*only).instantiate_identity(); + ( + true, + format!( + "specify the specific `impl` for type `{ty}` to avoid requiring \"object safety\" \ + from `{trait_str}`", + ), + with_no_trimmed_paths!(format!("{ty} as ")), + Applicability::MachineApplicable, + ) + } else { + ( + false, + format!( + "you might have meant to access the associated function of a specific `impl` to \ + avoid requiring \"object safety\" from `{trait_str}`, either with some explicit \ + type...", + ), + "/* Type */ as ".to_string(), + Applicability::HasPlaceholders, + ) + }; + // `::segment()` or `::segment()` to `::segment()` + let sp = ty.span.until(trait_ref.trait_ref.path.span); + err.span_suggestion_verbose(sp, msg, sugg, appl); + if !only { + // `::segment()` or `::segment()` to `Trait::segment()` + err.multipart_suggestion_verbose( + "...or rely on inference if the compiler has enough context to identify the desired \ + type on its own...", + vec![ + (expr.span.until(trait_ref.trait_ref.path.span), String::new()), + ( + path_segment + .ident + .span + .shrink_to_lo() + .with_lo(trait_ref.trait_ref.path.span.hi()), + "::".to_string(), + ), + ], + Applicability::MaybeIncorrect, + ); + // `::segment()` or `::segment()` to `<_ as Trait>::segment()` + err.span_suggestion_verbose( + ty.span.until(trait_ref.trait_ref.path.span), + "...which is equivalent to", + format!("_ as "), + Applicability::MaybeIncorrect, + ); + } + true +} diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr index c5a0bb2fda36c..e4479b8af1b90 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr @@ -25,7 +25,7 @@ note: `Default` is the type for the trait in editions 2015 and 2018 and is equiv | LL | let x: u32 = ::default(); | ^^^^^^^ - = help: when writing `::default` you are requiring `Default` be "object safe", which it isn't + = help: when writing `::default` you are requiring `Default` be "object safe", which it isn't help: you might have meant to access the associated function of a specific `impl` to avoid requiring "object safety" from `Default`, either with some explicit type... | LL | let x: u32 = ::default(); From c9e80298dfd32e4816f09816bc92081c730e26b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Jun 2024 19:42:55 +0000 Subject: [PATCH 12/26] Tweak wording and only suggest `dyn Trait` if `Trait` is object safe --- .../src/hir_ty_lowering/lint.rs | 58 ++++-- .../suggest-assoc-ty-bound-on-eq-bound.rs | 3 - .../suggest-assoc-ty-bound-on-eq-bound.stderr | 19 +- .../const-generics/not_wf_param_in_rpitit.rs | 7 +- .../not_wf_param_in_rpitit.stderr | 111 +++------- .../const_refs_to_static-ice-121413.stderr | 4 +- tests/ui/did_you_mean/bad-assoc-ty.stderr | 2 +- .../dyn-keyword/dyn-2018-edition-lint.stderr | 6 +- .../ui/dyn-keyword/dyn-angle-brackets.stderr | 2 +- ...g-dyn-in-qualified-path.edition2018.stderr | 5 +- ...g-dyn-in-qualified-path.edition2021.stderr | 5 - ...lifetime-from-bare-trait-obj-114664.stderr | 4 +- tests/ui/issues/issue-28344.stderr | 4 +- tests/ui/issues/issue-50781.stderr | 1 - tests/ui/issues/issue-58734.stderr | 5 +- tests/ui/issues/issue-86756.stderr | 2 +- tests/ui/lint/bare-trait-objects-path.stderr | 8 +- .../allowed-group-warn-by-default-lint.stderr | 2 +- .../ui/lint/force-warn/cap-lints-allow.stderr | 2 +- ...up-allowed-cli-warn-by-default-lint.stderr | 2 +- .../lint-group-allowed-lint-group.stderr | 2 +- ...-group-allowed-warn-by-default-lint.stderr | 2 +- .../avoid-ice-on-warning-2.old.stderr | 10 +- .../avoid-ice-on-warning-3.old.stderr | 46 ++-- .../avoid-ice-on-warning.old.stderr | 5 +- .../bare-trait-dont-suggest-dyn.old.stderr | 5 +- .../parser/trait-object-trait-parens.stderr | 6 +- tests/ui/suggestions/issue-116434-2015.rs | 4 - tests/ui/suggestions/issue-116434-2015.stderr | 28 +-- tests/ui/suggestions/issue-61963.stderr | 4 +- .../object-unsafe-trait-should-use-self.rs | 2 + ...object-unsafe-trait-should-use-self.stderr | 31 ++- .../suggest-swapping-self-ty-and-trait.stderr | 6 +- .../bound/not-on-bare-trait-2021.stderr | 12 ++ .../ui/traits/bound/not-on-bare-trait.stderr | 2 +- .../unspecified-self-in-trait-ref.stderr | 10 +- ...ce-hir-wf-check-anon-const-issue-122199.rs | 25 +-- ...ir-wf-check-anon-const-issue-122199.stderr | 196 +++--------------- ...ce-hir-wf-check-anon-const-issue-122989.rs | 13 +- ...ir-wf-check-anon-const-issue-122989.stderr | 142 +++++-------- 40 files changed, 268 insertions(+), 535 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index b42dc96f7b78f..e5af709f4aed6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -20,9 +20,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Option { let tcx = self.tcx(); - let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = - self_ty.kind - else { + let hir::TyKind::TraitObject(traits, _, TraitObjectSyntax::None) = self_ty.kind else { + return None; + }; + let [poly_trait_ref, ..] = traits else { return None; }; @@ -36,6 +37,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let is_global = poly_trait_ref.trait_ref.path.is_global(); + let object_safe = traits.iter().all(|ptr| match ptr.trait_ref.path.res { + Res::Def(DefKind::Trait, def_id) => tcx.object_safety_violations(def_id).is_empty(), + _ => false, + }); + let mut sugg = vec![( self_ty.span.shrink_to_lo(), format!( @@ -63,10 +69,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); let mut downgrade = false; if self_ty.span.can_be_used_for_suggestions() { - let (non_object_safe, should_downgrade) = - self.maybe_suggest_impl_trait(self_ty, &mut diag); + let should_downgrade = self.maybe_suggest_impl_trait(self_ty, &mut diag); downgrade = should_downgrade; - if !non_object_safe { + if object_safe { // Only emit this suggestion if the trait is object safe. diag.multipart_suggestion_verbose( label, @@ -89,12 +94,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); - if self_ty.span.can_be_used_for_suggestions() { - lint.multipart_suggestion_verbose( - "if this is an object-safe trait, use `dyn`", - sugg, - Applicability::MachineApplicable, - ); + match (object_safe, self_ty.span.can_be_used_for_suggestions()) { + (true, true) => { + lint.multipart_suggestion_verbose( + "as this is an \"object safe\" trait, write `dyn` in front of the \ + trait", + sugg, + Applicability::MachineApplicable, + ); + } + (true, false) => { + lint.note( + "as this is an \"object safe\" trait, you can write `dyn` in front of \ + the trait", + ); + } + (false, _) => { + lint.note( + "you can't use write a trait object here because the trait isn't \ + \"object safe\"", + ); + } } self.maybe_suggest_blanket_trait_impl(self_ty, lint); }); @@ -170,7 +190,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Make sure that we are in the condition to suggest `impl Trait`. /// /// Returns whether a suggestion was provided and whether the error itself should not be emitted - fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> (bool, bool) { + fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool { let tcx = self.tcx(); let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0` @@ -185,10 +205,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { owner_id, .. }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), - _ => return (false, false), + _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { - return (false, false); + return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; let mut is_downgradable = true; @@ -201,7 +221,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // For recursive traits, don't downgrade the error. (#119652) is_downgradable = false; } - tcx.is_object_safe(id) + tcx.object_safety_violations(id).is_empty() } _ => false, }) @@ -234,7 +254,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // We'll emit the object safety error already, with a structured suggestion. downgrade = true; } - return (true, downgrade); + return downgrade; } for ty in sig.decl.inputs { if ty.hir_id != self_ty.hir_id { @@ -279,9 +299,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MachineApplicable, ); } - return (true, downgrade); + return downgrade; } - (false, downgrade) + downgrade } fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs index 23f89eb28eb38..c00acfef6d80f 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs @@ -3,12 +3,10 @@ fn f(_: impl Trait) {} //~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait //~| HELP you might have meant to write a bound here fn g(_: impl Trait) {} //~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait //~| HELP you might have meant to write a bound here fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} @@ -19,7 +17,6 @@ fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} // Don't suggest assoc ty bound in trait object types, that's not valid: type Obj = dyn Trait; //~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait trait Trait { type T; } diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr index 990aae8cfe38b..3353873a84dff 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr @@ -4,32 +4,24 @@ error[E0782]: trait objects must include the `dyn` keyword LL | fn f(_: impl Trait) {} | ^^^^ | -help: add `dyn` keyword before this trait - | -LL | fn f(_: impl Trait) {} - | +++ help: you might have meant to write a bound here | LL | fn f(_: impl Trait) {} | ~ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:9:24 + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:8:24 | LL | fn g(_: impl Trait) {} | ^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait - | -LL | fn g(_: impl Trait) {} - | +++ help: you might have meant to write a bound here | LL | fn g(_: impl Trait) {} | ~ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:14:26 + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:12:26 | LL | fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,15 +36,10 @@ LL | fn h(_: impl Trait: 'static + for<'a> Fn(&'a ())>) {} | ~ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:20:26 + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26 | LL | type Obj = dyn Trait; | ^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | type Obj = dyn Trait; - | +++ error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.rs b/tests/ui/const-generics/not_wf_param_in_rpitit.rs index 5471dc9022f90..07012a42d7143 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.rs +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.rs @@ -2,12 +2,7 @@ trait Trait { //~^ ERROR: cannot find value `bar` in this scope - //~| ERROR: cycle detected when computing type of `Trait::N` - //~| ERROR: the trait `Trait` cannot be made into an object - //~| ERROR: the trait `Trait` cannot be made into an object - //~| ERROR: the trait `Trait` cannot be made into an object - //~| ERROR: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: cycle detected when computing predicates of `Trait` async fn a() {} } diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr index 9095948d22b8a..a5687d8409123 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr @@ -4,110 +4,51 @@ error[E0425]: cannot find value `bar` in this scope LL | trait Trait { | ^^^ not found in this scope -error[E0391]: cycle detected when computing type of `Trait::N` - --> $DIR/not_wf_param_in_rpitit.rs:3:22 +error[E0391]: cycle detected when computing predicates of `Trait` + --> $DIR/not_wf_param_in_rpitit.rs:3:1 | LL | trait Trait { - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...which immediately requires computing type of `Trait::N` again -note: cycle used when computing explicit predicates of trait `Trait` +note: ...which requires computing predicates of `Trait`... --> $DIR/not_wf_param_in_rpitit.rs:3:1 | LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/not_wf_param_in_rpitit.rs:3:22 +note: ...which requires computing explicit predicates of `Trait`... + --> $DIR/not_wf_param_in_rpitit.rs:3:1 | LL | trait Trait { - | ^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing explicit predicates of trait `Trait`... + --> $DIR/not_wf_param_in_rpitit.rs:3:1 | LL | trait Trait { - | ----- this trait cannot be made into an object... -... -LL | async fn a() {} - | ^ ...because associated function `a` has no `self` parameter -help: consider turning `a` into a method by giving it a `&self` argument - | -LL | async fn a(&self) {} - | +++++ -help: alternatively, consider constraining `a` so it does not apply to trait objects - | -LL | async fn a() where Self: Sized {} - | +++++++++++++++++ - -error[E0038]: the trait `Trait` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing type of `Trait::N`... --> $DIR/not_wf_param_in_rpitit.rs:3:13 | LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14 - | -LL | trait Trait { - | ----- this trait cannot be made into an object... -... -LL | async fn a() {} - | ^ ...because associated function `a` has no `self` parameter -help: consider turning `a` into a method by giving it a `&self` argument - | -LL | async fn a(&self) {} - | +++++ -help: alternatively, consider constraining `a` so it does not apply to trait objects - | -LL | async fn a() where Self: Sized {} - | +++++++++++++++++ - -error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/not_wf_param_in_rpitit.rs:3:22 - | -LL | trait Trait { - | ^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/not_wf_param_in_rpitit.rs:3:13 + | ^^^^^^^^^^^^^^^^^^^^ +note: ...which requires determining object safety of trait `Trait`... + --> $DIR/not_wf_param_in_rpitit.rs:3:1 | LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires check whether the item has a `where Self: Sized` bound... + --> $DIR/not_wf_param_in_rpitit.rs:6:5 | -LL | trait Trait { - | ----- this trait cannot be made into an object... -... LL | async fn a() {} - | ^ ...because associated function `a` has no `self` parameter - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider turning `a` into a method by giving it a `&self` argument - | -LL | async fn a(&self) {} - | +++++ -help: alternatively, consider constraining `a` so it does not apply to trait objects - | -LL | async fn a() where Self: Sized {} - | +++++++++++++++++ - -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not_wf_param_in_rpitit.rs:3:22 + | ^^^^^^^^^^^^ + = note: ...which again requires computing predicates of `Trait`, completing the cycle +note: cycle used when checking that `Trait` is well-formed + --> $DIR/not_wf_param_in_rpitit.rs:3:1 | LL | trait Trait { - | ^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | trait Trait { - | +++ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 7 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0038, E0391, E0425, E0782. -For more information about an error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0391, E0425. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr index e41f352282a88..2dcf0deb1546b 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr @@ -18,7 +18,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | static FOO: dyn Sync = AtomicUsize::new(0); | +++ @@ -32,7 +32,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | static FOO: dyn Sync = AtomicUsize::new(0); | +++ diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index b349332bcb9c3..d6ee1b4b514cd 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -182,7 +182,7 @@ LL | type H = Fn(u8) -> (u8)::Output; = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | type H = (u8)>::Output; | ++++ + diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr index 711bfa188ecd8..ea0277ca26549 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #[deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | fn function(x: &dyn SomeTrait, y: Box) { | +++ @@ -24,7 +24,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | fn function(x: &SomeTrait, y: Box) { | +++ @@ -37,7 +37,7 @@ LL | let _x: &SomeTrait = todo!(); | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let _x: &dyn SomeTrait = todo!(); | +++ diff --git a/tests/ui/dyn-keyword/dyn-angle-brackets.stderr b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr index 41298cc73c818..e81efc7fe7c0f 100644 --- a/tests/ui/dyn-keyword/dyn-angle-brackets.stderr +++ b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | ::fmt(self, f) | +++ diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr index e4479b8af1b90..223e260584e74 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr @@ -6,11 +6,8 @@ LL | let x: u32 = ::default(); | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see + = note: you can't use write a trait object here because the trait isn't "object safe" = note: `#[warn(bare_trait_objects)]` on by default -help: if this is an object-safe trait, use `dyn` - | -LL | let x: u32 = ::default(); - | +++ error[E0038]: the trait `Default` cannot be made into an object --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19 diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr index 2222cecbaa185..3f7430241ce8c 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr @@ -3,11 +3,6 @@ error[E0782]: trait objects must include the `dyn` keyword | LL | let x: u32 = ::default(); | ^^^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | let x: u32 = ::default(); - | +++ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr index d82b2c0f6066a..f6358a22baf09 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr @@ -7,7 +7,7 @@ LL | fn ice() -> impl AsRef { = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | fn ice() -> impl AsRef { | +++ @@ -21,7 +21,7 @@ LL | fn ice() -> impl AsRef { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | fn ice() -> impl AsRef { | +++ diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index d30fb3cfe58ab..ad770483e4a9b 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -7,7 +7,7 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let x: u8 = ::bitor(0 as u8, 0 as u8); | ++++ + @@ -35,7 +35,7 @@ LL | let g = BitXor::bitor; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let g = ::bitor; | ++++ + diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr index 6b0b42ca53a67..8dae3e7a91e12 100644 --- a/tests/ui/issues/issue-50781.stderr +++ b/tests/ui/issues/issue-50781.stderr @@ -29,7 +29,6 @@ LL | fn foo(&self) where Self: Trait; | ^^^ ...because method `foo` references the `Self` type in its `where` clause = help: consider moving `foo` to another trait = help: only type `()` implements the trait, consider using it directly instead - = note: required for the cast from `&()` to `&dyn X` error[E0038]: the trait `X` cannot be made into an object --> $DIR/issue-50781.rs:16:6 diff --git a/tests/ui/issues/issue-58734.stderr b/tests/ui/issues/issue-58734.stderr index 71581e96844ee..3130f919b277f 100644 --- a/tests/ui/issues/issue-58734.stderr +++ b/tests/ui/issues/issue-58734.stderr @@ -6,11 +6,8 @@ LL | Trait::nonexistent(()); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: you can't use write a trait object here because the trait isn't "object safe" = note: `#[warn(bare_trait_objects)]` on by default -help: if this is an object-safe trait, use `dyn` - | -LL | ::nonexistent(()); - | ++++ + error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope --> $DIR/issue-58734.rs:20:12 diff --git a/tests/ui/issues/issue-86756.stderr b/tests/ui/issues/issue-86756.stderr index d0906a6fa74f4..2ec5f42b90926 100644 --- a/tests/ui/issues/issue-86756.stderr +++ b/tests/ui/issues/issue-86756.stderr @@ -21,7 +21,7 @@ LL | eq:: = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | eq:: | +++ diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr index da1d9f248a01f..a92f1f9348a07 100644 --- a/tests/ui/lint/bare-trait-objects-path.stderr +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -7,7 +7,7 @@ LL | let _: Dyn::Ty; = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let _: ::Ty; | ++++ + @@ -26,7 +26,7 @@ LL | Dyn::func(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | ::func(); | ++++ + @@ -39,7 +39,7 @@ LL | ::Dyn::func(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | ::func(); | ++++++ ++ @@ -52,7 +52,7 @@ LL | Dyn::CONST; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | ::CONST; | ++++ + diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr index 388dc6160cb95..bbec1fc7abf74 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -7,7 +7,7 @@ LL | pub fn function(_x: Box) {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: requested on the command line with `--force-warn bare-trait-objects` -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr index a037fb671af29..de13121d87d41 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.stderr +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -7,7 +7,7 @@ LL | pub fn function(_x: Box) {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: requested on the command line with `--force-warn bare-trait-objects` -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr index a74cda2239f50..d5c4a840021b6 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -8,7 +8,7 @@ LL | pub fn function(_x: Box) {} = note: for more information, see = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]` -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr index c9472a3b9b9d3..380dead6eaedf 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -8,7 +8,7 @@ LL | pub fn function(_x: Box) {} = note: for more information, see = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]` -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr index 558d5cbb53156..7fb0fe2bcff5b 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -8,7 +8,7 @@ LL | pub fn function(_x: Box) {} = note: for more information, see = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]` -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr index f1f33a6c6d671..ddacb87b0c7f8 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr @@ -6,11 +6,8 @@ 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: you can't use write a trait object here because the trait isn't "object safe" = note: `#[warn(bare_trait_objects)]` on by default -help: if this is an object-safe trait, use `dyn` - | -LL | fn id(f: dyn Copy) -> usize { - | +++ warning: trait objects without an explicit `dyn` are deprecated --> $DIR/avoid-ice-on-warning-2.rs:4:13 @@ -20,11 +17,8 @@ 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: you can't use write a trait object here because the trait isn't "object safe" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn id(f: dyn Copy) -> usize { - | +++ error[E0038]: the trait `Copy` cannot be made into an object --> $DIR/avoid-ice-on-warning-2.rs:4:13 diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr index f499e2d946ffe..22cb607f5b7d6 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr @@ -1,55 +1,43 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:4:19 + --> $DIR/avoid-ice-on-warning-3.rs:12:19 | -LL | trait B { fn f(a: A) -> A; } +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: you can't use write a trait object here because the trait isn't "object safe" = note: `#[warn(bare_trait_objects)]` on by default -help: if this is an object-safe trait, use `dyn` - | -LL | trait B { fn f(a: dyn A) -> A; } - | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:4:25 + --> $DIR/avoid-ice-on-warning-3.rs:12:25 | -LL | trait B { fn f(a: A) -> A; } +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: if this is an object-safe trait, use `dyn` - | -LL | trait B { fn f(a: A) -> dyn A; } - | +++ + = note: you can't use write a trait object here because the trait isn't "object safe" warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | -LL | trait A { fn g(b: B) -> B; } +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: if this is an object-safe trait, use `dyn` - | -LL | trait A { fn g(b: dyn B) -> B; } - | +++ + = note: you can't use write a trait object here because the trait isn't "object safe" warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:25 + --> $DIR/avoid-ice-on-warning-3.rs:4:25 | -LL | trait A { fn g(b: B) -> B; } +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: if this is an object-safe trait, use `dyn` - | -LL | trait A { fn g(b: B) -> dyn B; } - | +++ + = note: you can't use write a trait object here because the trait isn't "object safe" warning: trait objects without an explicit `dyn` are deprecated --> $DIR/avoid-ice-on-warning-3.rs:4:19 @@ -59,11 +47,8 @@ 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: you can't use write a trait object here because the trait isn't "object safe" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | trait B { fn f(a: dyn A) -> A; } - | +++ error[E0038]: the trait `A` cannot be made into an object --> $DIR/avoid-ice-on-warning-3.rs:4:19 @@ -95,11 +80,8 @@ 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: you can't use write a trait object here because the trait isn't "object safe" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | trait A { fn g(b: dyn B) -> B; } - | +++ error[E0038]: the trait `B` cannot be made into an object --> $DIR/avoid-ice-on-warning-3.rs:12:19 diff --git a/tests/ui/object-safety/avoid-ice-on-warning.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr index 3939c06eabe5b..e97e24bb98528 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr @@ -18,11 +18,8 @@ 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: you can't use write a trait object here because the trait isn't "object safe" = note: `#[warn(bare_trait_objects)]` on by default -help: if this is an object-safe trait, use `dyn` - | -LL | fn call_this(f: F) : dyn Fn(&str) + call_that {} - | +++ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr index 0545a1afcc143..7163d86499839 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr @@ -6,15 +6,12 @@ LL | fn ord_prefer_dot(s: String) -> Ord { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: you can't use write a trait object here because the trait isn't "object safe" note: the lint level is defined here --> $DIR/bare-trait-dont-suggest-dyn.rs:5:9 | LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: if this is an object-safe trait, use `dyn` - | -LL | fn ord_prefer_dot(s: String) -> dyn Ord { - | +++ error[E0038]: the trait `Ord` cannot be made into an object --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33 diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr index 3134746b930ac..c04c330e09250 100644 --- a/tests/ui/parser/trait-object-trait-parens.stderr +++ b/tests/ui/parser/trait-object-trait-parens.stderr @@ -25,7 +25,7 @@ LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'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: `#[warn(bare_trait_objects)]` on by default -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let _: Box Trait<'a>)>; | +++ @@ -49,7 +49,7 @@ LL | let _: Box Trait<'a>) + (Obj)>; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let _: Box Trait<'a>) + (Obj)>; | +++ @@ -73,7 +73,7 @@ LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; | +++ diff --git a/tests/ui/suggestions/issue-116434-2015.rs b/tests/ui/suggestions/issue-116434-2015.rs index a53e2a044e93f..3e21284c9951a 100644 --- a/tests/ui/suggestions/issue-116434-2015.rs +++ b/tests/ui/suggestions/issue-116434-2015.rs @@ -3,10 +3,8 @@ trait Foo { fn foo() -> Clone; //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| HELP if this is an object-safe trait, use `dyn` //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| HELP if this is an object-safe trait, use `dyn` //~| ERROR the trait `Clone` cannot be made into an object [E0038] //~| HELP there is an associated type with the same name } @@ -18,10 +16,8 @@ trait DbInterface { fn handle() -> DbHandle; //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| HELP if this is an object-safe trait, use `dyn` //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| HELP if this is an object-safe trait, use `dyn` //~| ERROR the trait `DbHandle` cannot be made into an object [E0038] //~| HELP there is an associated type with the same name } diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr index 73a1cfa9c1d54..396936c02ada0 100644 --- a/tests/ui/suggestions/issue-116434-2015.stderr +++ b/tests/ui/suggestions/issue-116434-2015.stderr @@ -6,24 +6,18 @@ LL | fn foo() -> Clone; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: you can't use write a trait object here because the trait isn't "object safe" = note: `#[warn(bare_trait_objects)]` on by default -help: if this is an object-safe trait, use `dyn` - | -LL | fn foo() -> dyn Clone; - | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:18:20 + --> $DIR/issue-116434-2015.rs:16:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` - | -LL | fn handle() -> dyn DbHandle; - | +++ + = note: you can't use write a trait object here because the trait isn't "object safe" warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-116434-2015.rs:3:17 @@ -33,11 +27,8 @@ LL | fn foo() -> Clone; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: you can't use write a trait object here because the trait isn't "object safe" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn foo() -> dyn Clone; - | +++ error[E0038]: the trait `Clone` cannot be made into an object --> $DIR/issue-116434-2015.rs:3:17 @@ -53,27 +44,24 @@ LL | fn foo() -> Self::Clone; | ++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:18:20 + --> $DIR/issue-116434-2015.rs:16:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see + = note: you can't use write a trait object here because the trait isn't "object safe" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn handle() -> dyn DbHandle; - | +++ error[E0038]: the trait `DbHandle` cannot be made into an object - --> $DIR/issue-116434-2015.rs:18:20 + --> $DIR/issue-116434-2015.rs:16:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ `DbHandle` 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/issue-116434-2015.rs:14:17 + --> $DIR/issue-116434-2015.rs:12:17 | LL | trait DbHandle: Sized {} | -------- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr index 084b0cbeef292..faf7e95aa8e1d 100644 --- a/tests/ui/suggestions/issue-61963.stderr +++ b/tests/ui/suggestions/issue-61963.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | bar: Box, | +++ @@ -24,7 +24,7 @@ LL | pub struct Foo { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | dyn pub struct Foo { | +++ diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs index 75f99075eb18f..1b5ed995c5de1 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs @@ -11,6 +11,8 @@ trait B { } trait C { fn f(&self, a: C) -> C; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `C` cannot be made into an object } fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr index 55047b42698b5..c061fe80740f3 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr @@ -60,6 +60,35 @@ help: alternatively, consider constraining `f` so it does not apply to trait obj LL | fn f(a: B) -> B where Self: Sized; | +++++++++++++++++ -error: aborting due to 4 previous errors +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self.rs:13:20 + | +LL | trait C { + | - in this trait +LL | fn f(&self, a: C) -> C; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(&self, a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `C` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self.rs:13:20 + | +LL | fn f(&self, a: C) -> C; + | ----- ^ `C` cannot be made into an object + | | + | help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self` + | +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.rs:13:10 + | +LL | trait C { + | - this trait cannot be made into an object... +LL | fn f(&self, a: C) -> C; + | ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr index 5d805d97a4358..2b583a4f198d1 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr @@ -67,7 +67,7 @@ LL | impl<'a, T> Struct for Trait<'a, T> {} = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | impl<'a, T> Struct for dyn Trait<'a, T> {} | +++ @@ -80,7 +80,7 @@ LL | impl<'a, T> Enum for Trait<'a, T> {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | impl<'a, T> Enum for dyn Trait<'a, T> {} | +++ @@ -93,7 +93,7 @@ LL | impl<'a, T> Union for Trait<'a, T> {} | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | impl<'a, T> Union for dyn Trait<'a, T> {} | +++ diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr index 6f41f872e4cf6..78ba00c40d3a2 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr @@ -16,6 +16,10 @@ help: alternatively, use a trait object to accept any type that implements `Foo | LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + +help: add `dyn` keyword before this trait + | +LL | fn foo(_x: dyn Foo + Send) { + | +++ error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:11:11 @@ -35,6 +39,10 @@ help: alternatively, use a trait object to accept any type that implements `Foo` | LL | fn bar(x: &dyn Foo) -> Foo { | ++++ +help: add `dyn` keyword before this trait + | +LL | fn bar(x: dyn Foo) -> Foo { + | +++ error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:11:19 @@ -50,6 +58,10 @@ help: alternatively, you can return an owned trait object | LL | fn bar(x: Foo) -> Box { | +++++++ + +help: add `dyn` keyword before this trait + | +LL | fn bar(x: Foo) -> dyn Foo { + | +++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index f1e7a28654a74..471fb4988abca 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -7,7 +7,7 @@ LL | fn foo(_x: Foo + Send) { = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | fn foo(_x: dyn Foo + Send) { | +++ diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr index 3614348ceedc7..af8e671a64ac2 100644 --- a/tests/ui/traits/unspecified-self-in-trait-ref.stderr +++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr @@ -7,7 +7,7 @@ LL | let a = Foo::lol(); = 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: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let a = ::lol(); | ++++ + @@ -26,7 +26,7 @@ LL | let b = Foo::<_>::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let b = >::lol(); | ++++ + @@ -45,7 +45,7 @@ LL | let c = Bar::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let c = ::lol(); | ++++ + @@ -64,7 +64,7 @@ LL | let d = Bar::::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let d = >::lol(); | ++++ + @@ -83,7 +83,7 @@ LL | let e = Bar::::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: if this is an object-safe trait, use `dyn` +help: as this is an "object safe" trait, write `dyn` in front of the trait | LL | let e = >::lol(); | ++++ + diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs index 3f43fbfc0cf41..9cf87425f28b4 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs @@ -1,27 +1,10 @@ trait Trait { //~^ ERROR cannot find value `bar` in this scope - //~| ERROR cycle detected when computing type of `Trait::N` - //~| ERROR the trait `Trait` cannot be made into an object - //~| ERROR the trait `Trait` cannot be made into an object - //~| ERROR the trait `Trait` cannot be made into an object - //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| 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 [bare_trait_objects] - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| ERROR cycle detected when determining object safety of trait `Trait` fn fnc(&self) -> Trait { - //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters - //~| ERROR expected value, found builtin type `u32` - //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `Trait` cannot be made into an object - //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| 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 [bare_trait_objects] - //~| 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 [bare_trait_objects] - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters + //~| ERROR expected value, found builtin type `u32` + //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions bar //~^ ERROR cannot find value `bar` in this scope } diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr index f2456f99e6233..e45cdd8b6fea2 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr @@ -1,5 +1,5 @@ error[E0403]: the name `N` is already used for a generic parameter in this item's generic parameters - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:18 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:18 | LL | trait Trait { | - first use of `N` @@ -14,201 +14,63 @@ LL | trait Trait { | ^^^ not found in this scope error[E0423]: expected value, found builtin type `u32` - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:29 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:29 | LL | fn fnc(&self) -> Trait { | ^^^ not a value error[E0425]: cannot find value `bar` in this scope - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:25:9 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:8:9 | LL | bar | ^^^ not found in this scope -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 - | -LL | trait Trait { - | ^^^^^ - | - = 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: if this is an object-safe trait, use `dyn` - | -LL | trait Trait { - | +++ - -error[E0391]: cycle detected when computing type of `Trait::N` - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 - | -LL | trait Trait { - | ^^^^^ - | - = note: ...which immediately requires computing type of `Trait::N` again -note: cycle used when computing explicit predicates of trait `Trait` - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1 - | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:12 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:12 | LL | fn fnc(&self) -> Trait { | ^^^^^^^^^^^^^^^^^^^^ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 - | -LL | fn fnc(&self) -> Trait { - | ^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see -help: if this is an object-safe trait, use `dyn` - | -LL | fn fnc(&self) -> Trait { - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44 - | -LL | fn fnc(&self) -> Trait { - | ^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see -help: if this is an object-safe trait, use `dyn` - | -LL | fn fnc(&self) -> dyn Trait { - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 - | -LL | trait Trait { - | ^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | trait Trait { - | +++ - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 - | -LL | trait Trait { - | ^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 - | -LL | trait Trait { - | ----- this trait cannot be made into an object... -... -LL | fn fnc(&self) -> Trait { - | ^^^ ...because method `fnc` has generic type parameters - = help: consider moving `fnc` to another trait - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:13 +error[E0391]: cycle detected when determining object safety of trait `Trait` + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1 | LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 +note: ...which requires check whether the item has a `where Self: Sized` bound... + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:5 | -LL | trait Trait { - | ----- this trait cannot be made into an object... -... LL | fn fnc(&self) -> Trait { - | ^^^ ...because method `fnc` has generic type parameters - = help: consider moving `fnc` to another trait - -error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 - | -LL | trait Trait { - | ^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - -error: associated item referring to unboxed trait object for its own trait - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing predicates of `Trait::fnc`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:5 | -LL | trait Trait { - | ----- in this trait -... LL | fn fnc(&self) -> Trait { - | ^^^^^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL | fn fnc(&self) -> Self { - | ~~~~ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing predicates of `Trait::fnc`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:5 | LL | fn fnc(&self) -> Trait { - | ^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn fnc(&self) -> Trait { - | +++ - -error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing explicit predicates of `Trait::fnc`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:5 | LL | fn fnc(&self) -> Trait { - | ^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing type of `Trait::fnc::N`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:4:12 | -LL | trait Trait { - | ----- this trait cannot be made into an object... -... LL | fn fnc(&self) -> Trait { - | ^^^ ...because method `fnc` has generic type parameters - = help: consider moving `fnc` to another trait - -error[E0038]: the trait `Trait` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires determining object safety of trait `Trait`, completing the cycle +note: cycle used when computing type of `Trait::N` --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:13 | LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 - | -LL | trait Trait { - | ----- this trait cannot be made into an object... -... -LL | fn fnc(&self) -> Trait { - | ^^^ ...because method `fnc` has generic type parameters - = help: consider moving `fnc` to another trait - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 - | -LL | fn fnc(&self) -> Trait { - | ^^^^^ - | - = note: the only supported types are integers, `bool` and `char` + | ^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 13 previous errors; 5 warnings emitted +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0038, E0391, E0403, E0423, E0425. -For more information about an error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0391, E0403, E0423, E0425. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs index a953f1818c580..5e271c0ca1f25 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs @@ -1,17 +1,10 @@ // Regression test for ICE #122989 trait Foo> { - //~^ 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 cycle detected when computing type of `Foo::N` - //~| ERROR the trait `Foo` cannot be made into an object - //~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter - fn func() {} + //~^ ERROR cycle detected when computing predicates of `Foo` + fn func() { + } } trait Bar> {} -//~^ 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 `Foo` cannot be made into an object -//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr index a0fd11de2dc6f..7e2339b59484b 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr @@ -1,112 +1,82 @@ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20 +error[E0391]: cycle detected when computing predicates of `Foo` + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 | LL | trait Foo> { - | ^^^^^^ - | - = 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: if this is an object-safe trait, use `dyn` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | trait Foo> { - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 +note: ...which requires computing predicates of `Foo`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 | -LL | trait Bar> {} - | ^^^^^^ +LL | trait Foo> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing explicit predicates of `Foo`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see -help: if this is an object-safe trait, use `dyn` +LL | trait Foo> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing explicit predicates of trait `Foo`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 | -LL | trait Bar> {} - | +++ - -error[E0391]: cycle detected when computing type of `Foo::N` +LL | trait Foo> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing type of `Foo::N`... --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11 | LL | trait Foo> { | ^^^^^^^^^^^^^^^ - | -note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 +note: ...which requires determining object safety of trait `Bar`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:1 | LL | trait Bar> {} - | ^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::N`, completing the cycle -note: cycle used when computing explicit predicates of trait `Foo` - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 - | -LL | trait Foo> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:24 - | -LL | trait Foo> { - | ^ `Foo` cannot be made into an object +note: ...which requires check whether the item has a `where Self: Sized` bound... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:1 | -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/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 +LL | trait Bar> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing predicates of `Bar`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:1 | -LL | trait Foo> { - | --- this trait cannot be made into an object... -... -LL | fn func() {} - | ^^^^ ...because associated function `func` has no `self` parameter -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) {} - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized {} - | +++++++++++++++++ - -error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20 +LL | trait Bar> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing predicates of `Bar`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:1 | -LL | trait Foo> { - | ^^^^^^ +LL | trait Bar> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing explicit predicates of `Bar`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:1 | - = note: the only supported types are integers, `bool` and `char` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 +LL | trait Bar> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing explicit predicates of trait `Bar`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:1 | LL | trait Bar> {} - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing type of `Bar::M`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:11 | -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/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 +LL | trait Bar> {} + | ^^^^^^^^^^^^^^^ +note: ...which requires determining object safety of trait `Foo`... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 | LL | trait Foo> { - | --- this trait cannot be made into an object... -... -LL | fn func() {} - | ^^^^ ...because associated function `func` has no `self` parameter -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) {} - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized {} - | +++++++++++++++++ - -error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires check whether the item has a `where Self: Sized` bound... + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:4:5 | -LL | trait Bar> {} - | ^^^^^^ +LL | fn func() { + | ^^^^^^^^^ + = note: ...which again requires computing predicates of `Foo`, completing the cycle +note: cycle used when checking that `Foo` is well-formed + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 | - = note: the only supported types are integers, `bool` and `char` +LL | trait Foo> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 5 previous errors; 2 warnings emitted +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0391. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0391`. From adc750fa94502040a8bbbecc56be5a531e02650c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Jun 2024 23:29:57 +0000 Subject: [PATCH 13/26] Suggest `<_ as Default>::default()` when given `::default()` --- .../src/hir_ty_lowering/lint.rs | 8 ++++++++ ...ssing-dyn-in-qualified-path.edition2021.stderr | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index e5af709f4aed6..d5da198db4286 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -2,6 +2,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::{codes::*, Diag, EmissionGuarantee, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; +use rustc_infer::traits::error_reporting::suggest_path_on_bare_trait; use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; @@ -80,6 +81,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } } + + if !object_safe && self_ty.span.can_be_used_for_suggestions() { + // suggest_impl_trait_on_bare_trait(tcx, &mut diag, self_ty); + let parent = tcx.parent_hir_node(self_ty.hir_id); + suggest_path_on_bare_trait(tcx, &mut diag, parent); + } + // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr index 3f7430241ce8c..1374e138d69ce 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr @@ -3,6 +3,21 @@ error[E0782]: trait objects must include the `dyn` keyword | LL | let x: u32 = ::default(); | ^^^^^^^ + | + = help: when writing `::default` you are requiring `Default` be "object safe", which it isn't +help: you might have meant to access the associated function of a specific `impl` to avoid requiring "object safety" from `Default`, either with some explicit type... + | +LL | let x: u32 = ::default(); + | +++++++++++++ +help: ...or rely on inference if the compiler has enough context to identify the desired type on its own... + | +LL - let x: u32 = ::default(); +LL + let x: u32 = Default::default(); + | +help: ...which is equivalent to + | +LL | let x: u32 = <_ as Default>::default(); + | ++++ error: aborting due to 1 previous error From dd7b36f470ba83677a0db5463555bbca7ca6888b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Jun 2024 23:31:14 +0000 Subject: [PATCH 14/26] review comment: `guard` -> `guar` --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 2ebb0ce3dfb36..fd3bd3bce4f42 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2069,8 +2069,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - if let Some(guard) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path) { - return Ty::new_error(tcx, guard); + if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path) { + return Ty::new_error(tcx, guar); } let repr = match repr { From e6d90507d05e4e92d5c5bd4d53974ba0cbfca369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Jun 2024 23:37:57 +0000 Subject: [PATCH 15/26] review comment: unnecessary check for object safety on sized trait --- .../error_reporting/type_err_ctxt_ext.rs | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index fb64ea0e9e653..11d540b8dd90b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -638,20 +638,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.span_label(span, explanation); } - if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { - if !self.tcx.object_safety_violations(trait_ref.def_id()).is_empty() { - if let ObligationCauseCode::SizedCallReturnType(did) - = obligation.cause.code() - { - let fn_sig = self.tcx.fn_sig(did); - let ret_kind = - fn_sig.skip_binder().output().skip_binder().kind(); - if let ty::Param(param_ty) = ret_kind - && param_ty.name == kw::SelfUpper - { - return err.delay_as_bug(); - } - } + if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() + && let ObligationCauseCode::SizedCallReturnType(did) + = obligation.cause.code() + { + let fn_sig = self.tcx.fn_sig(did); + let ret_kind = + fn_sig.skip_binder().output().skip_binder().kind(); + if let ty::Param(param_ty) = ret_kind + && param_ty.name == kw::SelfUpper + { + return err.delay_as_bug(); } } From 5f22c02425acc230457ba2d609df3cbd3e17c0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Jun 2024 23:49:32 +0000 Subject: [PATCH 16/26] Add explanatory comment --- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 11d540b8dd90b..ccd61263b651f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -648,6 +648,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let ty::Param(param_ty) = ret_kind && param_ty.name == kw::SelfUpper { + // We expect the return type of an fn call is expected to be + // `Sized`. In the test `trait-missing-dyn-in-qualified-path.rs` + // under edition 2018, when writing `::default()`, we will + // check both `dyn Default` and `::default()` for + // being `Sized`, but in every case where an associated function + // like `Default::default` which returns `Self`, if the returned + // value is `!Sized`, so will be the `Self`, so we'd always have + // two redundat errors. return err.delay_as_bug(); } } From 84be44bda8e6b767adf9f60dbead04f1ce258e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 10 Jun 2024 17:20:42 +0000 Subject: [PATCH 17/26] Fix tidy --- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index ccd61263b651f..1dd4ddc8e491b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -649,7 +649,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && param_ty.name == kw::SelfUpper { // We expect the return type of an fn call is expected to be - // `Sized`. In the test `trait-missing-dyn-in-qualified-path.rs` + // `Sized`. In the test `trait-missing-dyn-in-qualified-path.rs` // under edition 2018, when writing `::default()`, we will // check both `dyn Default` and `::default()` for // being `Sized`, but in every case where an associated function From d8f5b144b7d1050ca6f4eb5f8f69b82a43b9213c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 10 Jun 2024 18:18:26 +0000 Subject: [PATCH 18/26] Remove conditional delay_as_bug from "missing `dyn` error" --- .../src/hir_ty_lowering/lint.rs | 13 +--- .../avoid-ice-on-warning-2.new.stderr | 40 +++------- .../avoid-ice-on-warning-2.old.stderr | 2 +- .../object-safety/avoid-ice-on-warning-2.rs | 7 +- .../avoid-ice-on-warning-3.new.stderr | 74 +++++++++++-------- .../avoid-ice-on-warning-3.old.stderr | 10 +-- .../object-safety/avoid-ice-on-warning-3.rs | 8 +- .../avoid-ice-on-warning.new.stderr | 16 +++- .../ui/object-safety/avoid-ice-on-warning.rs | 1 + .../bare-trait-dont-suggest-dyn.new.fixed | 3 +- .../bare-trait-dont-suggest-dyn.new.stderr | 15 +--- .../bare-trait-dont-suggest-dyn.rs | 3 +- tests/ui/suggestions/issue-116434-2021.rs | 8 +- tests/ui/suggestions/issue-116434-2021.stderr | 31 +++----- 14 files changed, 107 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index d5da198db4286..209977605f5f9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -68,10 +68,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let label = "add `dyn` keyword before this trait"; let mut diag = rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); - let mut downgrade = false; if self_ty.span.can_be_used_for_suggestions() { - let should_downgrade = self.maybe_suggest_impl_trait(self_ty, &mut diag); - downgrade = should_downgrade; + self.maybe_suggest_impl_trait(self_ty, &mut diag); if object_safe { // Only emit this suggestion if the trait is object safe. diag.multipart_suggestion_verbose( @@ -91,14 +89,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - if downgrade { - // FIXME: Delayed bugs and stashing are not compatible, so we paper over it here by - // consuming the diagnostic without emitting it, instead of downgrading it. - diag.delay_as_bug(); - None - } else { - diag.stash(self_ty.span, StashKey::TraitMissingMethod) - } + diag.stash(self_ty.span, StashKey::TraitMissingMethod) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr index 0bc396390d7d2..a6cb07f5aa712 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr @@ -1,41 +1,19 @@ -error[E0038]: the trait `Copy` cannot be made into an object +error[E0782]: trait objects must include the `dyn` keyword --> $DIR/avoid-ice-on-warning-2.rs:4: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[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 - | -LL | fn id(f: Copy) -> usize { - | - `f` has type `(dyn Copy + 'static)` -... -LL | f() - | ^-- - | | - | call expression requires function - -error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time - --> $DIR/avoid-ice-on-warning-2.rs:4:10 + = note: `Copy` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` | -LL | fn id(f: Copy) -> usize { - | ^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type +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 { | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn id(f: &dyn Copy) -> usize { - | ++++ -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0277, E0618. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr index ddacb87b0c7f8..21c405ce6ce55 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr @@ -30,7 +30,7 @@ LL | fn id(f: Copy) -> usize { = 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[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 + --> $DIR/avoid-ice-on-warning-2.rs:12:5 | LL | fn id(f: Copy) -> usize { | - `f` has type `(dyn Copy + 'static)` diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/object-safety/avoid-ice-on-warning-2.rs index db2f4aea05b58..5b12038b0af16 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs @@ -2,13 +2,14 @@ //@[old] edition:2015 //@[new] edition:2021 fn id(f: Copy) -> usize { -//~^ ERROR the trait `Copy` cannot be made into an object -//~| ERROR: the size for values of type `(dyn Copy + 'static)` +//[new]~^ ERROR trait objects must include the `dyn` keyword +//[old]~^^ ERROR the trait `Copy` cannot be made into an object +//[old]~| ERROR the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! f() - //~^ ERROR: expected function, found `(dyn Copy + 'static)` + //[old]~^ ERROR: expected function, found `(dyn Copy + 'static)` } fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr index fd92d43ef9a24..19b9b4c729deb 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr @@ -1,47 +1,57 @@ -error[E0038]: the trait `A` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:4:19 +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | -LL | trait B { fn f(a: A) -> A; } - | ^ `A` cannot be made into an object +LL | trait A { fn g(b: B) -> B; } + | ^ | -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:12:14 + = note: `B` it is not object safe, so it can't be `dyn` +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[E0782]: trait objects must include the `dyn` keyword + --> $DIR/avoid-ice-on-warning-3.rs:14:25 | 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 +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) -> B where Self: Sized; } - | +++++++++++++++++ +LL | trait A { fn g(b: B) -> impl B; } + | ++++ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | -LL | trait A { fn g(b: B) -> B; } - | ^ `B` cannot be made into an object +LL | trait B { fn f(a: A) -> A; } + | ^ | -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:4:14 + = 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; } + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/avoid-ice-on-warning-3.rs:4:25 | 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 +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) -> A where Self: Sized; } - | +++++++++++++++++ +LL | trait B { fn f(a: A) -> impl A; } + | ++++ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr index 22cb607f5b7d6..9bdfdb2ab4c1f 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr @@ -1,5 +1,5 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -10,7 +10,7 @@ LL | trait A { fn g(b: B) -> B; } = note: `#[warn(bare_trait_objects)]` on by default warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:25 + --> $DIR/avoid-ice-on-warning-3.rs:14:25 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -57,7 +57,7 @@ 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:12:14 + --> $DIR/avoid-ice-on-warning-3.rs:14:14 | LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter @@ -73,7 +73,7 @@ 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:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -84,7 +84,7 @@ LL | trait A { fn g(b: B) -> B; } = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ `B` cannot be made into an object diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/object-safety/avoid-ice-on-warning-3.rs index 38bee8142bb9a..1a51b6c823a38 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.rs @@ -2,7 +2,9 @@ //@[old] edition:2015 //@[new] edition:2021 trait B { fn f(a: A) -> A; } -//~^ ERROR the trait `A` cannot be made into an object +//[new]~^ ERROR trait objects must include the `dyn` keyword +//[new]~| ERROR trait objects must include the `dyn` keyword +//[old]~^^^ ERROR the trait `A` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated @@ -10,7 +12,9 @@ trait B { fn f(a: A) -> A; } //[old]~| WARN this is accepted in the current edition //[old]~| WARN this is accepted in the current edition trait A { fn g(b: B) -> B; } -//~^ ERROR the trait `B` cannot be made into an object +//[new]~^ ERROR trait objects must include the `dyn` keyword +//[new]~| ERROR trait objects must include the `dyn` keyword +//[old]~^^^ ERROR the trait `B` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated diff --git a/tests/ui/object-safety/avoid-ice-on-warning.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning.new.stderr index 517f910080de7..7624250ec0b15 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.new.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning.new.stderr @@ -10,6 +10,18 @@ error[E0405]: cannot find trait `call_that` in this scope LL | fn call_this(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/avoid-ice-on-warning.rs:4:25 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^^^^^^^^^^^^ + | +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 3 previous errors -For more information about this error, try `rustc --explain E0405`. +Some errors have detailed explanations: E0405, E0782. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs index b90d8911d500b..920e10becf18e 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning.rs @@ -4,6 +4,7 @@ fn call_this(f: F) : Fn(&str) + call_that {} //~^ ERROR return types are denoted using `->` //~| ERROR cannot find trait `call_that` in this scope +//[new]~| ERROR trait objects must include the `dyn` keyword //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| 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/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed index 4f5310082e18d..a81541dedaed7 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> impl Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR trait objects must include the `dyn` keyword + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr index efddab6dff63d..99a9694fc341f 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr @@ -1,21 +1,14 @@ -error[E0038]: the trait `Ord` cannot be made into an object +error[E0782]: trait objects must include the `dyn` keyword --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33 | LL | fn ord_prefer_dot(s: String) -> Ord { - | ^^^ `Ord` 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 - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - ::: $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter -help: consider using an opaque type instead +help: `Ord` is not object safe, use `impl Ord` to return an opaque type, as long as you return a single underlying type | LL | fn ord_prefer_dot(s: String) -> impl Ord { | ++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs index cb5a305eab087..2ea1324abcdd8 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR trait objects must include the `dyn` keyword + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs index 6feba3dc6c16d..4f13d3fac3d73 100644 --- a/tests/ui/suggestions/issue-116434-2021.rs +++ b/tests/ui/suggestions/issue-116434-2021.rs @@ -3,8 +3,8 @@ trait Foo { type Clone; fn foo() -> Clone; - //~^ ERROR the trait `Clone` cannot be made into an object [E0038] - //~| HELP there is an associated type with the same name + //~^ ERROR trait objects must include the `dyn` keyword + //~| HELP `Clone` is not object safe, use `impl Clone` to return an opaque type, as long as you return a single underlying type } trait DbHandle: Sized {} @@ -12,8 +12,8 @@ trait DbHandle: Sized {} trait DbInterface { type DbHandle; fn handle() -> DbHandle; - //~^ ERROR the trait `DbHandle` cannot be made into an object [E0038] - //~| HELP there is an associated type with the same name + //~^ ERROR trait objects must include the `dyn` keyword + //~| HELP `DbHandle` is not object safe, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type } fn main() {} diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr index a10d6ef6da4d9..e60f60357ea8a 100644 --- a/tests/ui/suggestions/issue-116434-2021.stderr +++ b/tests/ui/suggestions/issue-116434-2021.stderr @@ -1,34 +1,25 @@ -error[E0038]: the trait `Clone` cannot be made into an object +error[E0782]: trait objects must include the `dyn` keyword --> $DIR/issue-116434-2021.rs:5:17 | LL | fn foo() -> Clone; - | ^^^^^ `Clone` 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 -help: there is an associated type with the same name +help: `Clone` is not object safe, use `impl Clone` to return an opaque type, as long as you return a single underlying type | -LL | fn foo() -> Self::Clone; - | ++++++ +LL | fn foo() -> impl Clone; + | ++++ -error[E0038]: the trait `DbHandle` cannot be made into an object +error[E0782]: trait objects must include the `dyn` keyword --> $DIR/issue-116434-2021.rs:14:20 | LL | fn handle() -> DbHandle; - | ^^^^^^^^ `DbHandle` 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/issue-116434-2021.rs:10:17 +help: `DbHandle` is not object safe, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type | -LL | trait DbHandle: Sized {} - | -------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... -help: there is an associated type with the same name - | -LL | fn handle() -> Self::DbHandle; - | ++++++ +LL | fn handle() -> impl DbHandle; + | ++++ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. From 8ee6812c282bb0dd65a460ccc88c0a8b49e40f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 10 Jun 2024 18:26:42 +0000 Subject: [PATCH 19/26] Remove `delay_as_bug` for fn call with unsized `Self` that return `Self`. --- .../error_reporting/type_err_ctxt_ext.rs | 24 +------------------ ...g-dyn-in-qualified-path.edition2018.stderr | 11 ++++++++- .../trait-missing-dyn-in-qualified-path.rs | 1 + 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 1dd4ddc8e491b..46bb8adb8e566 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -48,7 +48,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::sym; use rustc_span::{BytePos, ExpnKind, Span, Symbol, DUMMY_SP}; use std::borrow::Cow; use std::fmt; @@ -638,28 +638,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.span_label(span, explanation); } - if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() - && let ObligationCauseCode::SizedCallReturnType(did) - = obligation.cause.code() - { - let fn_sig = self.tcx.fn_sig(did); - let ret_kind = - fn_sig.skip_binder().output().skip_binder().kind(); - if let ty::Param(param_ty) = ret_kind - && param_ty.name == kw::SelfUpper - { - // We expect the return type of an fn call is expected to be - // `Sized`. In the test `trait-missing-dyn-in-qualified-path.rs` - // under edition 2018, when writing `::default()`, we will - // check both `dyn Default` and `::default()` for - // being `Sized`, but in every case where an associated function - // like `Default::default` which returns `Self`, if the returned - // value is `!Sized`, so will be the `Self`, so we'd always have - // two redundat errors. - return err.delay_as_bug(); - } - } - if let ObligationCauseCode::Coercion { source, target, .. } = *obligation.cause.code().peel_derives() { diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr index 223e260584e74..bd0f46ec7f4a6 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr @@ -68,7 +68,16 @@ LL | let x: u32 = ::default(); = 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 4 previous errors; 1 warning emitted +error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time + --> $DIR/trait-missing-dyn-in-qualified-path.rs:5:18 + | +LL | let x: u32 = ::default(); + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Default` + = note: the return type of a function must have a statically known size + +error: aborting due to 5 previous errors; 1 warning emitted Some errors have detailed explanations: E0038, E0277, E0308. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs index d15b17993e45f..a237f2a719599 100644 --- a/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs +++ b/tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.rs @@ -8,6 +8,7 @@ fn main() { //[edition2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! //[edition2018]~| ERROR trait `Default` cannot be made into an object //[edition2018]~| ERROR trait `Default` cannot be made into an object + //[edition2018]~| ERROR the size for values of type `dyn Default` cannot be known at compilation time //[edition2018]~| ERROR mismatched types //[edition2018]~| ERROR the size for values of type `dyn Default` cannot be known at compilation time } From 8140dcd4b8a36129e865361b25f6a9bd19ffff07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 10 Jun 2024 21:11:25 +0000 Subject: [PATCH 20/26] Emit method not found error for object safe traits without `dyn` Given `Trait::foo()` in edition 2021 where `Trait` is object safe and `foo` isn't resolved, emit E0782 instead of marking the expression as `{type error}`, as `foo` not being part of `Trait` is more useful information. If `Trait` *isn't* object safe, then the resolve error isn't as useful because E0782 will have more actionable feedback. --- .../src/hir_ty_lowering/lint.rs | 20 ++++++++++++++++- tests/ui/resolve/issue-111312.rs | 3 ++- tests/ui/resolve/issue-111312.stderr | 22 ++++++++++++++----- tests/ui/resolve/issue-111727.rs | 3 ++- tests/ui/resolve/issue-111727.stderr | 11 ++++++++-- 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 209977605f5f9..b1f350c5d081f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -81,7 +81,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if !object_safe && self_ty.span.can_be_used_for_suggestions() { - // suggest_impl_trait_on_bare_trait(tcx, &mut diag, self_ty); let parent = tcx.parent_hir_node(self_ty.hir_id); suggest_path_on_bare_trait(tcx, &mut diag, parent); } @@ -89,6 +88,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); + + if object_safe { + let parents = self.tcx().hir().parent_iter(self_ty.hir_id); + for (_, parent) in parents { + let hir::Node::Expr(expr) = parent else { + break; + }; + if let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = expr.kind + && let Res::Err = segment.res + { + // If the trait is object safe *and* there's a path segment that couldn't be + // resolved, we know that we will have a resolve error later. If there's an + // unresolved segment *and* the trait is not object safe, then no other + // error would have been emitted, so we always emit an error in that case. + diag.emit(); + return None; + } + } + } diag.stash(self_ty.span, StashKey::TraitMissingMethod) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs index c8de1570cd093..efb750de12fb7 100644 --- a/tests/ui/resolve/issue-111312.rs +++ b/tests/ui/resolve/issue-111312.rs @@ -7,6 +7,7 @@ trait Has { trait HasNot {} fn main() { - ::has(); + HasNot::has(); //~^ ERROR no function or associated item named `has` found for trait `HasNot` + //~| ERROR trait objects must include the `dyn` keyword } diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr index 99bc1c4437728..431802ead30c4 100644 --- a/tests/ui/resolve/issue-111312.stderr +++ b/tests/ui/resolve/issue-111312.stderr @@ -1,8 +1,19 @@ -error[E0599]: no function or associated item named `has` found for trait `HasNot` - --> $DIR/issue-111312.rs:10:19 +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/issue-111312.rs:10:5 + | +LL | HasNot::has(); + | ^^^^^^ + | +help: add `dyn` keyword before this trait | LL | ::has(); - | ^^^ function or associated item not found in `HasNot` + | ++++ + + +error[E0599]: no function or associated item named `has` found for trait `HasNot` + --> $DIR/issue-111312.rs:10:13 + | +LL | HasNot::has(); + | ^^^ function or associated item not found in `HasNot` | note: `Has` defines an item `has` --> $DIR/issue-111312.rs:3:1 @@ -10,6 +21,7 @@ note: `Has` defines an item `has` LL | trait Has { | ^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. +Some errors have detailed explanations: E0599, E0782. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs index b698c1dc1b167..19b8b2eb32e82 100644 --- a/tests/ui/resolve/issue-111727.rs +++ b/tests/ui/resolve/issue-111727.rs @@ -2,5 +2,6 @@ fn main() { std::any::Any::create(); - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR no function or associated item named `create` found for trait `Any` + //~| ERROR trait objects must include the `dyn` keyword } diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr index 4cb280cfed950..1ef5a1a1d5efb 100644 --- a/tests/ui/resolve/issue-111727.stderr +++ b/tests/ui/resolve/issue-111727.stderr @@ -9,6 +9,13 @@ help: add `dyn` keyword before this trait LL | ::create(); | ++++ + -error: aborting due to 1 previous error +error[E0599]: no function or associated item named `create` found for trait `Any` + --> $DIR/issue-111727.rs:4:20 + | +LL | std::any::Any::create(); + | ^^^^^^ function or associated item not found in `Any` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0782`. +Some errors have detailed explanations: E0599, E0782. +For more information about an error, try `rustc --explain E0599`. From f116d4d42c2e652aaf7720a717a07c407bf86ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 10 Jun 2024 21:56:49 +0000 Subject: [PATCH 21/26] Move tests that no longer ICE --- .../traits/missing-dyn-trait-2.rs} | 0 tests/ui/traits/missing-dyn-trait-2.stderr | 57 +++++++++++++++++++ .../traits/missing-dyn-trait-3.rs} | 0 tests/ui/traits/missing-dyn-trait-3.stderr | 57 +++++++++++++++++++ .../traits/missing-dyn-trait-4.rs} | 0 tests/ui/traits/missing-dyn-trait-4.stderr | 19 +++++++ .../traits/missing-dyn-trait.rs} | 0 tests/ui/traits/missing-dyn-trait.stderr | 30 ++++++++++ 8 files changed, 163 insertions(+) rename tests/{crashes/125512.rs => ui/traits/missing-dyn-trait-2.rs} (100%) create mode 100644 tests/ui/traits/missing-dyn-trait-2.stderr rename tests/{crashes/120241.rs => ui/traits/missing-dyn-trait-3.rs} (100%) create mode 100644 tests/ui/traits/missing-dyn-trait-3.stderr rename tests/{crashes/120241-2.rs => ui/traits/missing-dyn-trait-4.rs} (100%) create mode 100644 tests/ui/traits/missing-dyn-trait-4.stderr rename tests/{crashes/120482.rs => ui/traits/missing-dyn-trait.rs} (100%) create mode 100644 tests/ui/traits/missing-dyn-trait.stderr diff --git a/tests/crashes/125512.rs b/tests/ui/traits/missing-dyn-trait-2.rs similarity index 100% rename from tests/crashes/125512.rs rename to tests/ui/traits/missing-dyn-trait-2.rs diff --git a/tests/ui/traits/missing-dyn-trait-2.stderr b/tests/ui/traits/missing-dyn-trait-2.stderr new file mode 100644 index 0000000000000..62234465283f1 --- /dev/null +++ b/tests/ui/traits/missing-dyn-trait-2.stderr @@ -0,0 +1,57 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-2.rs:8:20 + | +LL | fn concrete(b: B) -> B; + | ^ + | + = note: `B` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn concrete(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 | fn concrete(b: impl B) -> B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-2.rs:8:26 + | +LL | fn concrete(b: B) -> B; + | ^ + | +help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn concrete(b: B) -> impl B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-2.rs:5:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is not object safe, so it can't be `dyn` +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; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-2.rs:5:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/crashes/120241.rs b/tests/ui/traits/missing-dyn-trait-3.rs similarity index 100% rename from tests/crashes/120241.rs rename to tests/ui/traits/missing-dyn-trait-3.rs diff --git a/tests/ui/traits/missing-dyn-trait-3.stderr b/tests/ui/traits/missing-dyn-trait-3.stderr new file mode 100644 index 0000000000000..650c11d546c01 --- /dev/null +++ b/tests/ui/traits/missing-dyn-trait-3.stderr @@ -0,0 +1,57 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-3.rs:10:13 + | +LL | fn g(b: B) -> B; + | ^ + | + = note: `B` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | 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 | fn g(b: impl B) -> B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-3.rs:10:19 + | +LL | fn g(b: B) -> B; + | ^ + | +help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(b: B) -> impl B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-3.rs:6:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is not object safe, so it can't be `dyn` +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; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-3.rs:6:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/crashes/120241-2.rs b/tests/ui/traits/missing-dyn-trait-4.rs similarity index 100% rename from tests/crashes/120241-2.rs rename to tests/ui/traits/missing-dyn-trait-4.rs diff --git a/tests/ui/traits/missing-dyn-trait-4.stderr b/tests/ui/traits/missing-dyn-trait-4.stderr new file mode 100644 index 0000000000000..af5fa572fa81b --- /dev/null +++ b/tests/ui/traits/missing-dyn-trait-4.stderr @@ -0,0 +1,19 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait-4.rs:6:14 + | +LL | fn guard(_s: Copy) -> bool { + | ^^^^ + | + = note: `Copy` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn guard(_s: T) -> bool { + | +++++++++ ~ +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 guard(_s: impl Copy) -> bool { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/crashes/120482.rs b/tests/ui/traits/missing-dyn-trait.rs similarity index 100% rename from tests/crashes/120482.rs rename to tests/ui/traits/missing-dyn-trait.rs diff --git a/tests/ui/traits/missing-dyn-trait.stderr b/tests/ui/traits/missing-dyn-trait.stderr new file mode 100644 index 0000000000000..45ed425435c71 --- /dev/null +++ b/tests/ui/traits/missing-dyn-trait.stderr @@ -0,0 +1,30 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait.rs:10:15 + | +LL | fn g(new: B) -> B; + | ^ + | + = note: `B` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn g(new: 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 g(new: impl B) -> B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/missing-dyn-trait.rs:10:21 + | +LL | fn g(new: B) -> B; + | ^ + | +help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(new: B) -> impl B; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0782`. From aec9eeba18e357f905e453081bf21764b01c9797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 10 Jun 2024 23:53:20 +0000 Subject: [PATCH 22/26] Do not produce incorrect `dyn Trait` suggestion in `fn` ``` error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:8:12 | LL | fn foo(_x: Foo + Send) { | ^^^^^^^^^^ | help: use a new generic type parameter, constrained by `Foo + Send` | LL | fn foo(_x: T) { | +++++++++++++++ ~ 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 foo(_x: impl Foo + Send) { | ++++ help: alternatively, use a trait object to accept any type that implements `Foo + Send`, accessing its methods at runtime using dynamic dispatch | LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + - help: add `dyn` keyword before this trait - | - LL | fn foo(_x: dyn Foo + Send) { - | +++ ``` --- .../src/hir_ty_lowering/lint.rs | 34 +++++-------------- .../bound/not-on-bare-trait-2021.stderr | 12 ------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index b1f350c5d081f..9b44c621bd214 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -69,8 +69,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut diag = rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); if self_ty.span.can_be_used_for_suggestions() { - self.maybe_suggest_impl_trait(self_ty, &mut diag); - if object_safe { + if !self.maybe_suggest_impl_trait(self_ty, &mut diag) && object_safe { // Only emit this suggestion if the trait is object safe. diag.multipart_suggestion_verbose( label, @@ -212,34 +211,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0` // and suggest `Trait0`. - let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { - (sig, generics, None) + (sig, generics) } hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; - let mut is_downgradable = true; - let mut downgrade = false; 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 { - // For recursive traits, don't downgrade the error. (#119652) - is_downgradable = false; - } - tcx.object_safety_violations(id).is_empty() - } + Res::Def(DefKind::Trait, id) => tcx.object_safety_violations(id).is_empty(), _ => false, }) } @@ -267,11 +257,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ], Applicability::MachineApplicable, ); - } else if is_downgradable { - // We'll emit the object safety error already, with a structured suggestion. - downgrade = true; + return true; } - return downgrade; + return false; } for ty in sig.decl.inputs { if ty.hir_id != self_ty.hir_id { @@ -293,10 +281,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); - if is_downgradable { - // We'll emit the object safety error already, with a structured suggestion. - downgrade = true; - } } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. @@ -316,9 +300,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MachineApplicable, ); } - return downgrade; + return true; } - downgrade + false } fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr index 78ba00c40d3a2..6f41f872e4cf6 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr @@ -16,10 +16,6 @@ help: alternatively, use a trait object to accept any type that implements `Foo | LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + -help: add `dyn` keyword before this trait - | -LL | fn foo(_x: dyn Foo + Send) { - | +++ error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:11:11 @@ -39,10 +35,6 @@ help: alternatively, use a trait object to accept any type that implements `Foo` | LL | fn bar(x: &dyn Foo) -> Foo { | ++++ -help: add `dyn` keyword before this trait - | -LL | fn bar(x: dyn Foo) -> Foo { - | +++ error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:11:19 @@ -58,10 +50,6 @@ help: alternatively, you can return an owned trait object | LL | fn bar(x: Foo) -> Box { | +++++++ + -help: add `dyn` keyword before this trait - | -LL | fn bar(x: Foo) -> dyn Foo { - | +++ error: aborting due to 3 previous errors From 05bffa072eb2e00cf2e26ae153de647d87c695b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Jun 2024 16:40:15 +0000 Subject: [PATCH 23/26] Mention associated type with same name as trait in `E0782` ``` error[E0782]: trait objects must include the `dyn` keyword --> $DIR/issue-116434-2021.rs:5:17 | LL | type Clone; | ---------- you might have meant to use this associated type LL | fn foo() -> Clone; | ^^^^^ | help: `Clone` is not object safe, use `impl Clone` to return an opaque type, as long as you return a single underlying type | LL | fn foo() -> impl Clone; | ++++ help: there is an associated type with the same name | LL | fn foo() -> Self::Clone; | ++++++ ``` --- .../src/hir_ty_lowering/lint.rs | 37 +++++++++++++++++++ tests/ui/suggestions/issue-116434-2021.rs | 6 ++- tests/ui/suggestions/issue-116434-2021.stderr | 14 ++++++- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 9b44c621bd214..1307f3f2181e9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -4,6 +4,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_infer::traits::error_reporting::suggest_path_on_bare_trait; use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; +use rustc_middle::ty; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; @@ -87,6 +88,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); + self.maybe_suggest_assoc_type(&poly_trait_ref.trait_ref, &mut diag); if object_safe { let parents = self.tcx().hir().parent_iter(self_ty.hir_id); @@ -338,4 +340,39 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } } + + /// Look for associated types with the same name as the `-> Trait` and suggest `-> Self::Trait`. + fn maybe_suggest_assoc_type(&self, trait_ref: &hir::TraitRef<'_>, diag: &mut Diag<'_>) { + let tcx = self.tcx(); + let [segment] = trait_ref.path.segments else { return }; + let mut trait_or_impl = None; + let mut iter = tcx.hir().parent_owner_iter(trait_ref.hir_ref_id); + while let Some((def_id, node)) = iter.next() { + if let hir::OwnerNode::Item(hir::Item { + kind: hir::ItemKind::Trait(..) | hir::ItemKind::Impl(..), + .. + }) = node + { + trait_or_impl = Some(def_id); + break; + } + } + let Some(parent_id) = trait_or_impl else { return }; + let mut assocs = tcx + .associated_items(parent_id) + .filter_by_name_unhygienic(segment.ident.name) + .filter(|assoc| assoc.kind == ty::AssocKind::Type); + if let Some(assoc) = assocs.next() { + diag.span_label( + tcx.def_span(assoc.def_id), + "you might have meant to use this associated type", + ); + diag.span_suggestion_verbose( + segment.ident.span.shrink_to_lo(), + "there is an associated type with the same name", + "Self::", + Applicability::MaybeIncorrect, + ); + } + } } diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs index 4f13d3fac3d73..3be7cabbfbe1b 100644 --- a/tests/ui/suggestions/issue-116434-2021.rs +++ b/tests/ui/suggestions/issue-116434-2021.rs @@ -1,19 +1,21 @@ //@ edition:2021 trait Foo { - type Clone; + type Clone; //~ NOTE you might have meant to use this associated type fn foo() -> Clone; //~^ ERROR trait objects must include the `dyn` keyword //~| HELP `Clone` is not object safe, use `impl Clone` to return an opaque type, as long as you return a single underlying type + //~| HELP there is an associated type with the same name } trait DbHandle: Sized {} trait DbInterface { - type DbHandle; + type DbHandle; //~ NOTE you might have meant to use this associated type fn handle() -> DbHandle; //~^ ERROR trait objects must include the `dyn` keyword //~| HELP `DbHandle` is not object safe, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type + //~| HELP there is an associated type with the same name } fn main() {} diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr index e60f60357ea8a..1118e9e3a5f06 100644 --- a/tests/ui/suggestions/issue-116434-2021.stderr +++ b/tests/ui/suggestions/issue-116434-2021.stderr @@ -1,6 +1,8 @@ error[E0782]: trait objects must include the `dyn` keyword --> $DIR/issue-116434-2021.rs:5:17 | +LL | type Clone; + | ---------- you might have meant to use this associated type LL | fn foo() -> Clone; | ^^^^^ | @@ -8,10 +10,16 @@ help: `Clone` is not object safe, use `impl Clone` to return an opaque type, as | LL | fn foo() -> impl Clone; | ++++ +help: there is an associated type with the same name + | +LL | fn foo() -> Self::Clone; + | ++++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/issue-116434-2021.rs:14:20 + --> $DIR/issue-116434-2021.rs:15:20 | +LL | type DbHandle; + | ------------- you might have meant to use this associated type LL | fn handle() -> DbHandle; | ^^^^^^^^ | @@ -19,6 +27,10 @@ help: `DbHandle` is not object safe, use `impl DbHandle` to return an opaque typ | LL | fn handle() -> impl DbHandle; | ++++ +help: there is an associated type with the same name + | +LL | fn handle() -> Self::DbHandle; + | ++++++ error: aborting due to 2 previous errors From 88ccfa4eb0eb4a7842cc7d479ffd8457d914d23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Jun 2024 18:22:22 +0000 Subject: [PATCH 24/26] Account for `static` and `const` in suggestion When encountering `static FOO: Trait = ...`, if `Trait` is object safe, suggest `static FOO: Box = ...`. --- .../src/hir_ty_lowering/lint.rs | 66 +++++++++++++++---- ...s_to_static-ice-121413.edition2015.stderr} | 22 +++---- ...fs_to_static-ice-121413.edition2021.stderr | 28 ++++++++ .../consts/const_refs_to_static-ice-121413.rs | 22 +++++-- 4 files changed, 107 insertions(+), 31 deletions(-) rename tests/ui/consts/{const_refs_to_static-ice-121413.stderr => const_refs_to_static-ice-121413.edition2015.stderr} (78%) create mode 100644 tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 1307f3f2181e9..33026c3993d5f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -64,6 +64,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )); } + let parent = tcx.parent_hir_node(self_ty.hir_id); if self_ty.span.edition().at_least_rust_2021() { let msg = "trait objects must include the `dyn` keyword"; let label = "add `dyn` keyword before this trait"; @@ -71,17 +72,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); if self_ty.span.can_be_used_for_suggestions() { if !self.maybe_suggest_impl_trait(self_ty, &mut diag) && object_safe { - // Only emit this suggestion if the trait is object safe. - diag.multipart_suggestion_verbose( - label, - sugg, - Applicability::MachineApplicable, - ); + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Static(..) | hir::ItemKind::Const(..), + .. + }) = parent + { + // Statics can't be unsized, so we suggest `Box` instead. + diag.multipart_suggestion_verbose( + "`static` can't be unsized; use a boxed trait object", + vec![ + (self_ty.span.shrink_to_lo(), "Box".to_string()), + ], + Applicability::MachineApplicable, + ); + } else { + // Only emit this suggestion if the trait is object safe. + diag.multipart_suggestion_verbose( + label, + sugg, + Applicability::MachineApplicable, + ); + } } } if !object_safe && self_ty.span.can_be_used_for_suggestions() { - let parent = tcx.parent_hir_node(self_ty.hir_id); suggest_path_on_bare_trait(tcx, &mut diag, parent); } @@ -112,8 +128,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); - match (object_safe, self_ty.span.can_be_used_for_suggestions()) { - (true, true) => { + match (object_safe, self_ty.span.can_be_used_for_suggestions(), parent) { + ( + true, + true, + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Static(..) | hir::ItemKind::Const(..), + .. + }), + ) => { + // Statics can't be unsized, so we suggest `Box` instead. + lint.multipart_suggestion_verbose( + "`static` can't be unsized; use a boxed trait object", + vec![ + (self_ty.span.shrink_to_lo(), "Box".to_string()), + ], + Applicability::MachineApplicable, + ); + } + (true, true, _) => { lint.multipart_suggestion_verbose( "as this is an \"object safe\" trait, write `dyn` in front of the \ trait", @@ -121,13 +155,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MachineApplicable, ); } - (true, false) => { + ( + true, + false, + hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }), + ) => { lint.note( - "as this is an \"object safe\" trait, you can write `dyn` in front of \ - the trait", + "as this is an \"object safe\" trait, you can write `Box`", ); } - (false, _) => { + (true, false, _) => { + lint.note("as this is an \"object safe\" trait, you can write `dyn Trait`"); + } + (false, _, _) => { lint.note( "you can't use write a trait object here because the trait isn't \ \"object safe\"", diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr similarity index 78% rename from tests/ui/consts/const_refs_to_static-ice-121413.stderr rename to tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr index 2dcf0deb1546b..69ec27d7bbd32 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` - --> $DIR/const_refs_to_static-ice-121413.rs:8:24 + --> $DIR/const_refs_to_static-ice-121413.rs:11:24 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` @@ -10,7 +10,7 @@ LL + use std::sync::atomic::AtomicUsize; | warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/const_refs_to_static-ice-121413.rs:8:17 + --> $DIR/const_refs_to_static-ice-121413.rs:11:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ @@ -18,13 +18,13 @@ LL | static FOO: Sync = AtomicUsize::new(0); = 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: as this is an "object safe" trait, write `dyn` in front of the trait +help: `static` can't be unsized; use a boxed trait object | -LL | static FOO: dyn Sync = AtomicUsize::new(0); - | +++ +LL | static FOO: Box = AtomicUsize::new(0); + | +++++++ + warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/const_refs_to_static-ice-121413.rs:8:17 + --> $DIR/const_refs_to_static-ice-121413.rs:11:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ @@ -32,13 +32,13 @@ LL | static FOO: Sync = AtomicUsize::new(0); = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: as this is an "object safe" trait, write `dyn` in front of the trait +help: `static` can't be unsized; use a boxed trait object | -LL | static FOO: dyn Sync = AtomicUsize::new(0); - | +++ +LL | static FOO: Box = AtomicUsize::new(0); + | +++++++ + error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - --> $DIR/const_refs_to_static-ice-121413.rs:8:17 + --> $DIR/const_refs_to_static-ice-121413.rs:11:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ doesn't have a size known at compile-time @@ -46,7 +46,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - --> $DIR/const_refs_to_static-ice-121413.rs:8:24 + --> $DIR/const_refs_to_static-ice-121413.rs:11:24 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr new file mode 100644 index 0000000000000..1fbd87cac2627 --- /dev/null +++ b/tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr @@ -0,0 +1,28 @@ +error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` + --> $DIR/const_refs_to_static-ice-121413.rs:11:24 + | +LL | static FOO: Sync = AtomicUsize::new(0); + | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` + | +help: consider importing one of these items + | +LL + use core::sync::atomic::AtomicUsize; + | +LL + use std::sync::atomic::AtomicUsize; + | + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/const_refs_to_static-ice-121413.rs:11:17 + | +LL | static FOO: Sync = AtomicUsize::new(0); + | ^^^^ + | +help: `static` can't be unsized; use a boxed trait object + | +LL | static FOO: Box = AtomicUsize::new(0); + | +++++++ + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0782. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.rs b/tests/ui/consts/const_refs_to_static-ice-121413.rs index c95be778272c9..8f7d6337eb484 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.rs +++ b/tests/ui/consts/const_refs_to_static-ice-121413.rs @@ -2,17 +2,25 @@ // or with -Zextra-const-ub-checks: expected wide pointer extra data (e.g. slice length or trait object vtable) // issue: rust-lang/rust#121413 //@ compile-flags: -Zextra-const-ub-checks -// ignore-tidy-linelength +//@ revisions: edition2015 edition2021 +//@[edition2021] edition:2021 #![feature(const_refs_to_static)] const REF_INTERIOR_MUT: &usize = { + //[edition2015]~^ HELP consider importing this struct + //[edition2021]~^^ HELP consider importing one of these items static FOO: Sync = AtomicUsize::new(0); //~^ ERROR failed to resolve: use of undeclared type `AtomicUsize` - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| HELP `static` can't be unsized; use a boxed trait object + //[edition2021]~^^^ ERROR trait objects must include the `dyn` keyword + //[edition2015]~^^^^ WARN trait objects without an explicit `dyn` are deprecated + //[edition2015]~| WARN trait objects without an explicit `dyn` are deprecated + //[edition2015]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //[edition2015]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //[edition2015]~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static) + //[edition2015]~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static) + //[edition2015]~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time + //[edition2015]~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time + //[edition2015]~| HELP `static` can't be unsized; use a boxed trait object unsafe { &*(&FOO as *const _ as *const usize) } }; pub fn main() {} From a62bfcd744c2511219bf934c217ff36ae7f85301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Jun 2024 22:18:50 +0000 Subject: [PATCH 25/26] Use verbose format for fully-qualified path suggestion --- compiler/rustc_hir_typeck/src/method/suggest.rs | 4 +++- .../trait-dyn-in-qualified-path-with-collision.stderr | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index c1e14f7fb753a..7b423166ac50c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -15,6 +15,7 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::{ codes::*, pluralize, struct_span_code_err, Applicability, Diag, MultiSpan, StashKey, + SuggestionStyle, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -1949,11 +1950,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(span) = sugg_span { suggs.sort(); - err.span_suggestions( + err.span_suggestions_with_style( span.with_hi(item_name.span.lo()), "use fully-qualified syntax to disambiguate", suggs, Applicability::MachineApplicable, + SuggestionStyle::ShowAlways, ); } if sources.len() > limit { diff --git a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr index 07107c78fc4ce..d24a0fc23dae0 100644 --- a/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr +++ b/tests/ui/dyn-keyword/trait-dyn-in-qualified-path-with-collision.stderr @@ -2,9 +2,7 @@ error[E0034]: multiple applicable items in scope --> $DIR/trait-dyn-in-qualified-path-with-collision.rs:9:18 | LL | ::function(&()); - | -------------^^^^^^^^ multiple `function` found - | | - | help: use fully-qualified syntax to disambiguate: `Trait::` + | ^^^^^^^^ multiple `function` found | note: candidate #1 is defined in the trait `Trait` --> $DIR/trait-dyn-in-qualified-path-with-collision.rs:2:5 @@ -16,6 +14,10 @@ note: candidate #2 is defined in an impl for the type `(dyn Trait + 'static)` | LL | fn function(&self) {} | ^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL | Trait::function(&()); + | ~~~~~~~ error: aborting due to 1 previous error From 7f923f3e49772c11a91006c71bd72d29b946d7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Jun 2024 22:20:52 +0000 Subject: [PATCH 26/26] Fix tidy --- .../const_refs_to_static-ice-121413.edition2015.stderr | 10 +++++----- .../const_refs_to_static-ice-121413.edition2021.stderr | 4 ++-- tests/ui/consts/const_refs_to_static-ice-121413.rs | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr index 69ec27d7bbd32..9fb9ecfd837a1 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` - --> $DIR/const_refs_to_static-ice-121413.rs:11:24 + --> $DIR/const_refs_to_static-ice-121413.rs:12:24 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` @@ -10,7 +10,7 @@ LL + use std::sync::atomic::AtomicUsize; | warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/const_refs_to_static-ice-121413.rs:11:17 + --> $DIR/const_refs_to_static-ice-121413.rs:12:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ @@ -24,7 +24,7 @@ LL | static FOO: Box = AtomicUsize::new(0); | +++++++ + warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/const_refs_to_static-ice-121413.rs:11:17 + --> $DIR/const_refs_to_static-ice-121413.rs:12:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ @@ -38,7 +38,7 @@ LL | static FOO: Box = AtomicUsize::new(0); | +++++++ + error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - --> $DIR/const_refs_to_static-ice-121413.rs:11:17 + --> $DIR/const_refs_to_static-ice-121413.rs:12:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ doesn't have a size known at compile-time @@ -46,7 +46,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - --> $DIR/const_refs_to_static-ice-121413.rs:11:24 + --> $DIR/const_refs_to_static-ice-121413.rs:12:24 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr index 1fbd87cac2627..2384584349042 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.edition2021.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` - --> $DIR/const_refs_to_static-ice-121413.rs:11:24 + --> $DIR/const_refs_to_static-ice-121413.rs:12:24 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` @@ -12,7 +12,7 @@ LL + use std::sync::atomic::AtomicUsize; | error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/const_refs_to_static-ice-121413.rs:11:17 + --> $DIR/const_refs_to_static-ice-121413.rs:12:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.rs b/tests/ui/consts/const_refs_to_static-ice-121413.rs index 8f7d6337eb484..fe3bdca81336c 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.rs +++ b/tests/ui/consts/const_refs_to_static-ice-121413.rs @@ -1,5 +1,6 @@ -// ICE: ImmTy { imm: Scalar(alloc1), ty: *const dyn Sync } input to a fat-to-thin cast (*const dyn Sync -> *const usize -// or with -Zextra-const-ub-checks: expected wide pointer extra data (e.g. slice length or trait object vtable) +// ICE: ImmTy { imm: Scalar(alloc1), ty: *const dyn Sync } input to a fat-to-thin cast (*const dyn +// Sync -> *const usize or with -Zextra-const-ub-checks: expected wide pointer extra data (e.g. +// slice length or trait object vtable) // issue: rust-lang/rust#121413 //@ compile-flags: -Zextra-const-ub-checks //@ revisions: edition2015 edition2021