From 7b62d97abdd38850621153e806cc7b0ee6ab4289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 17 Jan 2026 00:19:20 +0000 Subject: [PATCH 01/17] Mention implicit bounds from `#[derive(Clone)]` on moved value When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply: ``` note: if `TypedAddress` implemented `Clone`, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] | ----- derived `Clone` adds implicit bounds on type parameters LL | pub struct TypedAddress{ | ^^^^^^^^^^^^^^^^^^^^^^^^-^ | | | | | introduces an implicit `T: Clone` bound | consider manually implementing `Clone` for this type ... LL | let old = self.return_value(offset); | ------ you could clone this value ``` --- .../src/diagnostics/conflict_errors.rs | 37 +++++++++++++++++- .../borrowck/derive-clone-implicit-bound.rs | 32 ++++++++++++++++ .../derive-clone-implicit-bound.stderr | 38 +++++++++++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 tests/ui/borrowck/derive-clone-implicit-bound.rs create mode 100644 tests/ui/borrowck/derive-clone-implicit-bound.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index caf6a86af098..692ce240e36f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1256,7 +1256,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning_inner(err, ty, expr); } } else if let ty::Adt(def, args) = ty.kind() - && def.did().as_local().is_some() + && let Some(local_did) = def.did().as_local() && def.variants().iter().all(|variant| { variant .fields @@ -1266,7 +1266,40 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { { let ty_span = self.infcx.tcx.def_span(def.did()); let mut span: MultiSpan = ty_span.into(); - span.push_span_label(ty_span, "consider implementing `Clone` for this type"); + let mut derive_clone = false; + self.infcx.tcx.for_each_relevant_impl( + self.infcx.tcx.lang_items().clone_trait().unwrap(), + ty, + |def_id| { + if self.infcx.tcx.is_automatically_derived(def_id) { + derive_clone = true; + span.push_span_label( + self.infcx.tcx.def_span(def_id), + "derived `Clone` adds implicit bounds on type parameters", + ); + if let Some(generics) = self.infcx.tcx.hir_get_generics(local_did) { + for param in generics.params { + if let hir::GenericParamKind::Type { .. } = param.kind { + span.push_span_label( + param.span, + format!( + "introduces an implicit `{}: Clone` bound", + param.name.ident() + ), + ); + } + } + } + } + }, + ); + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); span.push_span_label(expr.span, "you could clone this value"); err.span_note( span, diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs new file mode 100644 index 000000000000..a20e04d3afdc --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -0,0 +1,32 @@ +// Issue #108894 + +use std::marker::PhantomData; + +#[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters +pub struct TypedAddress{ +//~^ NOTE if `TypedAddress` implemented `Clone`, you could clone the value +//~| NOTE consider manually implementing `Clone` for this type +//~| NOTE introduces an implicit `T: Clone` bound + inner: u64, + phantom: PhantomData, +} + +pub trait Memory { + fn write_value(&self, offset: TypedAddress, value: &T); + fn return_value(&self, offset: TypedAddress) -> T; + //~^ NOTE consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + //~| NOTE in this method + //~| NOTE this parameter takes ownership of the value + fn update_value(&self, offset: TypedAddress, update: F) + //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait + where F: FnOnce(T) -> T + { + let old = self.return_value(offset); //~ NOTE value moved here + //~^ NOTE you could clone this value + let new = update(old); + self.write_value(offset, &new); //~ ERROR use of moved value: `offset` + //~^ NOTE value used here after move + } +} + +fn main() {} diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr new file mode 100644 index 000000000000..b10e3a92c96b --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -0,0 +1,38 @@ +error[E0382]: use of moved value: `offset` + --> $DIR/derive-clone-implicit-bound.rs:27:26 + | +LL | fn update_value(&self, offset: TypedAddress, update: F) + | ------ move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait +... +LL | let old = self.return_value(offset); + | ------ value moved here +... +LL | self.write_value(offset, &new); + | ^^^^^^ value used here after move + | +note: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + --> $DIR/derive-clone-implicit-bound.rs:16:39 + | +LL | fn return_value(&self, offset: TypedAddress) -> T; + | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value +note: if `TypedAddress` implemented `Clone`, you could clone the value + --> $DIR/derive-clone-implicit-bound.rs:6:1 + | +LL | #[derive(Clone, Copy)] + | ----- derived `Clone` adds implicit bounds on type parameters +LL | pub struct TypedAddress{ + | ^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | | + | | introduces an implicit `T: Clone` bound + | consider manually implementing `Clone` for this type +... +LL | let old = self.return_value(offset); + | ------ you could clone this value +help: consider further restricting type parameter `T` with trait `Copy` + | +LL | where F: FnOnce(T) -> T, T: Copy + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. From 679f38c1259d96463c5f04f175846501fbca2a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 02:29:33 +0000 Subject: [PATCH 02/17] On E0277 pointing at bound in derive, suggest manual impl When encountering a bound coming from a derive macro, suggest manual impl of the trait. Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself. ``` error[E0277]: can't compare `SomeNode` with `SomeNode` --> f29.rs:24:15 | 24 | accept_eq(&node); | --------- ^^^^^ no implementation for `SomeNode == SomeNode` | | | required by a bound introduced by this call | = note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:279:39 = help: the trait `PartialEq` is not implemented for `SomeNode` note: required for `Id` to implement `PartialEq` --> f29.rs:3:10 | 3 | #[derive(PartialEq, Eq)] | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 4 | pub struct Id(PhantomData); | - = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> f29.rs:15:23 | 15 | fn accept_eq(_: &impl PartialEq) { } | ^^^^^^^^^ required by this bound in `accept_eq` help: consider annotating `SomeNode` with `#[derive(PartialEq)]` | 13 + #[derive(PartialEq)] 14 | struct SomeNode(); | ``` --- .../src/deriving/generic/mod.rs | 18 +++++----- compiler/rustc_hir/src/hir.rs | 11 ++++-- compiler/rustc_middle/src/ty/diagnostics.rs | 15 ++++---- .../src/error_reporting/traits/suggestions.rs | 8 +++++ tests/ui/associated-types/issue-38821.stderr | 3 ++ .../unsizing-wfcheck-issue-126272.stderr | 6 +++- .../ui/consts/const-blocks/trait-error.stderr | 5 ++- tests/ui/derives/deriving-copyclone.stderr | 15 ++++++-- .../impl_bounds.stderr | 10 ++++-- .../issue-104884-trait-impl-sugg-err.stderr | 6 +++- ...missing-bound-in-derive-copy-impl-2.stderr | 2 ++ .../missing-bound-in-derive-copy-impl.stderr | 2 ++ tests/ui/traits/derive-implicit-bound.rs | 34 +++++++++++++++++++ tests/ui/traits/derive-implicit-bound.stderr | 31 +++++++++++++++++ 14 files changed, 140 insertions(+), 26 deletions(-) create mode 100644 tests/ui/traits/derive-implicit-bound.rs create mode 100644 tests/ui/traits/derive-implicit-bound.stderr diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c2260a459097..665e0ddab194 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -638,27 +638,27 @@ impl<'a> TraitDef<'a> { GenericParamKind::Type { .. } => { // Extra restrictions on the generics parameters to the // type being derived upon. + let span = param.ident.span.with_ctxt(ctxt); let bounds: Vec<_> = self .additional_bounds .iter() .map(|p| { - cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), - self.is_const, - ) + cx.trait_bound(p.to_path(cx, span, type_ident, generics), self.is_const) }) .chain( // Add a bound for the current trait. - self.skip_path_as_bound - .not() - .then(|| cx.trait_bound(trait_path.clone(), self.is_const)), + self.skip_path_as_bound.not().then(|| { + let mut trait_path = trait_path.clone(); + trait_path.span = span; + cx.trait_bound(trait_path, self.is_const) + }), ) .chain({ // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { let p = deriving::path_std!(marker::Copy); Some(cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), + p.to_path(cx, span, type_ident, generics), self.is_const, )) } else { @@ -671,7 +671,7 @@ impl<'a> TraitDef<'a> { ) .collect(); - cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None) + cx.typaram(span, param.ident, bounds, None) } GenericParamKind::Const { ty, span, .. } => { let const_nodefault_kind = GenericParamKind::Const { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c1bcffa1cf4..b117fa832729 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ // ignore-tidy-filelength use std::borrow::Cow; use std::fmt; +use std::ops::Not; use rustc_abi::ExternAbi; use rustc_ast::attr::AttributeExt; @@ -1012,10 +1013,14 @@ impl<'hir> Generics<'hir> { span_for_parentheses.map_or_else( || { - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. + // We include bounds that come from a `#[derive(_)]` but point at the user's + // code, as we use this method to get a span appropriate for suggestions. let bs = bound.span(); - bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None)) + // We use `from_expansion` instead of `can_be_used_for_suggestions` because + // the trait bound from imperfect derives do point at the type parameter, + // but expanded to a where clause, so we want to ignore those. This is only + // true for derive intrinsics. + bs.from_expansion().not().then(|| (bs.shrink_to_hi(), None)) }, |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))), ) diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 279c34cb275d..b3b06314e1a0 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -526,12 +526,15 @@ pub fn suggest_constraining_type_params<'a>( // // fn foo(t: T) { ... } // - help: consider restricting this type parameter with `T: Foo` - suggestions.push(( - param.span.shrink_to_hi(), - post, - format!(": {constraint}"), - SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, - )); + let span = param.span.shrink_to_hi(); + if span.can_be_used_for_suggestions() { + suggestions.push(( + span, + post, + format!(": {constraint}"), + SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, + )); + } } // FIXME: remove the suggestions that are from derive, as the span is not correct diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index d54f3812350d..94876c6dd89f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3586,6 +3586,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } spans.push(self_ty.span); let mut spans: MultiSpan = spans.into(); + let mut derived = false; if matches!( self_ty.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _) @@ -3593,6 +3594,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind), Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { + derived = true; spans.push_span_label( data.span, "unsatisfied trait bound introduced in this `derive` macro", @@ -3621,6 +3623,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); + if derived { + err.help(format!( + "consider manually implementing `{trait_name}` to avoid undesired \ + bounds", + )); + } point_at_assoc_type_restriction( tcx, err, diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 01329f69c3be..3c5f67fee26a 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -102,6 +102,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -146,6 +147,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -219,6 +221,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index aecd97ef7763..ea411741536f 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -65,6 +65,7 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^^^^ LL | struct Bar(T); | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` = note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug` @@ -96,7 +97,10 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ unsatisfied trait bound introduced in this `derive` macro + | ^^ +LL | struct Bar(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` note: required by a bound in `std::cmp::AssertParamIsEq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 601d067e3d84..1e66daa7132d 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,7 +8,10 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Foo(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block | diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index befff8802804..f4cd4cff7f44 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,7 +10,10 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | @@ -33,7 +36,10 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 | @@ -56,7 +62,10 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 7847bbd813cd..d6a794fa0b19 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,7 +32,10 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Fooy(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 | @@ -56,7 +59,10 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Fooy(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index b7aed4a8485a..93fd2df0398e 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,7 +37,11 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^^ +... +LL | struct PriorityQueue(BinaryHeap>); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index a48dd30d008a..2b8c6baeeafe 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -30,6 +30,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` | @@ -71,6 +72,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 645d6ebb3961..2bd56b7688f4 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -65,6 +65,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` | @@ -134,6 +135,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/traits/derive-implicit-bound.rs b/tests/ui/traits/derive-implicit-bound.rs new file mode 100644 index 000000000000..22fb68f37c5c --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.rs @@ -0,0 +1,34 @@ +// Second case reported in issue #108894. + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct Id(PhantomData); + +// manual implementation which would break the usage of const patterns +// impl PartialEq for Id { fn eq(&self, _: &Id) -> bool { true } } +// impl Eq for Id {} + +// This derive is undesired but cannot be removed without +// breaking the usages below +// #[derive(PartialEq, Eq)] +struct SomeNode(); + +fn accept_eq(_: &impl PartialEq) { } + +fn main() { + let node = Id::(PhantomData); + + // this will only work if + // - `Partial/Eq` is implemented manually, or + // - `SomeNode` also needlessly(?) implements `Partial/Eq` + accept_eq(&node); //~ ERROR can't compare `SomeNode` with `SomeNode` + + const CONST_ID: Id:: = Id::(PhantomData); + // this will work only when `Partial/Eq` is being derived + // otherwise: error: to use a constant of type `Id` in a pattern, + // `Id` must be annotated with `#[derive(PartialEq, Eq)]` + match node { + CONST_ID => {} + } +} diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr new file mode 100644 index 000000000000..9805835bb07f --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -0,0 +1,31 @@ +error[E0277]: can't compare `SomeNode` with `SomeNode` + --> $DIR/derive-implicit-bound.rs:25:15 + | +LL | accept_eq(&node); + | --------- ^^^^^ no implementation for `SomeNode == SomeNode` + | | + | required by a bound introduced by this call + | + = help: the trait `PartialEq` is not implemented for `SomeNode` +note: required for `Id` to implement `PartialEq` + --> $DIR/derive-implicit-bound.rs:5:10 + | +LL | #[derive(PartialEq, Eq)] + | ^^^^^^^^^ +LL | pub struct Id(PhantomData); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `PartialEq` to avoid undesired bounds +note: required by a bound in `accept_eq` + --> $DIR/derive-implicit-bound.rs:17:23 + | +LL | fn accept_eq(_: &impl PartialEq) { } + | ^^^^^^^^^ required by this bound in `accept_eq` +help: consider annotating `SomeNode` with `#[derive(PartialEq)]` + | +LL + #[derive(PartialEq)] +LL | struct SomeNode(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 54fe73fd6d3d0b2935977016039ded8d6a0d4772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 05:43:19 +0000 Subject: [PATCH 03/17] Tweak span labels caused by trait bound coming from derive expansion ``` note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { | - would need to be `Copy` ``` --- .../src/error_reporting/traits/suggestions.rs | 12 +++++++++++- tests/ui/associated-types/issue-38821.stderr | 12 ++++++------ .../unsizing-wfcheck-issue-126272.stderr | 8 ++++---- tests/ui/consts/const-blocks/trait-error.stderr | 4 ++-- tests/ui/derives/deriving-copyclone.stderr | 12 ++++++------ tests/ui/generic-associated-types/impl_bounds.stderr | 8 ++++---- .../issue-104884-trait-impl-sugg-err.stderr | 4 ++-- .../missing-bound-in-derive-copy-impl-2.stderr | 8 ++++---- .../missing-bound-in-derive-copy-impl.stderr | 8 ++++---- tests/ui/traits/derive-implicit-bound.stderr | 4 ++-- 10 files changed, 45 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 94876c6dd89f..c9dc390ea0be 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3595,9 +3595,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { derived = true; + spans.push_span_label( + data.span.ctxt().outer_expn_data().call_site, + format!( + "unsatisfied trait bound introduced in this `derive` macro" + ), + ); spans.push_span_label( data.span, - "unsatisfied trait bound introduced in this `derive` macro", + if data.span.in_derive_expansion() { + format!("would need to be `{trait_name}`") + } else { + format!("") + }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { // `Sized` may be an explicit or implicit trait bound. If it is diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 3c5f67fee26a..11d0c9d514ff 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -98,10 +98,10 @@ note: required for `ColumnInsertValue` to implement `Debug` --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | @@ -143,10 +143,10 @@ note: required for `ColumnInsertValue` to implement `Copy` --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | @@ -217,10 +217,10 @@ note: required for `ColumnInsertValue` to implement `Clone` --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index ea411741536f..1aaa7591a7be 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -62,9 +62,9 @@ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Bar(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -97,9 +97,9 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ + | ^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Bar(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 1e66daa7132d..991a48917efb 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,9 +8,9 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Foo(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index f4cd4cff7f44..1baacf85f6a2 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,9 +10,9 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -36,9 +36,9 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -62,9 +62,9 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index d6a794fa0b19..fd7dd774cf08 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,9 +32,9 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Fooy(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -59,9 +59,9 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Fooy(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index 93fd2df0398e..c3513e19981f 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,10 +37,10 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | struct PriorityQueue(BinaryHeap>); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 2b8c6baeeafe..800f07054af7 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -27,9 +27,9 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,9 +69,9 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 2bd56b7688f4..3f889f31484b 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -62,9 +62,9 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -132,9 +132,9 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 9805835bb07f..275cef7a94fd 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -11,9 +11,9 @@ note: required for `Id` to implement `PartialEq` --> $DIR/derive-implicit-bound.rs:5:10 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Id(PhantomData); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 From b88fb8a0b0422697a8fe1573598795d7052e936c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 07:22:00 +0000 Subject: [PATCH 04/17] Mention that the trait could be manually impld in E0599 --- compiler/rustc_hir_typeck/src/method/suggest.rs | 5 +++++ tests/ui/derives/derive-assoc-type-not-impl.stderr | 1 + tests/ui/derives/deriving-with-repr-packed-2.stderr | 1 + tests/ui/union/union-derive-clone.stderr | 1 + 4 files changed, 8 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cd25b866b098..f5ef5adff6bd 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1748,6 +1748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find all the requirements that come from a local `impl` block. let mut skip_list: UnordSet<_> = Default::default(); let mut spanned_predicates = FxIndexMap::default(); + let mut manually_impl = false; for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. @@ -1798,6 +1799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); entry.2.push(p); skip_list.insert(p); + manually_impl = true; } // Unmet obligation coming from an `impl`. @@ -2083,6 +2085,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *suggested_derive = self.suggest_derive(err, unsatisfied_predicates); *unsatisfied_bounds = true; } + if manually_impl { + err.help("consider manually implementing the trait to avoid undesired bounds"); + } } /// If an appropriate error source is not found, check method chain for possible candidates diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 13ba80243a5e..e239ad4ef209 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -15,6 +15,7 @@ note: trait bound `NotClone: Clone` was not satisfied | LL | #[derive(Clone)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NotClone` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index b62c67d9a9da..fff6269472bd 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -25,6 +25,7 @@ note: the following trait bounds were not satisfied: | LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)] diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 18f862aaa7d6..65488629b629 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -29,6 +29,7 @@ note: trait bound `CloneNoCopy: Copy` was not satisfied | LL | #[derive(Clone, Copy)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)] From 085da0cee4e6de6408c401ea2a807eff6b701307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:23:18 +0000 Subject: [PATCH 05/17] On E0308 caused by cloning a reference due to missing bounds, account for derive On type errors where the difference is expecting an owned type and getting a reference, if the expression is a `.clone()` call and the type is annotated with `#[derive(Clone)]`, we now explain implicit bounds and suggest manually implementing `Clone`. ``` error[E0308]: mismatched types --> $DIR/derive-implicit-bound-on-clone.rs:10:5 | LL | fn clone_me(x: &ContainsRc) -> ContainsRc { | ---------------- expected `ContainsRc` because of return type LL | x.clone() | ^^^^^^^^^ expected `ContainsRc`, found `&ContainsRc` | = note: expected struct `ContainsRc<_, _>` found reference `&ContainsRc<_, _>` note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead --> $DIR/derive-implicit-bound-on-clone.rs:10:5 | LL | x.clone() | ^ help: `Clone` is not implemented because the some trait bounds could not be satisfied --> $DIR/derive-implicit-bound-on-clone.rs:5:19 | LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct ContainsRc { | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` | | | derive introduces an implicit unsatisfied trait bound `T: Clone` = help: consider manually implementing `Clone` to avoid the implict type parameter bounds ``` --- .../src/fn_ctxt/suggestions.rs | 97 ++++++++++++++++--- ...on-ref-due-to-missing-bound.current.stderr | 3 +- ...ll-on-ref-due-to-missing-bound.next.stderr | 3 +- .../traits/derive-implicit-bound-on-clone.rs | 24 +++++ .../derive-implicit-bound-on-clone.stderr | 53 ++++++++++ 5 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 tests/ui/traits/derive-implicit-bound-on-clone.rs create mode 100644 tests/ui/traits/derive-implicit-bound-on-clone.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e4c194147f9..285288e87ee0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1932,25 +1932,96 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); } else { + let mut suggest_derive = true; if let Some(errors) = self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { + let manually_impl = "consider manually implementing `Clone` to avoid the \ + implict type parameter bounds"; match &errors[..] { [] => {} [error] => { - diag.help(format!( - "`Clone` is not implemented because the trait bound `{}` is \ - not satisfied", - error.obligation.predicate, - )); + // diag.note("{error:#?}"); + // diag.note(format!("{:#?} {:#?} {:#?}", error.obligation, error.obligation.cause, error.obligation.cause.code())); + let msg = "`Clone` is not implemented because a trait bound is not \ + satisfied"; + if let traits::ObligationCauseCode::ImplDerived(data) = + error.obligation.cause.code() + { + let mut span: MultiSpan = data.span.into(); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) { + span.push_span_label( + data.span, + format!( + "derive introduces an implicit `{}` bound", + error.obligation.predicate + ), + ); + } + diag.span_help(span, msg); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(msg); + } } _ => { - diag.help(format!( - "`Clone` is not implemented because the following trait bounds \ - could not be satisfied: {}", - listify(&errors, |e| format!("`{}`", e.obligation.predicate)) - .unwrap(), - )); + let unsatisfied_bounds: Vec<_> = errors + .iter() + .filter_map(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + let pre = if self + .tcx + .is_automatically_derived(data.impl_or_alias_def_id) + { + "derive introduces an implicit " + } else { + "" + }; + Some(( + data.span, + format!( + "{pre}unsatisfied trait bound `{}`", + error.obligation.predicate + ), + )) + } + _ => None, + }) + .collect(); + let msg = "`Clone` is not implemented because the some trait bounds \ + could not be satisfied"; + if errors.len() == unsatisfied_bounds.len() { + let mut unsatisfied_bounds_spans: MultiSpan = unsatisfied_bounds + .iter() + .map(|(span, _)| *span) + .collect::>() + .into(); + for (span, label) in unsatisfied_bounds { + unsatisfied_bounds_spans.push_span_label(span, label); + } + diag.span_help(unsatisfied_bounds_spans, msg); + if errors.iter().all(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + } + _ => false, + }) { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(format!( + "{msg}: {}", + listify(&errors, |e| format!("`{}`", e.obligation.predicate)) + .unwrap(), + )); + } } } for error in errors { @@ -1968,7 +2039,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + if suggest_derive { + self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + } } } } diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr index 301f3c3a458d..5de99cc6ca6a 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr index 301f3c3a458d..5de99cc6ca6a 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.rs b/tests/ui/traits/derive-implicit-bound-on-clone.rs new file mode 100644 index 000000000000..a4c9e88ef576 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.rs @@ -0,0 +1,24 @@ +// Issue #146515 +use std::rc::Rc; + +#[derive(Clone)] +struct ContainsRc { //~ HELP `Clone` is not implemented + value: Rc<(T, K)>, +} + +fn clone_me(x: &ContainsRc) -> ContainsRc { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +#[derive(Clone)] +struct ContainsRcSingle { //~ HELP `Clone` is not implemented + value: Rc, +} + +fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +fn main() {} diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.stderr b/tests/ui/traits/derive-implicit-bound-on-clone.stderr new file mode 100644 index 000000000000..0cec4ef7c609 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.stderr @@ -0,0 +1,53 @@ +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | fn clone_me(x: &ContainsRc) -> ContainsRc { + | ---------------- expected `ContainsRc` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRc`, found `&ContainsRc` + | + = note: expected struct `ContainsRc<_, _>` + found reference `&ContainsRc<_, _>` +note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because the some trait bounds could not be satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:5:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` + | | + | derive introduces an implicit unsatisfied trait bound `T: Clone` + = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + | ------------------- expected `ContainsRcSingle` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRcSingle`, found `&ContainsRcSingle` + | + = note: expected struct `ContainsRcSingle<_>` + found reference `&ContainsRcSingle<_>` +note: `ContainsRcSingle` does not implement `Clone`, so `&ContainsRcSingle` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:15:25 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRcSingle { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From aebf1fdcf9c3b1e7b674499ce10aee43960569a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:40:29 +0000 Subject: [PATCH 06/17] Keep span of type in builtin derive macros expansions --- .../src/deriving/generic/mod.rs | 3 +- tests/ui/associated-types/issue-38821.rs | 6 +-- tests/ui/associated-types/issue-38821.stderr | 47 +++++++++++++++---- .../const_param_ty_impl_bad_field.rs | 4 +- .../const_param_ty_impl_bad_field.stderr | 7 ++- .../const_param_ty_impl_no_structural_eq.rs | 8 ++-- ...onst_param_ty_impl_no_structural_eq.stderr | 14 ++++-- .../nested_bad_const_param_ty.rs | 6 +-- .../nested_bad_const_param_ty.stderr | 27 +++++------ .../adt_const_params/unsized_field-1.rs | 6 +-- .../adt_const_params/unsized_field-1.stderr | 27 +++++------ .../unsizing-wfcheck-issue-126272.rs | 2 +- .../unsizing-wfcheck-issue-126272.stderr | 22 ++++++--- .../ui/consts/const-blocks/trait-error.stderr | 7 ++- .../derives/copy-drop-mutually-exclusive.rs | 8 ++-- .../copy-drop-mutually-exclusive.stderr | 12 +++-- tests/ui/derives/deriving-copyclone.stderr | 21 ++++++--- tests/ui/derives/issue-97343.stderr | 9 ++-- ...ith-same-name-and-derive-default-133965.rs | 12 ++--- ...same-name-and-derive-default-133965.stderr | 23 ++++----- ...ultiple-types-with-same-name-and-derive.rs | 12 ++--- ...ple-types-with-same-name-and-derive.stderr | 40 ++++++++-------- tests/ui/error-codes/E0184.rs | 4 +- tests/ui/error-codes/E0184.stderr | 6 ++- .../impl_bounds.stderr | 14 ++++-- tests/ui/issues/issue-27340.rs | 4 +- tests/ui/issues/issue-27340.stderr | 10 ++-- tests/ui/malformed/malformed-derive-entry.rs | 10 ++-- .../malformed/malformed-derive-entry.stderr | 14 ++++-- .../issue-104884-trait-impl-sugg-err.rs | 13 +++-- .../issue-104884-trait-impl-sugg-err.stderr | 20 +++++--- tests/ui/range/range_traits-2.rs | 4 +- tests/ui/range/range_traits-2.stderr | 6 +-- tests/ui/range/range_traits-3.rs | 4 +- tests/ui/range/range_traits-3.stderr | 6 +-- tests/ui/range/range_traits-6.rs | 4 +- tests/ui/range/range_traits-6.stderr | 6 +-- tests/ui/span/E0204.rs | 8 ++-- tests/ui/span/E0204.stderr | 10 ++-- .../ui/suggestions/derive-clone-for-eq.fixed | 4 +- tests/ui/suggestions/derive-clone-for-eq.rs | 4 +- .../ui/suggestions/derive-clone-for-eq.stderr | 6 ++- ...missing-bound-in-derive-copy-impl-2.stderr | 14 ++++-- .../missing-bound-in-derive-copy-impl-3.fixed | 4 +- .../missing-bound-in-derive-copy-impl-3.rs | 4 +- ...missing-bound-in-derive-copy-impl-3.stderr | 17 +++---- .../missing-bound-in-derive-copy-impl.rs | 4 +- .../missing-bound-in-derive-copy-impl.stderr | 19 +++++--- tests/ui/traits/derive-implicit-bound.stderr | 7 ++- tests/ui/traits/issue-106072.rs | 8 ++-- tests/ui/traits/issue-106072.stderr | 15 ++++-- tests/ui/traits/issue-50480.rs | 11 ++--- tests/ui/traits/issue-50480.stderr | 35 +++++++------- .../global-cache-and-parallel-frontend.rs | 4 +- .../global-cache-and-parallel-frontend.stderr | 6 ++- 55 files changed, 356 insertions(+), 272 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 665e0ddab194..bc86cdbc9f7e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -791,7 +791,8 @@ impl<'a> TraitDef<'a> { .collect(); // Create the type of `self`. - let path = cx.path_all(self.span, false, vec![type_ident], self_params); + let path = + cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params); let self_type = cx.ty_path(path); let rustc_const_unstable = cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); diff --git a/tests/ui/associated-types/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs index 5212bc886f0d..35c371235e64 100644 --- a/tests/ui/associated-types/issue-38821.rs +++ b/tests/ui/associated-types/issue-38821.rs @@ -34,11 +34,11 @@ pub trait Column: Expression {} //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied pub enum ColumnInsertValue where //~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied +//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied +//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied +//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied Col: Column, Expr: Expression::Nullable>, //~^ ERROR the trait bound `::SqlType: IntoNullable` is not satisfied diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 11d0c9d514ff..58d06860fe30 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:40:1 + --> $DIR/issue-38821.rs:37:1 | LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -82,10 +82,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -98,7 +101,13 @@ note: required for `ColumnInsertValue` to implement `Debug` --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ @@ -127,10 +136,13 @@ LL | Expr: Expression::Nullable>, ::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ---- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -143,7 +155,13 @@ note: required for `ColumnInsertValue` to implement `Copy` --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ @@ -201,10 +219,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -217,7 +238,13 @@ note: required for `ColumnInsertValue` to implement `Clone` --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs index 0614ea97b1ad..1900931b3f35 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs @@ -8,10 +8,10 @@ struct NotParam; struct CantParam(NotParam); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type struct CantParamDerive(NotParam); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr index fd1836802c4a..084c64d27335 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr @@ -8,13 +8,12 @@ LL | impl std::marker::ConstParamTy_ for CantParam {} | ^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/const_param_ty_impl_bad_field.rs:13:10 + --> $DIR/const_param_ty_impl_bad_field.rs:14:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct CantParamDerive(NotParam); - | -------- this field does not implement `ConstParamTy_` + | ^^^^^^^^^^^^^^^ -------- this field does not implement `ConstParamTy_` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs index a1c8eccfb095..a8f190609c04 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs @@ -8,13 +8,13 @@ impl std::marker::ConstParamTy_ for ImplementsConstParamTy {} struct CantParam(ImplementsConstParamTy); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the type `CantParam` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParam: Eq` is not satisfied +//~^ ERROR: the type `CantParam` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParam: Eq` is not satisfied #[derive(std::marker::ConstParamTy)] -//~^ error: the type `CantParamDerive` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParamDerive: Eq` is not satisfied struct CantParamDerive(ImplementsConstParamTy); +//~^ ERROR: the type `CantParamDerive` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParamDerive: Eq` is not satisfied fn check() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr index ca2a693d48ce..1219d5f04380 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -27,10 +27,12 @@ note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` | note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -41,13 +43,15 @@ LL | struct CantParamDerive(ImplementsConstParamTy); | error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ unsatisfied trait bound | help: the nightly-only, unstable trait `StructuralPartialEq` is not implemented for `CantParamDerive` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:17:1 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:1 | LL | struct CantParamDerive(ImplementsConstParamTy); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs index d42ef90e1b18..e8a16be2197b 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs @@ -4,15 +4,15 @@ use std::marker::ConstParamTy; #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo([*const u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo2([*mut u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo3([fn(); 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr index 442ec6b96cef..6c8a506d1f40 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:6:10 + --> $DIR/nested_bad_const_param_ty.rs:7:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo([*const u8; 1]); - | -------------- this field does not implement `ConstParamTy_` + | ^^^ -------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:8:12 + --> $DIR/nested_bad_const_param_ty.rs:7:12 | LL | struct Foo([*const u8; 1]); | ^^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:10:10 + --> $DIR/nested_bad_const_param_ty.rs:11:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo2([*mut u8; 1]); - | ------------ this field does not implement `ConstParamTy_` + | ^^^^ ------------ this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:12:13 + --> $DIR/nested_bad_const_param_ty.rs:11:13 | LL | struct Foo2([*mut u8; 1]); | ^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:14:10 + --> $DIR/nested_bad_const_param_ty.rs:15:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo3([fn(); 1]); - | --------- this field does not implement `ConstParamTy_` + | ^^^^ --------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:16:13 + --> $DIR/nested_bad_const_param_ty.rs:15:13 | LL | struct Foo3([fn(); 1]); | ^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs index 5db031cb900f..f2d972612dc6 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs @@ -6,18 +6,18 @@ extern crate unsized_const_param; use std::marker::ConstParamTy; #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct A([u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct B(&'static [u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] struct C(unsized_const_param::Foo); #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr index 134dbba0d63a..2538b811618b 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:8:10 + --> $DIR/unsized_field-1.rs:9:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct A([u8]); - | ---- this field does not implement `ConstParamTy_` + | ^ ---- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:10:10 + --> $DIR/unsized_field-1.rs:9:10 | LL | struct A([u8]); | ^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:12:10 + --> $DIR/unsized_field-1.rs:13:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct B(&'static [u8]); - | ------------- this field does not implement `ConstParamTy_` + | ^ ------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `&'static [u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:14:10 + --> $DIR/unsized_field-1.rs:13:10 | LL | struct B(&'static [u8]); | ^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:19:10 + --> $DIR/unsized_field-1.rs:20:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); - | ---------------------------------------------------------- this field does not implement `ConstParamTy_` + | ^ ---------------------------------------------------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:21:10 + --> $DIR/unsized_field-1.rs:20:10 | LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs index 500e8e22b0e3..71ac662cf580 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs @@ -6,8 +6,8 @@ use std::marker::ConstParamTy; #[derive(Debug, PartialEq, Eq, ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` struct Foo { +//~^ ERROR the trait `ConstParamTy_` nested: &'static Bar, //~^ ERROR the size for values //~| ERROR the size for values diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index 1aaa7591a7be..f90f0b45d967 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -19,11 +19,13 @@ LL | struct Bar(T); | this could be changed to `T: ?Sized`... error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32 + --> $DIR/unsizing-wfcheck-issue-126272.rs:9:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^^^^^^^^ -... + | ------------ in this derive macro expansion +LL | struct Foo { + | ^^^ +LL | LL | nested: &'static Bar, | ----------------------------------------- this field does not implement `ConstParamTy_` | @@ -62,9 +64,12 @@ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Bar(T); - | - + | ^^^ - = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -97,9 +102,12 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ unsatisfied trait bound introduced in this `derive` macro + | ^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Bar(T); - | - would need to be `Eq` + | ^^^ - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 991a48917efb..aa9177d2b017 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,9 +8,12 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Foo(T); - | - would need to be `Copy` + | ^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.rs b/tests/ui/derives/copy-drop-mutually-exclusive.rs index 5147605910d7..64cd5bf594b0 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.rs +++ b/tests/ui/derives/copy-drop-mutually-exclusive.rs @@ -1,14 +1,14 @@ //! Regression test for issue #20126: Copy and Drop traits are mutually exclusive -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Foo; +#[derive(Copy, Clone)] +struct Foo; //~ ERROR the trait `Copy` cannot be implemented impl Drop for Foo { fn drop(&mut self) {} } -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Bar(::std::marker::PhantomData); +#[derive(Copy, Clone)] +struct Bar(::std::marker::PhantomData); //~ ERROR the trait `Copy` cannot be implemented impl Drop for Bar { fn drop(&mut self) {} diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.stderr b/tests/ui/derives/copy-drop-mutually-exclusive.stderr index 771bbc925695..f17d33ffbfed 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.stderr +++ b/tests/ui/derives/copy-drop-mutually-exclusive.stderr @@ -1,14 +1,18 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:3:10 + --> $DIR/copy-drop-mutually-exclusive.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:10:10 + --> $DIR/copy-drop-mutually-exclusive.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Bar(::std::marker::PhantomData); + | ^^^ `Copy` not allowed on types with destructors error: aborting due to 2 previous errors diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 1baacf85f6a2..226163474482 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,9 +10,12 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Copy` + | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -36,9 +39,12 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Clone` + | ^ - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -62,9 +68,12 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Copy` + | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr index 27691f571884..c033a3d227c1 100644 --- a/tests/ui/derives/issue-97343.stderr +++ b/tests/ui/derives/issue-97343.stderr @@ -2,12 +2,11 @@ error[E0109]: type arguments are not allowed on type parameter `Irrelevant` --> $DIR/issue-97343.rs:4:23 | LL | #[derive(Debug)] - | ----- - | | - | not allowed on type parameter `Irrelevant` - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Irrelevant { - | ^^^^^^^^^^ type argument not allowed + | ---------- ^^^^^^^^^^ type argument not allowed + | | + | not allowed on type parameter `Irrelevant` | note: type parameter `Irrelevant` defined here --> $DIR/issue-97343.rs:4:23 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs index 8e5cd4248f14..f4193f18352d 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs @@ -3,12 +3,12 @@ struct NonGeneric {} #[derive(Default)] -//~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied -//~^^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied struct NonGeneric<'a, const N: usize> {} -//~^ ERROR lifetime parameter `'a` is never used -//~^^ ERROR the name `NonGeneric` is defined multiple times +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR: lifetime parameter `'a` is never used +//~| ERROR: the name `NonGeneric` is defined multiple times pub fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr index cf9c0d0ad3be..0d6aaaf5186d 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NonGeneric` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:1 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:1 | LL | struct NonGeneric {} | ----------------- previous definition of the type `NonGeneric` here @@ -37,7 +37,7 @@ LL | struct NonGeneric {} | ^^^^^^^^^^ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:19 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:19 | LL | struct NonGeneric<'a, const N: usize> {} | ^^ unused lifetime parameter @@ -45,29 +45,26 @@ LL | struct NonGeneric<'a, const N: usize> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 lifetime arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | -- help: remove the lifetime argument + | ^^^^^^^^^^ -- help: remove the lifetime argument + | | + | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 | LL | struct NonGeneric {} | ^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 generic arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | - help: remove the unnecessary generic argument + | ^^^^^^^^^^ - help: remove the unnecessary generic argument + | | + | expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs index f3bf299aa65f..e946c0c5350e 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs @@ -8,12 +8,12 @@ struct NotSM; #[derive(PartialEq, Eq)] -//~^ ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments +//~^ ERROR: struct takes 0 generic arguments struct NotSM(T); -//~^ ERROR the name `NotSM` is defined multiple times -//~| ERROR no field `0` +//~^ ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: the name `NotSM` is defined multiple times +//~| ERROR: no field `0` fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr index 32c3cf440316..e80cf35d81e1 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NotSM` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:1 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:1 | LL | struct NotSM; | ------------- previous definition of the type `NotSM` here @@ -10,10 +10,10 @@ LL | struct NotSM(T); = note: `NotSM` must be defined only once in the type namespace of this module error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -30,27 +30,27 @@ LL | #[derive(PartialEq, Eq)] note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 | +LL | struct NotSM; + | ^^^^^ + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 + | +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 + | LL | struct NotSM; | ^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:21 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^ expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 - | -LL | struct NotSM; - | ^^^^^ - -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 - | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -60,7 +60,7 @@ LL | struct NotSM; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0609]: no field `0` on type `&NotSM` - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:17 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:17 | LL | struct NotSM(T); | ^ unknown field diff --git a/tests/ui/error-codes/E0184.rs b/tests/ui/error-codes/E0184.rs index 0c448e4ad8bc..64cc1f0d1538 100644 --- a/tests/ui/error-codes/E0184.rs +++ b/tests/ui/error-codes/E0184.rs @@ -1,5 +1,5 @@ -#[derive(Copy)] //~ ERROR E0184 -struct Foo; +#[derive(Copy)] +struct Foo; //~ ERROR E0184 impl Drop for Foo { fn drop(&mut self) { diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 1a7df9ac095a..98b5305ad0dc 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -1,8 +1,10 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/E0184.rs:1:10 + --> $DIR/E0184.rs:2:8 | LL | #[derive(Copy)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index fd7dd774cf08..d918bd62c2d7 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,9 +32,12 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Fooy(T); - | - would need to be `Copy` + | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -59,9 +62,12 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Fooy(T); - | - would need to be `Copy` + | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/issues/issue-27340.rs index 53ca2bc973ff..9966c24a7441 100644 --- a/tests/ui/issues/issue-27340.rs +++ b/tests/ui/issues/issue-27340.rs @@ -1,7 +1,7 @@ struct Foo; #[derive(Copy, Clone)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(Foo); -//~^ ERROR `Foo: Clone` is not satisfied +//~^ ERROR: the trait `Copy` cannot be implemented for this type +//~| ERROR: `Foo: Clone` is not satisfied fn main() {} diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr index 7cde901ffd95..3b4ad58b1f08 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/issues/issue-27340.stderr @@ -1,18 +1,16 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-27340.rs:2:10 + --> $DIR/issue-27340.rs:3:8 | LL | #[derive(Copy, Clone)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Bar(Foo); - | --- this field does not implement `Copy` + | ^^^ --- this field does not implement `Copy` error[E0277]: the trait bound `Foo: Clone` is not satisfied - --> $DIR/issue-27340.rs:4:12 + --> $DIR/issue-27340.rs:3:12 | LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion -LL | LL | struct Bar(Foo); | ^^^ the trait `Clone` is not implemented for `Foo` | diff --git a/tests/ui/malformed/malformed-derive-entry.rs b/tests/ui/malformed/malformed-derive-entry.rs index 77fa2f566a8f..f9dc98d9d270 100644 --- a/tests/ui/malformed/malformed-derive-entry.rs +++ b/tests/ui/malformed/malformed-derive-entry.rs @@ -1,14 +1,14 @@ #[derive(Copy(Bad))] -//~^ ERROR traits in `#[derive(...)]` don't accept arguments -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept arguments struct Test1; +//~^ ERROR: the trait bound #[derive(Copy="bad")] -//~^ ERROR traits in `#[derive(...)]` don't accept values -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept values struct Test2; +//~^ ERROR: the trait bound -#[derive] //~ ERROR malformed `derive` attribute input +#[derive] //~ ERROR: malformed `derive` attribute input struct Test4; fn main() {} diff --git a/tests/ui/malformed/malformed-derive-entry.stderr b/tests/ui/malformed/malformed-derive-entry.stderr index 02036e8d4c90..a5d7c3a4f8aa 100644 --- a/tests/ui/malformed/malformed-derive-entry.stderr +++ b/tests/ui/malformed/malformed-derive-entry.stderr @@ -17,10 +17,13 @@ LL | #[derive] | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error[E0277]: the trait bound `Test1: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:1:10 + --> $DIR/malformed-derive-entry.rs:3:8 | LL | #[derive(Copy(Bad))] - | ^^^^ the trait `Clone` is not implemented for `Test1` + | ---- in this derive macro expansion +LL | +LL | struct Test1; + | ^^^^^ the trait `Clone` is not implemented for `Test1` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -31,10 +34,13 @@ LL | struct Test1; | error[E0277]: the trait bound `Test2: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:6:10 + --> $DIR/malformed-derive-entry.rs:8:8 | LL | #[derive(Copy="bad")] - | ^^^^ the trait `Clone` is not implemented for `Test2` + | ---- in this derive macro expansion +LL | +LL | struct Test2; + | ^^^^^ the trait `Clone` is not implemented for `Test2` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index d420f2641daf..0c66b47b3941 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -12,12 +12,11 @@ struct PriorityQueueEntry { } #[derive(PartialOrd, AddImpl)] -//~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` -//~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied -//~| ERROR can't compare `T` with `T` -//~| ERROR no method named `cmp` found for struct `BinaryHeap>` -//~| ERROR no field `height` on type `&PriorityQueue` - +//~^ ERROR: the trait bound `PriorityQueue: Eq` is not satisfied +//~| ERROR: can't compare `T` with `T` +//~| ERROR: no method named `cmp` found for struct `BinaryHeap>` +//~| ERROR: no field `height` on type `&PriorityQueue` struct PriorityQueue(BinaryHeap>); -//~^ ERROR can't compare `BinaryHeap>` with `_` +//~^ ERROR: can't compare `PriorityQueue` with `PriorityQueue` +//~| ERROR: can't compare `BinaryHeap>` with `_` fn main() {} diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index c3513e19981f..e49cf6256cb2 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -1,11 +1,14 @@ error[E0277]: can't compare `PriorityQueue` with `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` + | ---------- in this derive macro expansion +... +LL | struct PriorityQueue(BinaryHeap>); + | ^^^^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` | help: the trait `PartialEq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +22,7 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ unsatisfied trait bound | help: the trait `Eq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,16 +40,19 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); - | - would need to be `PartialOrd` + | ^^^^^^^^^^^^^ - would need to be `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL error[E0277]: can't compare `BinaryHeap>` with `_` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:25 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:25 | LL | #[derive(PartialOrd, AddImpl)] | ---------- in this derive macro expansion diff --git a/tests/ui/range/range_traits-2.rs b/tests/ui/range/range_traits-2.rs index 234d7a64dc8b..7dd91243082c 100644 --- a/tests/ui/range/range_traits-2.rs +++ b/tests/ui/range/range_traits-2.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(Range); +#[derive(Copy, Clone)] +struct R(Range); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 2001c85c4348..f38539cc648c 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-2.rs:3:10 + --> $DIR/range_traits-2.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(Range); - | ------------ this field does not implement `Copy` + | ^ ------------ this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-3.rs b/tests/ui/range/range_traits-3.rs index 2d597cce5ad5..79ba1842f62f 100644 --- a/tests/ui/range/range_traits-3.rs +++ b/tests/ui/range/range_traits-3.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeFrom); +#[derive(Copy, Clone)] +struct R(RangeFrom); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index 71210379c79c..1f3768ad8d84 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-3.rs:3:10 + --> $DIR/range_traits-3.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeFrom); - | ---------------- this field does not implement `Copy` + | ^ ---------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-6.rs b/tests/ui/range/range_traits-6.rs index bce106bbfe79..72c6cecc88d6 100644 --- a/tests/ui/range/range_traits-6.rs +++ b/tests/ui/range/range_traits-6.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeInclusive); +#[derive(Copy, Clone)] +struct R(RangeInclusive); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index a58022ef7e4f..53fe2fed0a61 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-6.rs:3:10 + --> $DIR/range_traits-6.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeInclusive); - | --------------------- this field does not implement `Copy` + | ^ --------------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs index 8793a05c8a85..841bd5e32b8a 100644 --- a/tests/ui/span/E0204.rs +++ b/tests/ui/span/E0204.rs @@ -4,8 +4,8 @@ struct Foo { impl Copy for Foo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -struct Foo2<'a> { +#[derive(Copy)] +struct Foo2<'a> { //~ ERROR cannot be implemented for this type ty: &'a mut bool, } @@ -16,8 +16,8 @@ enum EFoo { impl Copy for EFoo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -enum EFoo2<'a> { +#[derive(Copy)] +enum EFoo2<'a> { //~ ERROR cannot be implemented for this type Bar(&'a mut bool), Baz, } diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr index fe375b94781b..a0b51be17863 100644 --- a/tests/ui/span/E0204.stderr +++ b/tests/ui/span/E0204.stderr @@ -8,11 +8,12 @@ LL | impl Copy for Foo { } | ^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:7:10 + --> $DIR/E0204.rs:8:8 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | struct Foo2<'a> { + | ^^^^ LL | ty: &'a mut bool, | ---------------- this field does not implement `Copy` @@ -26,11 +27,12 @@ LL | impl Copy for EFoo { } | ^^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:19:10 + --> $DIR/E0204.rs:20:6 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | enum EFoo2<'a> { + | ^^^^^ LL | Bar(&'a mut bool), | ------------ this field does not implement `Copy` diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed index 4dc362f94787..17259dd687c6 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.fixed +++ b/tests/ui/suggestions/derive-clone-for-eq.fixed @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs index b3635000f165..3e4331745be8 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.rs +++ b/tests/ui/suggestions/derive-clone-for-eq.rs @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index eb0355853daa..bed5ff90c194 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/derive-clone-for-eq.rs:4:17 + --> $DIR/derive-clone-for-eq.rs:5:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/derive-clone-for-eq.rs:7:19 diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 800f07054af7..872ce7105ce8 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -27,9 +27,12 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,9 +72,12 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 74df1d7c7cfd..bd1785e35112 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 8550a4d72476..36502044bd46 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index e3375b67c86d..cc80e7297e48 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:11:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ -LL | pub struct AABB{ + | ---- in this derive macro expansion +LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -14,7 +15,7 @@ LL | pub loc: Vector2, | ^^^^^^^^^^ help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++ error[E0277]: `K` doesn't implement `Debug` @@ -30,7 +31,7 @@ LL | pub struct Vector2{ | ^^^^^ required by this bound in `Vector2` help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -38,13 +39,13 @@ error[E0277]: `K` doesn't implement `Debug` | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion -LL | pub struct AABB{ +LL | pub struct AABB { LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -58,7 +59,7 @@ LL | pub size: Vector2 | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 0ffc1b8f7a25..60a9074e5c0d 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -6,8 +6,8 @@ pub struct Vector2 { pub y: T, } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB { +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~^ ERROR doesn't implement `Debug` //~| ERROR `K: Copy` is not satisfied diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 3f889f31484b..f843fb0d6d7e 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 + --> $DIR/missing-bound-in-derive-copy-impl.rs:10:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -62,9 +63,12 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -132,9 +136,12 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 275cef7a94fd..02c7fe9e689e 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -11,9 +11,12 @@ note: required for `Id` to implement `PartialEq` --> $DIR/derive-implicit-bound.rs:5:10 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Id(PhantomData); - | - would need to be `PartialEq` + | ^^ - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index d45668312218..6b04004621d8 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] -//~^ ERROR expected a type, found a trait -//~| ERROR expected a type, found a trait -struct Foo; -trait Foo {} //~ ERROR the name `Foo` is defined multiple times +#[derive(Clone)] //~ ERROR: expected a type, found a trait +struct Foo; //~ ERROR: expected a type, found a trait +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 815787c3bfec..ebb22cb9cd74 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 @@ -9,18 +9,23 @@ LL | trait Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0782]: expected a type, found a trait - --> $DIR/issue-106072.rs:1:10 + --> $DIR/issue-106072.rs:2:8 | LL | #[derive(Clone)] - | ^^^^^ + | ----- in this derive macro expansion +LL | struct Foo; + | ^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | struct dyn Foo; + | +++ error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 | LL | #[derive(Clone)] | ^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index ccd35a850f2d..2f62906e9df3 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -1,18 +1,17 @@ #[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Foo(N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator -#[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type -//~| ERROR `i32` is not an iterator +#[derive(Clone, Copy)] //~ ERROR `i32` is not an iterator struct Bar(T, N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 32c8b2cf3ac1..1fb5e8b00783 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -10,13 +10,13 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -27,7 +27,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope @@ -38,7 +38,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, St | ++++++++++++ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:14:18 + --> $DIR/issue-50480.rs:12:18 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | - ^ @@ -56,13 +56,13 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, Strin | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:14:21 + --> $DIR/issue-50480.rs:12:21 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:27 + --> $DIR/issue-50480.rs:2:27 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -70,29 +70,27 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:1:17 + --> $DIR/issue-50480.rs:2:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:11:17 + --> $DIR/issue-50480.rs:12:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -... + | ---- in this derive macro expansion LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -100,7 +98,7 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:28 + --> $DIR/issue-50480.rs:2:28 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^ `i32` is not an iterator @@ -116,11 +114,10 @@ LL | #[derive(Clone, Copy)] = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | #[derive(Clone, Copy)] | ----- in this derive macro expansion -... LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs index 2b4f7ba9fa29..ceef87d76abb 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs @@ -12,8 +12,8 @@ // we already face this difficulty, probably. If we need to fix this by reducing the error margin, // we should improve compiletest. -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr index 290b1df1665d..912286a48faf 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/global-cache-and-parallel-frontend.rs:15:17 + --> $DIR/global-cache-and-parallel-frontend.rs:16:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/global-cache-and-parallel-frontend.rs:18:19 From b9e5cf7806b824c1080b66755701840f9d88f80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:57:27 +0000 Subject: [PATCH 07/17] Fix incorrect suggestion caused by change in derive expansion Span --- .../rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs | 6 +++++- tests/ui/traits/issue-106072.stderr | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 29f29761b605..57defac577d8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -592,7 +592,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if span.can_be_used_for_suggestions() && poly_trait_ref.trait_ref.trait_def_id().is_some() && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag) - && !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag) + && !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag) { self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag); } @@ -750,10 +750,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn maybe_suggest_dyn_trait( &self, hir_id: hir::HirId, + span: Span, sugg: Vec<(Span, String)>, diag: &mut Diag<'_>, ) -> bool { let tcx = self.tcx(); + if span.in_derive_expansion() { + return false; + } // Look at the direct HIR parent, since we care about the relationship between // the type and the thing that directly encloses it. diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index ebb22cb9cd74..57661fda7307 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -15,11 +15,6 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct Foo; | ^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | struct dyn Foo; - | +++ error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 From dd8148373fa376541b40e24129251153e0bf5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:16:39 +0000 Subject: [PATCH 08/17] Tweak span labels --- .../src/error_reporting/traits/suggestions.rs | 12 +++------ tests/ui/associated-types/issue-38821.stderr | 27 +++++++------------ .../unsizing-wfcheck-issue-126272.stderr | 16 ++++------- .../ui/consts/const-blocks/trait-error.stderr | 7 ++--- tests/ui/derives/deriving-copyclone.stderr | 21 +++++---------- .../impl_bounds.stderr | 14 +++------- .../issue-104884-trait-impl-sugg-err.stderr | 7 ++--- ...missing-bound-in-derive-copy-impl-2.stderr | 18 +++++-------- .../missing-bound-in-derive-copy-impl.stderr | 18 +++++-------- tests/ui/traits/derive-implicit-bound.stderr | 7 ++--- 10 files changed, 46 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index c9dc390ea0be..70a16b23d276 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3581,7 +3581,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. })) => { let mut spans = Vec::with_capacity(2); - if let Some(of_trait) = of_trait { + if let Some(of_trait) = of_trait + && !of_trait.trait_ref.path.span.in_derive_expansion() + { spans.push(of_trait.trait_ref.path.span); } spans.push(self_ty.span); @@ -3595,18 +3597,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { derived = true; - spans.push_span_label( - data.span.ctxt().outer_expn_data().call_site, - format!( - "unsatisfied trait bound introduced in this `derive` macro" - ), - ); spans.push_span_label( data.span, if data.span.in_derive_expansion() { format!("would need to be `{trait_name}`") } else { - format!("") + format!("unsatisfied trait bound") }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 58d06860fe30..fae388c98d36 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -98,19 +98,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Debug` - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | @@ -152,19 +149,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Copy` - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | @@ -235,19 +229,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Clone` - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index f90f0b45d967..fc681e655e1a 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -61,15 +61,12 @@ help: the trait `Debug` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^^^^ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | struct Bar(T); - | ^^^ - + | ^^^ - unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -99,13 +96,10 @@ help: the trait `Eq` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^ note: required for `Bar` to implement `Eq` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | -- in this derive macro expansion LL | struct Bar(T); | ^^^ - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index aa9177d2b017..60402a412362 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -5,13 +5,10 @@ LL | [Foo(String::new()); 4]; | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | note: required for `Foo` to implement `Copy` - --> $DIR/trait-error.rs:1:10 + --> $DIR/trait-error.rs:2:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Foo(T); | ^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 226163474482..f8d2859f211e 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -7,13 +7,10 @@ LL | is_copy(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct B { | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds @@ -36,13 +33,10 @@ LL | is_clone(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Clone` - --> $DIR/deriving-copyclone.rs:9:16 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | struct B { | ^ - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds @@ -65,13 +59,10 @@ LL | is_copy(B { a: 1, b: D }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct B { | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index d918bd62c2d7..f65675686532 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -29,13 +29,10 @@ LL | type C = String where Self: Copy; | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds @@ -59,13 +56,10 @@ LL | fn d() where Self: Copy {} | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index e49cf6256cb2..d14f9eae6950 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,13 +37,10 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ no implementation for `T < T` and `T > T` | note: required for `PriorityQueue` to implement `PartialOrd` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---------- in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^ - would need to be `PartialOrd` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 872ce7105ce8..791e2d19f2f9 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -24,15 +24,12 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,15 +66,12 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index f843fb0d6d7e..55d6391f975e 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -60,15 +60,12 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -133,15 +130,12 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 02c7fe9e689e..ee78cba5af27 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -8,13 +8,10 @@ LL | accept_eq(&node); | = help: the trait `PartialEq` is not implemented for `SomeNode` note: required for `Id` to implement `PartialEq` - --> $DIR/derive-implicit-bound.rs:5:10 + --> $DIR/derive-implicit-bound.rs:6:12 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | --------- in this derive macro expansion LL | pub struct Id(PhantomData); | ^^ - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds From 20000ca25a90c1704e02e349b9583b0bb00086b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:28:58 +0000 Subject: [PATCH 09/17] Point at destructor when denying deriving `Copy` --- compiler/rustc_hir_analysis/messages.ftl | 1 + compiler/rustc_hir_analysis/src/coherence/builtin.rs | 5 +++-- compiler/rustc_hir_analysis/src/errors.rs | 2 ++ compiler/rustc_trait_selection/src/traits/misc.rs | 6 +++--- tests/ui/derives/copy-drop-mutually-exclusive.stderr | 12 ++++++++++++ tests/ui/error-codes/E0184.stderr | 6 ++++++ 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index d9f8eba65c4a..611aa070124a 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -142,6 +142,7 @@ hir_analysis_copy_impl_on_non_adt = hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors + .note = destructor declared here hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}` .label = can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 61562cc1e4f3..558d2ec84e4b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -121,9 +121,10 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span })) } - Err(CopyImplementationError::HasDestructor) => { + Err(CopyImplementationError::HasDestructor(did)) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; - Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span })) + let impl_ = tcx.def_span(did); + Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ })) } Err(CopyImplementationError::HasUnsafeFields) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a77d0b997e2..b90ccc6716d0 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -278,6 +278,8 @@ pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] #[label] pub span: Span, + #[note] + pub impl_: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index f33196bab647..2fd3a6e738cf 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -13,7 +13,7 @@ use crate::traits::{self, FulfillmentError, Obligation, ObligationCause}; pub enum CopyImplementationError<'tcx> { InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>), NotAnAdt, - HasDestructor, + HasDestructor(hir::def_id::DefId), HasUnsafeFields, } @@ -76,8 +76,8 @@ pub fn type_allowed_to_implement_copy<'tcx>( ) .map_err(CopyImplementationError::InfringingFields)?; - if adt.has_dtor(tcx) { - return Err(CopyImplementationError::HasDestructor); + if let Some(did) = adt.destructor(tcx).map(|dtor| dtor.did) { + return Err(CopyImplementationError::HasDestructor(did)); } if impl_safety.is_safe() && self_type.has_unsafe_fields() { diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.stderr b/tests/ui/derives/copy-drop-mutually-exclusive.stderr index f17d33ffbfed..ab2d086c7f5f 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.stderr +++ b/tests/ui/derives/copy-drop-mutually-exclusive.stderr @@ -5,6 +5,12 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo; | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:7:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor --> $DIR/copy-drop-mutually-exclusive.rs:11:8 @@ -13,6 +19,12 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Bar(::std::marker::PhantomData); | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:14:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 98b5305ad0dc..13294959bc3c 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -5,6 +5,12 @@ LL | #[derive(Copy)] | ---- in this derive macro expansion LL | struct Foo; | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/E0184.rs:5:5 + | +LL | fn drop(&mut self) { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error From 23b766ce631dc90c89f1c71878058a2618b7b8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:43:18 +0000 Subject: [PATCH 10/17] fix typo --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- tests/ui/traits/derive-implicit-bound-on-clone.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 285288e87ee0..349b2c756b64 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1937,7 +1937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { let manually_impl = "consider manually implementing `Clone` to avoid the \ - implict type parameter bounds"; + implicit type parameter bounds"; match &errors[..] { [] => {} [error] => { diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.stderr b/tests/ui/traits/derive-implicit-bound-on-clone.stderr index 0cec4ef7c609..2fb039f96528 100644 --- a/tests/ui/traits/derive-implicit-bound-on-clone.stderr +++ b/tests/ui/traits/derive-implicit-bound-on-clone.stderr @@ -22,7 +22,7 @@ LL | struct ContainsRc { | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` | | | derive introduces an implicit unsatisfied trait bound `T: Clone` - = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error[E0308]: mismatched types --> $DIR/derive-implicit-bound-on-clone.rs:20:5 @@ -46,7 +46,7 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct ContainsRcSingle { | ^ derive introduces an implicit `T: Clone` bound - = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error: aborting due to 2 previous errors From b534229a3ace7e39381efb8941d8277d17a985f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 18:49:12 +0000 Subject: [PATCH 11/17] remove commented out code --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 349b2c756b64..b8f99bbd7e17 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1941,8 +1941,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &errors[..] { [] => {} [error] => { - // diag.note("{error:#?}"); - // diag.note(format!("{:#?} {:#?} {:#?}", error.obligation, error.obligation.cause, error.obligation.cause.code())); let msg = "`Clone` is not implemented because a trait bound is not \ satisfied"; if let traits::ObligationCauseCode::ImplDerived(data) = From 6c8eee82970d4b1659329a8ff1f9bad7ac66e152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 18:59:32 +0000 Subject: [PATCH 12/17] reword span label --- .../src/error_reporting/traits/suggestions.rs | 2 +- .../adt_const_params/unsizing-wfcheck-issue-126272.stderr | 2 +- tests/ui/consts/const-blocks/trait-error.stderr | 2 +- tests/ui/derives/deriving-copyclone.stderr | 6 +++--- tests/ui/generic-associated-types/impl_bounds.stderr | 4 ++-- tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr | 2 +- tests/ui/traits/derive-implicit-bound.stderr | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 70a16b23d276..1880465eff54 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3600,7 +3600,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { spans.push_span_label( data.span, if data.span.in_derive_expansion() { - format!("would need to be `{trait_name}`") + format!("type parameter would need to implement `{trait_name}`") } else { format!("unsatisfied trait bound") }, diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index fc681e655e1a..f520413927c3 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -101,7 +101,7 @@ note: required for `Bar` to implement `Eq` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | -- in this derive macro expansion LL | struct Bar(T); - | ^^^ - would need to be `Eq` + | ^^^ - type parameter would need to implement `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 60402a412362..853e10e0b35a 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -10,7 +10,7 @@ note: required for `Foo` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo(T); - | ^^^ - would need to be `Copy` + | ^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index f8d2859f211e..40f96919121f 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -12,7 +12,7 @@ note: required for `B` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { - | ^ - would need to be `Copy` + | ^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -38,7 +38,7 @@ note: required for `B` to implement `Clone` LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion LL | struct B { - | ^ - would need to be `Clone` + | ^ - type parameter would need to implement `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -64,7 +64,7 @@ note: required for `B` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { - | ^ - would need to be `Copy` + | ^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index f65675686532..63c4ba900829 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -34,7 +34,7 @@ note: required for `Fooy` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); - | ^^^^ - would need to be `Copy` + | ^^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -61,7 +61,7 @@ note: required for `Fooy` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); - | ^^^^ - would need to be `Copy` + | ^^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index d14f9eae6950..b53ebe9f7271 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -43,7 +43,7 @@ LL | #[derive(PartialOrd, AddImpl)] | ---------- in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); - | ^^^^^^^^^^^^^ - would need to be `PartialOrd` + | ^^^^^^^^^^^^^ - type parameter would need to implement `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index ee78cba5af27..fe2bc77b9529 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -13,7 +13,7 @@ note: required for `Id` to implement `PartialEq` LL | #[derive(PartialEq, Eq)] | --------- in this derive macro expansion LL | pub struct Id(PhantomData); - | ^^ - would need to be `PartialEq` + | ^^ - type parameter would need to implement `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 From 879633f97b3affafd87a8726240b8109a7bc8363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 19:24:10 +0000 Subject: [PATCH 13/17] Change note to help --- .../src/diagnostics/conflict_errors.rs | 2 +- tests/ui/associated-types/issue-25700.stderr | 2 +- .../closure-shim-borrowck-error.stderr | 2 +- .../async-closures/move-out-of-ref.stderr | 2 +- .../borrowck-move-out-of-static-item.stderr | 2 +- .../borrowck-move-subcomponent.stderr | 2 +- .../borrowck/borrowck-overloaded-call.stderr | 2 +- tests/ui/borrowck/clone-on-ref.stderr | 2 +- .../borrowck/derive-clone-implicit-bound.rs | 4 ++-- .../derive-clone-implicit-bound.stderr | 2 +- tests/ui/borrowck/issue-103624.stderr | 2 +- .../issue-119915-bad-clone-suggestion.stderr | 2 +- .../borrowck/issue-17718-static-move.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 8 +++---- .../borrowck/move-error-in-promoted-2.stderr | 2 +- tests/ui/borrowck/move-error-snippets.stderr | 2 +- ...e-in-static-initializer-issue-38520.stderr | 4 ++-- tests/ui/box/leak-alloc.stderr | 2 +- .../closure-move-use-after-move-diagnostic.rs | 2 +- ...sure-move-use-after-move-diagnostic.stderr | 2 +- tests/ui/coroutine/moved-twice.stderr | 2 +- .../derives/deriving-with-repr-packed.stderr | 2 +- tests/ui/error-codes/E0504.stderr | 2 +- tests/ui/error-codes/E0505.stderr | 2 +- tests/ui/error-codes/E0507.stderr | 2 +- tests/ui/error-codes/E0508-fail.stderr | 2 +- tests/ui/error-codes/E0508.stderr | 2 +- tests/ui/error-codes/E0509.stderr | 2 +- tests/ui/mir/issue-102389.stderr | 2 +- tests/ui/moves/issue-72649-uninit-in-loop.rs | 10 ++++---- .../moves/issue-72649-uninit-in-loop.stderr | 15 ++++++------ .../issue-75904-move-closure-loop.stderr | 2 +- ...atching-partially-moved-value-17385.stderr | 4 ++-- tests/ui/moves/move-fn-self-receiver.stderr | 2 +- tests/ui/moves/move-out-of-array-1.stderr | 2 +- .../ui/moves/moved-value-on-as-ref-arg.stderr | 4 ++-- .../issue-21232-partial-init-and-use.stderr | 4 ++-- tests/ui/nll/move-errors.stderr | 12 +++++----- .../pin-ergonomics/borrow-unpin.pinned.stderr | 24 +++++++++---------- .../pin-ergonomics/borrow-unpin.unpin.stderr | 6 ++--- tests/ui/pin-macro/pin_move.stderr | 4 ++-- .../non_copy_move_out_of_tuple.stderr | 2 +- .../suggestions/option-content-move3.stderr | 4 ++-- .../union-borrow-move-parent-sibling.stderr | 2 +- tests/ui/union/union-move.stderr | 4 ++-- tests/ui/variance/variance-issue-20533.stderr | 8 +++---- 46 files changed, 90 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 692ce240e36f..72a35de73f32 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1301,7 +1301,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ), ); span.push_span_label(expr.span, "you could clone this value"); - err.span_note( + err.span_help( span, format!("if `{ty}` implemented `Clone`, you could clone the value"), ); diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index 8d40e6905e07..595aefc9a215 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -8,7 +8,7 @@ LL | drop(t); LL | drop(t); | ^ value used here after move | -note: if `S<()>` implemented `Clone`, you could clone the value +help: if `S<()>` implemented `Clone`, you could clone the value --> $DIR/issue-25700.rs:1:1 | LL | struct S(#[allow(dead_code)] Option<&'static T>); diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index 3fe1431fda71..a4d239090830 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -9,7 +9,7 @@ LL | LL | x.hello(); | - variable moved due to use in coroutine | -note: if `Ty` implemented `Clone`, you could clone the value +help: if `Ty` implemented `Clone`, you could clone the value --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr index d443dc9d4831..c516597c81f9 100644 --- a/tests/ui/async-await/async-closures/move-out-of-ref.stderr +++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr @@ -7,7 +7,7 @@ LL | let c = async || { LL | *x; | ^^ `*x` is moved here | -note: if `Ty` implemented `Clone`, you could clone the value +help: if `Ty` implemented `Clone`, you could clone the value --> $DIR/move-out-of-ref.rs:5:1 | LL | struct Ty; diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index b4b60d40d914..9eb90e169fd3 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-out-of-static-item.rs:3:1 | LL | struct Foo { diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index b5dc01f180b2..8dcb81273f89 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -10,7 +10,7 @@ LL | let S { x: ax } = a; LL | f(pb); | -- borrow later used here | -note: if `S` implemented `Clone`, you could clone the value +help: if `S` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-subcomponent.rs:6:1 | LL | struct S { diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index c3b7b0b6080c..c838c6512bc4 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -30,7 +30,7 @@ LL | s(" world".to_string()); LL | s(" world".to_string()); | ^ value used here after move | -note: if `SFnOnce` implemented `Clone`, you could clone the value +help: if `SFnOnce` implemented `Clone`, you could clone the value --> $DIR/borrowck-overloaded-call.rs:41:1 | LL | struct SFnOnce { diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index 72580e7464b7..535550409dd8 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -59,7 +59,7 @@ LL | LL | println!("{b:?}"); | - borrow later used here | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 | LL | struct A; diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs index a20e04d3afdc..12fd2129331b 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.rs +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; #[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters pub struct TypedAddress{ -//~^ NOTE if `TypedAddress` implemented `Clone`, you could clone the value +//~^ HELP if `TypedAddress` implemented `Clone`, you could clone the value //~| NOTE consider manually implementing `Clone` for this type //~| NOTE introduces an implicit `T: Clone` bound inner: u64, @@ -19,7 +19,7 @@ pub trait Memory { //~| NOTE this parameter takes ownership of the value fn update_value(&self, offset: TypedAddress, update: F) //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait - where F: FnOnce(T) -> T + where F: FnOnce(T) -> T //~ HELP consider further restricting type parameter `T` { let old = self.return_value(offset); //~ NOTE value moved here //~^ NOTE you could clone this value diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr index b10e3a92c96b..31a55b448eb6 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.stderr +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -15,7 +15,7 @@ note: consider changing this parameter type in method `return_value` to borrow i | LL | fn return_value(&self, offset: TypedAddress) -> T; | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value -note: if `TypedAddress` implemented `Clone`, you could clone the value +help: if `TypedAddress` implemented `Clone`, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index bd6c1c44bfb3..85769e187691 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -18,7 +18,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { | ^^^^^^^^^^^ -note: if `StructB` implemented `Clone`, you could clone the value +help: if `StructB` implemented `Clone`, you could clone the value --> $DIR/issue-103624.rs:23:1 | LL | self.b; diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr index dde17d1f6523..a5a218a0641d 100644 --- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -11,7 +11,7 @@ note: `Example::::change` takes ownership of the receiver `self`, | LL | unsafe fn change(self) -> Example { | ^^^^ -note: if `Example` implemented `Clone`, you could clone the value +help: if `Example` implemented `Clone`, you could clone the value --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1 | LL | struct Example(PhantomData<(fn(E), fn(FakeParam))>); diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index 057ac6d7e3df..959b1d1a3b84 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `FOO` LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 5fda92634d8f..5336352e0dbd 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a mutable reference LL | let a = unsafe { *mut_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -24,7 +24,7 @@ error[E0507]: cannot move out of a shared reference LL | let b = unsafe { *imm_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -44,7 +44,7 @@ error[E0507]: cannot move out of a raw pointer LL | let c = unsafe { *mut_ptr() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -59,7 +59,7 @@ error[E0507]: cannot move out of a raw pointer LL | let d = unsafe { *const_ptr() }; | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index 1e9b1d5209cb..f2bc6bd4760a 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -7,7 +7,7 @@ LL | &([S][0],); | cannot move out of here | move occurs because value has type `S`, which does not implement the `Copy` trait | -note: if `S` implemented `Clone`, you could clone the value +help: if `S` implemented `Clone`, you could clone the value --> $DIR/move-error-in-promoted-2.rs:3:1 | LL | struct S; diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 97d140515184..3796b7e05fb4 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -9,7 +9,7 @@ LL | let a = $c; LL | sss!(); | ------ in this macro invocation | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 | LL | struct A; diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr index 009e85a8031e..af5cbdcf150f 100644 --- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | static Y: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); @@ -19,7 +19,7 @@ error[E0507]: cannot move out of a shared reference LL | const Z: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index bdaa9449f913..f0d6dd3d4692 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -12,7 +12,7 @@ LL | LL | use_value(*theref) | ------- borrow later used here | -note: if `Alloc` implemented `Clone`, you could clone the value +help: if `Alloc` implemented `Clone`, you could clone the value --> $DIR/leak-alloc.rs:8:1 | LL | struct Alloc {} diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs index 3326af7486c5..b55c8c16f611 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs @@ -1,5 +1,5 @@ //! regression test for -struct NoCopy; //~ NOTE if `NoCopy` implemented `Clone`, you could clone the value +struct NoCopy; //~ HELP if `NoCopy` implemented `Clone`, you could clone the value //~^ NOTE consider implementing `Clone` for this type fn main() { let x = NoCopy; diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr index 94f80da1b10a..bde39ca6ca71 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr @@ -13,7 +13,7 @@ LL | let y = x; LL | let z = x; | ^ value used here after move | -note: if `NoCopy` implemented `Clone`, you could clone the value +help: if `NoCopy` implemented `Clone`, you could clone the value --> $DIR/closure-move-use-after-move-diagnostic.rs:2:1 | LL | struct NoCopy; diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr index 2b21f6c59f0b..561b3b331d9f 100644 --- a/tests/ui/coroutine/moved-twice.stderr +++ b/tests/ui/coroutine/moved-twice.stderr @@ -10,7 +10,7 @@ LL | yield; LL | let second = first; | ^^^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/moved-twice.rs:9:1 | LL | struct Foo([u8; FOO_SIZE]); diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 9cfc4abdc0cb..7c716fb9dd4c 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -7,7 +7,7 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because value has type `Y`, which does not implement the `Copy` trait | -note: if `Y` implemented `Clone`, you could clone the value +help: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 | LL | struct Y(usize); diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index c4cbc834ad98..528f311765df 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -14,7 +14,7 @@ LL | println!("child function: {}", fancy_num.num); LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here | -note: if `FancyNum` implemented `Clone`, you could clone the value +help: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0504.rs:2:1 | LL | struct FancyNum { diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index 3f2913e9fe3c..ac0f390bc54b 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -11,7 +11,7 @@ LL | eat(x); LL | _ref_to_val.use_ref(); | ----------- borrow later used here | -note: if `Value` implemented `Clone`, you could clone the value +help: if `Value` implemented `Clone`, you could clone the value --> $DIR/E0505.rs:1:1 | LL | struct Value {} diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index 70d99ea2cce5..ac03e5ea9cd5 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -11,7 +11,7 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w | LL | fn nothing_is_true(self) {} | ^^^^ -note: if `TheDarkKnight` implemented `Clone`, you could clone the value +help: if `TheDarkKnight` implemented `Clone`, you could clone the value --> $DIR/E0507.rs:3:1 | LL | struct TheDarkKnight; diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index fcfac399e0df..48ede17dc26a 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508-fail.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index b9fa0f4d17a5..c001b9461ebf 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index 628a253e0859..89c3a5848423 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -7,7 +7,7 @@ LL | let fancy_field = drop_struct.fancy; | cannot move out of here | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait | -note: if `FancyNum` implemented `Clone`, you could clone the value +help: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0509.rs:1:1 | LL | struct FancyNum { diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 162d7ac031a6..7aafe081deaf 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference LL | array[*inbounds as usize] | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait | -note: if `Enum` implemented `Clone`, you could clone the value +help: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-102389.rs:1:1 | LL | enum Enum { A, B, C } diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 8f2e01bdf1ab..965a4206253e 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -3,10 +3,10 @@ // 'value moved in previous iteration of loop' message struct NonCopy; -//~^ NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` +//~^ HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type @@ -70,6 +70,7 @@ fn moved_loop_2() { fn uninit_1() { loop { let value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized } @@ -77,6 +78,7 @@ fn uninit_1() { fn uninit_2() { let mut value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value loop { let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 3a93769ac454..1c54d3997ed6 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -10,7 +10,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -33,7 +33,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -53,7 +53,7 @@ LL | loop { LL | let _used = value; | ^^^^^ value moved here, in previous iteration of loop | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -73,7 +73,7 @@ LL | loop { LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -83,10 +83,11 @@ LL | let _used2 = value; | ----- you could clone this value error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:73:21 + --> $DIR/issue-72649-uninit-in-loop.rs:74:21 | LL | let value: NonCopy; | ----- binding declared here but left uninitialized +LL | LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | @@ -96,11 +97,11 @@ LL | let value: NonCopy = /* value */; | +++++++++++++ error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:81:21 + --> $DIR/issue-72649-uninit-in-loop.rs:83:21 | LL | let mut value: NonCopy; | --------- binding declared here but left uninitialized -LL | loop { +... LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index 815e91b0f4df..3fc50c48315d 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -11,7 +11,7 @@ LL | &mut a; LL | a; | - use occurs due to use in closure | -note: if `NotCopy` implemented `Clone`, you could clone the value +help: if `NotCopy` implemented `Clone`, you could clone the value --> $DIR/issue-75904-move-closure-loop.rs:5:1 | LL | struct NotCopy; diff --git a/tests/ui/moves/matching-partially-moved-value-17385.stderr b/tests/ui/moves/matching-partially-moved-value-17385.stderr index 906f7868bccb..83f4f4320485 100644 --- a/tests/ui/moves/matching-partially-moved-value-17385.stderr +++ b/tests/ui/moves/matching-partially-moved-value-17385.stderr @@ -8,7 +8,7 @@ LL | drop(foo); LL | match foo { | ^^^^^^^^^ value used here after move | -note: if `X` implemented `Clone`, you could clone the value +help: if `X` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:2:1 | LL | struct X(isize); @@ -27,7 +27,7 @@ LL | drop(e); LL | match e { | ^ value used here after move | -note: if `Enum` implemented `Clone`, you could clone the value +help: if `Enum` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:4:1 | LL | enum Enum { diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index de19a99d388c..b3a1215fa2f7 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -132,7 +132,7 @@ LL | foo_add + Foo; LL | foo_add; | ^^^^^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 8a030f021920..7ef859200b21 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -7,7 +7,7 @@ LL | a[i] | cannot move out of here | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait | -note: if `D` implemented `Clone`, you could clone the value +help: if `D` implemented `Clone`, you could clone the value --> $DIR/move-out-of-array-1.rs:5:1 | LL | struct D { _x: u8 } diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.stderr b/tests/ui/moves/moved-value-on-as-ref-arg.stderr index a99bdb4fe9d4..b553938c6fed 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.stderr +++ b/tests/ui/moves/moved-value-on-as-ref-arg.stderr @@ -23,7 +23,7 @@ LL | qux(bar); LL | let _baa = bar; | ^^^ value used here after move | -note: if `Bar` implemented `Clone`, you could clone the value +help: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; @@ -61,7 +61,7 @@ LL | baz(bar); LL | let _baa = bar; | ^^^ value used here after move | -note: if `Bar` implemented `Clone`, you could clone the value +help: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr index 496a298a36ce..84c543921687 100644 --- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -28,7 +28,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move | -note: if `S>` implemented `Clone`, you could clone the value +help: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { @@ -82,7 +82,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move | -note: if `S>` implemented `Clone`, you could clone the value +help: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index bcb2ab84a239..e84f75455217 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | let b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -27,7 +27,7 @@ LL | let b = a[0]; | cannot move out of here | move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -46,7 +46,7 @@ error[E0507]: cannot move out of `**r` which is behind a shared reference LL | let s = **r; | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -66,7 +66,7 @@ error[E0507]: cannot move out of an `Rc` LL | let s = *r; | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -89,7 +89,7 @@ LL | let a = [A("".to_string())][0]; | cannot move out of here | move occurs because value has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -137,7 +137,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr index cc438461a5d1..f9bef8d83f96 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -8,7 +8,7 @@ LL | foo_pin_mut(&pin mut foo); LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -27,7 +27,7 @@ LL | let x = &pin mut foo; LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -46,7 +46,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -65,7 +65,7 @@ LL | let x = &pin mut foo; // ok LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -87,7 +87,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -106,7 +106,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -125,7 +125,7 @@ LL | let x = &pin mut foo; // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -144,7 +144,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -163,7 +163,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -185,7 +185,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -204,7 +204,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -223,7 +223,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr index bf9921343ee7..523191655813 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -33,7 +33,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -55,7 +55,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -77,7 +77,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr index 3f4660209885..cf7d50091ba4 100644 --- a/tests/ui/pin-macro/pin_move.stderr +++ b/tests/ui/pin-macro/pin_move.stderr @@ -8,7 +8,7 @@ LL | pin!(pointee); LL | let _moved = pointee; | ^^^^^^^ value used here after move | -note: if `a::NotCopy` implemented `Clone`, you could clone the value +help: if `a::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:7:5 | LL | struct NotCopy(T); @@ -23,7 +23,7 @@ error[E0507]: cannot move out of a mutable reference LL | pin!(*&mut pointee); | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait | -note: if `b::NotCopy` implemented `Clone`, you could clone the value +help: if `b::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:16:5 | LL | struct NotCopy(T); diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr index 62f24324fcc1..5e447a57bfee 100644 --- a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -7,7 +7,7 @@ LL | (b,) = *tuple; | data moved here | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/non_copy_move_out_of_tuple.rs:3:1 | LL | struct NonCopy; diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index f78d3cf67862..cd13592d652e 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -10,7 +10,7 @@ LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once -note: if `NotCopyable` implemented `Clone`, you could clone the value +help: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; @@ -43,7 +43,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | fn func H, H: FnMut()>(_: F) {} | ^^^^^^^^^^^^ -note: if `NotCopyable` implemented `Clone`, you could clone the value +help: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr index 461ee407e2dd..5974441dd807 100644 --- a/tests/ui/union/union-borrow-move-parent-sibling.stderr +++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr @@ -59,7 +59,7 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, Moc LL | let a = (u.x.0).0; | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait | -note: if `MockVec` implemented `Clone`, you could clone the value +help: if `MockVec` implemented `Clone`, you could clone the value --> $DIR/union-borrow-move-parent-sibling.rs:25:1 | LL | struct MockVec { diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr index d520fb00ea9d..6266bb4770e0 100644 --- a/tests/ui/union/union-move.stderr +++ b/tests/ui/union/union-move.stderr @@ -16,7 +16,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -note: if `U1` implemented `Clone`, you could clone the value +help: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { @@ -43,7 +43,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -note: if `U1` implemented `Clone`, you could clone the value +help: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr index 21d8de6ae881..2a33a88bdd56 100644 --- a/tests/ui/variance/variance-issue-20533.stderr +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -10,7 +10,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -31,7 +31,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -52,7 +52,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -73,7 +73,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); From 8543404e8d8668d9834dc48a687d5096d4949f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 21:33:39 +0000 Subject: [PATCH 14/17] Tweak span in E0599 --- .../rustc_hir_typeck/src/method/suggest.rs | 50 ++++++++++++------- .../derives/derive-assoc-type-not-impl.stderr | 6 ++- .../deriving-with-repr-packed-2.stderr | 7 ++- tests/ui/union/union-derive-clone.stderr | 6 ++- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f5ef5adff6bd..517d73f51783 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1752,16 +1752,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. - let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) { - Some(ObligationCauseCode::ImplDerived(data)) => { - (data.impl_or_alias_def_id, data.span) - } - Some( - ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) - | ObligationCauseCode::WhereClause(def_id, span), - ) if !span.is_dummy() => (*def_id, *span), - _ => continue, - }; + let (item_def_id, cause_span, cause_msg) = + match cause.as_ref().map(|cause| cause.code()) { + Some(ObligationCauseCode::ImplDerived(data)) => { + let msg = if let DefKind::Impl { of_trait: true } = + self.tcx.def_kind(data.impl_or_alias_def_id) + { + format!( + "type parameter would need to implement `{}`", + self.tcx + .item_name(self.tcx.impl_trait_id(data.impl_or_alias_def_id)) + ) + } else { + format!("unsatisfied bound `{p}` introduced here") + }; + (data.impl_or_alias_def_id, data.span, msg) + } + Some( + ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) + | ObligationCauseCode::WhereClause(def_id, span), + ) if !span.is_dummy() => { + (*def_id, *span, format!("unsatisfied bound `{p}` introduced here")) + } + _ => continue, + }; // Don't point out the span of `WellFormed` predicates. if !matches!( @@ -1792,10 +1806,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let entry = entry.or_insert_with(|| { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); - entry.0.insert(span); + entry.0.insert(cause_span); entry.1.insert(( - span, - "unsatisfied trait bound introduced in this `derive` macro", + cause_span, + cause_msg, )); entry.2.push(p); skip_list.insert(p); @@ -1844,7 +1858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.2.push(p); if cause_span != *item_span { entry.0.insert(cause_span); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); } else { if let Some(of_trait) = of_trait { entry.0.insert(of_trait.trait_ref.path.span); @@ -1852,9 +1866,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.0.insert(self_ty.span); }; if let Some(of_trait) = of_trait { - entry.1.insert((of_trait.trait_ref.path.span, "")); + entry.1.insert((of_trait.trait_ref.path.span, String::new())); } - entry.1.insert((self_ty.span, "")); + entry.1.insert((self_ty.span, String::new())); } Some(Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..), @@ -1883,8 +1897,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(cause_span); - entry.1.insert((ident.span, "")); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((ident.span, String::new())); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); entry.2.push(p); } _ => { diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index e239ad4ef209..ca968910fde4 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -11,10 +11,12 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds | note: trait bound `NotClone: Clone` was not satisfied - --> $DIR/derive-assoc-type-not-impl.rs:6:10 + --> $DIR/derive-assoc-type-not-impl.rs:7:12 | LL | #[derive(Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | struct Bar { + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NotClone` with `#[derive(Clone)]` | diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index fff6269472bd..6bd3fff39790 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -21,10 +21,13 @@ LL | let x: Foo = Foo(NonCopy, NonCopy, NonCopy); note: the following trait bounds were not satisfied: `NonCopy: Clone` `NonCopy: Copy` - --> $DIR/deriving-with-repr-packed-2.rs:5:16 + --> $DIR/deriving-with-repr-packed-2.rs:7:16 | LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | #[repr(packed)] +LL | pub struct Foo(T, T, T); + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]` | diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 65488629b629..62ef35b76192 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -25,10 +25,12 @@ LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds | note: trait bound `CloneNoCopy: Copy` was not satisfied - --> $DIR/union-derive-clone.rs:25:10 + --> $DIR/union-derive-clone.rs:26:10 | LL | #[derive(Clone, Copy)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | union U5 { + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | From dffec20dee76131f74736f05f01abf44161d3264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 21:54:43 +0000 Subject: [PATCH 15/17] Tweak help to unify formatting and wording --- .../src/diagnostics/conflict_errors.rs | 27 +++++++++++-------- tests/ui/associated-types/issue-25700.stderr | 2 +- .../closure-shim-borrowck-error.stderr | 2 +- .../async-closures/move-out-of-ref.stderr | 2 +- .../borrowck-move-out-of-static-item.stderr | 2 +- .../borrowck-move-subcomponent.stderr | 2 +- .../borrowck/borrowck-overloaded-call.stderr | 2 +- tests/ui/borrowck/clone-on-ref.stderr | 2 +- .../borrowck/derive-clone-implicit-bound.rs | 26 +++++++++--------- .../derive-clone-implicit-bound.stderr | 12 ++++----- tests/ui/borrowck/issue-103624.stderr | 2 +- .../issue-119915-bad-clone-suggestion.stderr | 2 +- .../borrowck/issue-17718-static-move.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 8 +++--- .../borrowck/move-error-in-promoted-2.stderr | 2 +- tests/ui/borrowck/move-error-snippets.stderr | 2 +- ...e-in-static-initializer-issue-38520.stderr | 4 +-- tests/ui/box/leak-alloc.stderr | 2 +- .../closure-move-use-after-move-diagnostic.rs | 16 +++++------ ...sure-move-use-after-move-diagnostic.stderr | 2 +- tests/ui/coroutine/moved-twice.stderr | 2 +- .../derives/deriving-with-repr-packed.stderr | 2 +- tests/ui/error-codes/E0504.stderr | 2 +- tests/ui/error-codes/E0505.stderr | 2 +- tests/ui/error-codes/E0507.stderr | 2 +- tests/ui/error-codes/E0508-fail.stderr | 2 +- tests/ui/error-codes/E0508.stderr | 2 +- tests/ui/error-codes/E0509.stderr | 2 +- tests/ui/mir/issue-102389.stderr | 2 +- tests/ui/moves/issue-72649-uninit-in-loop.rs | 8 +++--- .../moves/issue-72649-uninit-in-loop.stderr | 8 +++--- .../issue-75904-move-closure-loop.stderr | 2 +- ...atching-partially-moved-value-17385.stderr | 4 +-- tests/ui/moves/move-fn-self-receiver.stderr | 2 +- tests/ui/moves/move-out-of-array-1.stderr | 2 +- .../ui/moves/moved-value-on-as-ref-arg.stderr | 4 +-- .../issue-21232-partial-init-and-use.stderr | 4 +-- tests/ui/nll/move-errors.stderr | 12 ++++----- .../pin-ergonomics/borrow-unpin.pinned.stderr | 24 ++++++++--------- .../pin-ergonomics/borrow-unpin.unpin.stderr | 6 ++--- tests/ui/pin-macro/pin_move.stderr | 4 +-- .../non_copy_move_out_of_tuple.stderr | 2 +- .../suggestions/option-content-move3.stderr | 4 +-- .../union-borrow-move-parent-sibling.stderr | 2 +- tests/ui/union/union-move.stderr | 4 +-- tests/ui/variance/variance-issue-20533.stderr | 8 +++--- 46 files changed, 122 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 72a35de73f32..a39300f7030f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1293,18 +1293,23 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } }, ); - span.push_span_label( - ty_span, - format!( - "consider {}implementing `Clone` for this type", - if derive_clone { "manually " } else { "" } - ), - ); + let msg = if !derive_clone { + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); + format!("if `{ty}` implemented `Clone`, you could clone the value") + } else { + format!("if all bounds were met, you could clone the value") + }; span.push_span_label(expr.span, "you could clone this value"); - err.span_help( - span, - format!("if `{ty}` implemented `Clone`, you could clone the value"), - ); + err.span_note(span, msg); + if derive_clone { + err.help("consider manually implementing `Clone` to avoid undesired bounds"); + } } else if let ty::Param(param) = ty.kind() && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() && let generics = self.infcx.tcx.generics_of(self.mir_def_id()) diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index 595aefc9a215..8d40e6905e07 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -8,7 +8,7 @@ LL | drop(t); LL | drop(t); | ^ value used here after move | -help: if `S<()>` implemented `Clone`, you could clone the value +note: if `S<()>` implemented `Clone`, you could clone the value --> $DIR/issue-25700.rs:1:1 | LL | struct S(#[allow(dead_code)] Option<&'static T>); diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index a4d239090830..3fe1431fda71 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -9,7 +9,7 @@ LL | LL | x.hello(); | - variable moved due to use in coroutine | -help: if `Ty` implemented `Clone`, you could clone the value +note: if `Ty` implemented `Clone`, you could clone the value --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr index c516597c81f9..d443dc9d4831 100644 --- a/tests/ui/async-await/async-closures/move-out-of-ref.stderr +++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr @@ -7,7 +7,7 @@ LL | let c = async || { LL | *x; | ^^ `*x` is moved here | -help: if `Ty` implemented `Clone`, you could clone the value +note: if `Ty` implemented `Clone`, you could clone the value --> $DIR/move-out-of-ref.rs:5:1 | LL | struct Ty; diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index 9eb90e169fd3..b4b60d40d914 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-out-of-static-item.rs:3:1 | LL | struct Foo { diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index 8dcb81273f89..b5dc01f180b2 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -10,7 +10,7 @@ LL | let S { x: ax } = a; LL | f(pb); | -- borrow later used here | -help: if `S` implemented `Clone`, you could clone the value +note: if `S` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-subcomponent.rs:6:1 | LL | struct S { diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index c838c6512bc4..c3b7b0b6080c 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -30,7 +30,7 @@ LL | s(" world".to_string()); LL | s(" world".to_string()); | ^ value used here after move | -help: if `SFnOnce` implemented `Clone`, you could clone the value +note: if `SFnOnce` implemented `Clone`, you could clone the value --> $DIR/borrowck-overloaded-call.rs:41:1 | LL | struct SFnOnce { diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index 535550409dd8..72580e7464b7 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -59,7 +59,7 @@ LL | LL | println!("{b:?}"); | - borrow later used here | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 | LL | struct A; diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs index 12fd2129331b..cd92ac1e9e59 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.rs +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -2,11 +2,10 @@ use std::marker::PhantomData; -#[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters +#[derive(Clone, Copy)] //~ NOTE: derived `Clone` adds implicit bounds on type parameters pub struct TypedAddress{ -//~^ HELP if `TypedAddress` implemented `Clone`, you could clone the value -//~| NOTE consider manually implementing `Clone` for this type -//~| NOTE introduces an implicit `T: Clone` bound +//~^ NOTE: if all bounds were met, you could clone the value +//~| NOTE: introduces an implicit `T: Clone` bound inner: u64, phantom: PhantomData, } @@ -14,18 +13,19 @@ pub struct TypedAddress{ pub trait Memory { fn write_value(&self, offset: TypedAddress, value: &T); fn return_value(&self, offset: TypedAddress) -> T; - //~^ NOTE consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary - //~| NOTE in this method - //~| NOTE this parameter takes ownership of the value + //~^ NOTE: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + //~| NOTE: in this method + //~| NOTE: this parameter takes ownership of the value fn update_value(&self, offset: TypedAddress, update: F) - //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait - where F: FnOnce(T) -> T //~ HELP consider further restricting type parameter `T` + //~^ NOTE: move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait + where F: FnOnce(T) -> T //~ HELP: consider further restricting type parameter `T` { - let old = self.return_value(offset); //~ NOTE value moved here - //~^ NOTE you could clone this value + let old = self.return_value(offset); //~ NOTE: value moved here + //~^ NOTE: you could clone this value let new = update(old); - self.write_value(offset, &new); //~ ERROR use of moved value: `offset` - //~^ NOTE value used here after move + self.write_value(offset, &new); //~ ERROR: use of moved value: `offset` + //~^ NOTE: value used here after move + //~| HELP: consider manually implementing `Clone` to avoid undesired bounds } } diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr index 31a55b448eb6..246fd1eaf075 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.stderr +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `offset` - --> $DIR/derive-clone-implicit-bound.rs:27:26 + --> $DIR/derive-clone-implicit-bound.rs:26:26 | LL | fn update_value(&self, offset: TypedAddress, update: F) | ------ move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait @@ -11,23 +11,23 @@ LL | self.write_value(offset, &new); | ^^^^^^ value used here after move | note: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary - --> $DIR/derive-clone-implicit-bound.rs:16:39 + --> $DIR/derive-clone-implicit-bound.rs:15:39 | LL | fn return_value(&self, offset: TypedAddress) -> T; | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value -help: if `TypedAddress` implemented `Clone`, you could clone the value +note: if all bounds were met, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] | ----- derived `Clone` adds implicit bounds on type parameters LL | pub struct TypedAddress{ | ^^^^^^^^^^^^^^^^^^^^^^^^-^ - | | | - | | introduces an implicit `T: Clone` bound - | consider manually implementing `Clone` for this type + | | + | introduces an implicit `T: Clone` bound ... LL | let old = self.return_value(offset); | ------ you could clone this value + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `T` with trait `Copy` | LL | where F: FnOnce(T) -> T, T: Copy diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index 85769e187691..bd6c1c44bfb3 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -18,7 +18,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { | ^^^^^^^^^^^ -help: if `StructB` implemented `Clone`, you could clone the value +note: if `StructB` implemented `Clone`, you could clone the value --> $DIR/issue-103624.rs:23:1 | LL | self.b; diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr index a5a218a0641d..dde17d1f6523 100644 --- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -11,7 +11,7 @@ note: `Example::::change` takes ownership of the receiver `self`, | LL | unsafe fn change(self) -> Example { | ^^^^ -help: if `Example` implemented `Clone`, you could clone the value +note: if `Example` implemented `Clone`, you could clone the value --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1 | LL | struct Example(PhantomData<(fn(E), fn(FakeParam))>); diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index 959b1d1a3b84..057ac6d7e3df 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `FOO` LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 5336352e0dbd..5fda92634d8f 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a mutable reference LL | let a = unsafe { *mut_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -24,7 +24,7 @@ error[E0507]: cannot move out of a shared reference LL | let b = unsafe { *imm_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -44,7 +44,7 @@ error[E0507]: cannot move out of a raw pointer LL | let c = unsafe { *mut_ptr() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -59,7 +59,7 @@ error[E0507]: cannot move out of a raw pointer LL | let d = unsafe { *const_ptr() }; | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index f2bc6bd4760a..1e9b1d5209cb 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -7,7 +7,7 @@ LL | &([S][0],); | cannot move out of here | move occurs because value has type `S`, which does not implement the `Copy` trait | -help: if `S` implemented `Clone`, you could clone the value +note: if `S` implemented `Clone`, you could clone the value --> $DIR/move-error-in-promoted-2.rs:3:1 | LL | struct S; diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 3796b7e05fb4..97d140515184 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -9,7 +9,7 @@ LL | let a = $c; LL | sss!(); | ------ in this macro invocation | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 | LL | struct A; diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr index af5cbdcf150f..009e85a8031e 100644 --- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | static Y: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); @@ -19,7 +19,7 @@ error[E0507]: cannot move out of a shared reference LL | const Z: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index f0d6dd3d4692..bdaa9449f913 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -12,7 +12,7 @@ LL | LL | use_value(*theref) | ------- borrow later used here | -help: if `Alloc` implemented `Clone`, you could clone the value +note: if `Alloc` implemented `Clone`, you could clone the value --> $DIR/leak-alloc.rs:8:1 | LL | struct Alloc {} diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs index b55c8c16f611..863bcedd01e6 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs @@ -1,16 +1,16 @@ //! regression test for -struct NoCopy; //~ HELP if `NoCopy` implemented `Clone`, you could clone the value -//~^ NOTE consider implementing `Clone` for this type +struct NoCopy; //~ NOTE: if `NoCopy` implemented `Clone`, you could clone the value +//~^ NOTE: consider implementing `Clone` for this type fn main() { let x = NoCopy; - //~^ NOTE move occurs because `x` has type `NoCopy` + //~^ NOTE: move occurs because `x` has type `NoCopy` let f = move || { - //~^ NOTE value moved into closure here + //~^ NOTE: value moved into closure here let y = x; - //~^ NOTE variable moved due to use in closure - //~| NOTE you could clone this value + //~^ NOTE: variable moved due to use in closure + //~| NOTE: you could clone this value }; let z = x; - //~^ ERROR use of moved value: `x` - //~| NOTE value used here after move + //~^ ERROR: use of moved value: `x` + //~| NOTE: value used here after move } diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr index bde39ca6ca71..94f80da1b10a 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr @@ -13,7 +13,7 @@ LL | let y = x; LL | let z = x; | ^ value used here after move | -help: if `NoCopy` implemented `Clone`, you could clone the value +note: if `NoCopy` implemented `Clone`, you could clone the value --> $DIR/closure-move-use-after-move-diagnostic.rs:2:1 | LL | struct NoCopy; diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr index 561b3b331d9f..2b21f6c59f0b 100644 --- a/tests/ui/coroutine/moved-twice.stderr +++ b/tests/ui/coroutine/moved-twice.stderr @@ -10,7 +10,7 @@ LL | yield; LL | let second = first; | ^^^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/moved-twice.rs:9:1 | LL | struct Foo([u8; FOO_SIZE]); diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 7c716fb9dd4c..9cfc4abdc0cb 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -7,7 +7,7 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because value has type `Y`, which does not implement the `Copy` trait | -help: if `Y` implemented `Clone`, you could clone the value +note: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 | LL | struct Y(usize); diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index 528f311765df..c4cbc834ad98 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -14,7 +14,7 @@ LL | println!("child function: {}", fancy_num.num); LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here | -help: if `FancyNum` implemented `Clone`, you could clone the value +note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0504.rs:2:1 | LL | struct FancyNum { diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index ac0f390bc54b..3f2913e9fe3c 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -11,7 +11,7 @@ LL | eat(x); LL | _ref_to_val.use_ref(); | ----------- borrow later used here | -help: if `Value` implemented `Clone`, you could clone the value +note: if `Value` implemented `Clone`, you could clone the value --> $DIR/E0505.rs:1:1 | LL | struct Value {} diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index ac03e5ea9cd5..70d99ea2cce5 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -11,7 +11,7 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w | LL | fn nothing_is_true(self) {} | ^^^^ -help: if `TheDarkKnight` implemented `Clone`, you could clone the value +note: if `TheDarkKnight` implemented `Clone`, you could clone the value --> $DIR/E0507.rs:3:1 | LL | struct TheDarkKnight; diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index 48ede17dc26a..fcfac399e0df 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508-fail.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index c001b9461ebf..b9fa0f4d17a5 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index 89c3a5848423..628a253e0859 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -7,7 +7,7 @@ LL | let fancy_field = drop_struct.fancy; | cannot move out of here | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait | -help: if `FancyNum` implemented `Clone`, you could clone the value +note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0509.rs:1:1 | LL | struct FancyNum { diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 7aafe081deaf..162d7ac031a6 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference LL | array[*inbounds as usize] | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait | -help: if `Enum` implemented `Clone`, you could clone the value +note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-102389.rs:1:1 | LL | enum Enum { A, B, C } diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 965a4206253e..f115656d7c0d 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -3,10 +3,10 @@ // 'value moved in previous iteration of loop' message struct NonCopy; -//~^ HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` +//~^ NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 1c54d3997ed6..8bde3b5c042d 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -10,7 +10,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -33,7 +33,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -53,7 +53,7 @@ LL | loop { LL | let _used = value; | ^^^^^ value moved here, in previous iteration of loop | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -73,7 +73,7 @@ LL | loop { LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index 3fc50c48315d..815e91b0f4df 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -11,7 +11,7 @@ LL | &mut a; LL | a; | - use occurs due to use in closure | -help: if `NotCopy` implemented `Clone`, you could clone the value +note: if `NotCopy` implemented `Clone`, you could clone the value --> $DIR/issue-75904-move-closure-loop.rs:5:1 | LL | struct NotCopy; diff --git a/tests/ui/moves/matching-partially-moved-value-17385.stderr b/tests/ui/moves/matching-partially-moved-value-17385.stderr index 83f4f4320485..906f7868bccb 100644 --- a/tests/ui/moves/matching-partially-moved-value-17385.stderr +++ b/tests/ui/moves/matching-partially-moved-value-17385.stderr @@ -8,7 +8,7 @@ LL | drop(foo); LL | match foo { | ^^^^^^^^^ value used here after move | -help: if `X` implemented `Clone`, you could clone the value +note: if `X` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:2:1 | LL | struct X(isize); @@ -27,7 +27,7 @@ LL | drop(e); LL | match e { | ^ value used here after move | -help: if `Enum` implemented `Clone`, you could clone the value +note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:4:1 | LL | enum Enum { diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index b3a1215fa2f7..de19a99d388c 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -132,7 +132,7 @@ LL | foo_add + Foo; LL | foo_add; | ^^^^^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 7ef859200b21..8a030f021920 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -7,7 +7,7 @@ LL | a[i] | cannot move out of here | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait | -help: if `D` implemented `Clone`, you could clone the value +note: if `D` implemented `Clone`, you could clone the value --> $DIR/move-out-of-array-1.rs:5:1 | LL | struct D { _x: u8 } diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.stderr b/tests/ui/moves/moved-value-on-as-ref-arg.stderr index b553938c6fed..a99bdb4fe9d4 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.stderr +++ b/tests/ui/moves/moved-value-on-as-ref-arg.stderr @@ -23,7 +23,7 @@ LL | qux(bar); LL | let _baa = bar; | ^^^ value used here after move | -help: if `Bar` implemented `Clone`, you could clone the value +note: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; @@ -61,7 +61,7 @@ LL | baz(bar); LL | let _baa = bar; | ^^^ value used here after move | -help: if `Bar` implemented `Clone`, you could clone the value +note: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr index 84c543921687..496a298a36ce 100644 --- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -28,7 +28,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move | -help: if `S>` implemented `Clone`, you could clone the value +note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { @@ -82,7 +82,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move | -help: if `S>` implemented `Clone`, you could clone the value +note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index e84f75455217..bcb2ab84a239 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | let b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -27,7 +27,7 @@ LL | let b = a[0]; | cannot move out of here | move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -46,7 +46,7 @@ error[E0507]: cannot move out of `**r` which is behind a shared reference LL | let s = **r; | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -66,7 +66,7 @@ error[E0507]: cannot move out of an `Rc` LL | let s = *r; | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -89,7 +89,7 @@ LL | let a = [A("".to_string())][0]; | cannot move out of here | move occurs because value has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -137,7 +137,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr index f9bef8d83f96..cc438461a5d1 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -8,7 +8,7 @@ LL | foo_pin_mut(&pin mut foo); LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -27,7 +27,7 @@ LL | let x = &pin mut foo; LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -46,7 +46,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -65,7 +65,7 @@ LL | let x = &pin mut foo; // ok LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -87,7 +87,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -106,7 +106,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -125,7 +125,7 @@ LL | let x = &pin mut foo; // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -144,7 +144,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -163,7 +163,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -185,7 +185,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -204,7 +204,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -223,7 +223,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr index 523191655813..bf9921343ee7 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -33,7 +33,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -55,7 +55,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -77,7 +77,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr index cf7d50091ba4..3f4660209885 100644 --- a/tests/ui/pin-macro/pin_move.stderr +++ b/tests/ui/pin-macro/pin_move.stderr @@ -8,7 +8,7 @@ LL | pin!(pointee); LL | let _moved = pointee; | ^^^^^^^ value used here after move | -help: if `a::NotCopy` implemented `Clone`, you could clone the value +note: if `a::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:7:5 | LL | struct NotCopy(T); @@ -23,7 +23,7 @@ error[E0507]: cannot move out of a mutable reference LL | pin!(*&mut pointee); | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait | -help: if `b::NotCopy` implemented `Clone`, you could clone the value +note: if `b::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:16:5 | LL | struct NotCopy(T); diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr index 5e447a57bfee..62f24324fcc1 100644 --- a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -7,7 +7,7 @@ LL | (b,) = *tuple; | data moved here | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/non_copy_move_out_of_tuple.rs:3:1 | LL | struct NonCopy; diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index cd13592d652e..f78d3cf67862 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -10,7 +10,7 @@ LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once -help: if `NotCopyable` implemented `Clone`, you could clone the value +note: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; @@ -43,7 +43,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | fn func H, H: FnMut()>(_: F) {} | ^^^^^^^^^^^^ -help: if `NotCopyable` implemented `Clone`, you could clone the value +note: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr index 5974441dd807..461ee407e2dd 100644 --- a/tests/ui/union/union-borrow-move-parent-sibling.stderr +++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr @@ -59,7 +59,7 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, Moc LL | let a = (u.x.0).0; | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait | -help: if `MockVec` implemented `Clone`, you could clone the value +note: if `MockVec` implemented `Clone`, you could clone the value --> $DIR/union-borrow-move-parent-sibling.rs:25:1 | LL | struct MockVec { diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr index 6266bb4770e0..d520fb00ea9d 100644 --- a/tests/ui/union/union-move.stderr +++ b/tests/ui/union/union-move.stderr @@ -16,7 +16,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -help: if `U1` implemented `Clone`, you could clone the value +note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { @@ -43,7 +43,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -help: if `U1` implemented `Clone`, you could clone the value +note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr index 2a33a88bdd56..21d8de6ae881 100644 --- a/tests/ui/variance/variance-issue-20533.stderr +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -10,7 +10,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -31,7 +31,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -52,7 +52,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -73,7 +73,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); From c95210f013cd0e607b4932cc841f90096037f191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Feb 2026 18:30:08 +0000 Subject: [PATCH 16/17] Do not suggest manual `impl Copy` --- .../src/error_reporting/traits/suggestions.rs | 2 +- tests/ui/associated-types/issue-38821.stderr | 1 - tests/ui/consts/const-blocks/trait-error.stderr | 1 - tests/ui/derives/deriving-copyclone.stderr | 2 -- tests/ui/generic-associated-types/impl_bounds.stderr | 2 -- 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 1880465eff54..764790a75bb4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3629,7 +3629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); - if derived { + if derived && trait_name != "Copy" { err.help(format!( "consider manually implementing `{trait_name}` to avoid undesired \ bounds", diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index fae388c98d36..07b146f8bfca 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -159,7 +159,6 @@ LL | pub enum ColumnInsertValue where ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound - = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 853e10e0b35a..308d71f0f4bd 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -11,7 +11,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo(T); | ^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block | diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 40f96919121f..20a73ffdcfbf 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -13,7 +13,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { | ^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | @@ -65,7 +64,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { | ^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 63c4ba900829..65e1dff479e5 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -35,7 +35,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 | @@ -62,7 +61,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | From 675656188786ebb1444b5ea7baece40d8afa51ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Feb 2026 18:31:21 +0000 Subject: [PATCH 17/17] fix test after rebase --- .../derive-clone-already-present-issue-146515.rs | 5 ++--- .../derive-clone-already-present-issue-146515.stderr | 11 ++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs index 083d73711a51..78b4c017251e 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs @@ -2,8 +2,8 @@ use std::rc::Rc; -#[derive(Clone)] -struct ContainsRc { +#[derive(Clone)] //~ NOTE in this expansion +struct ContainsRc { //~ NOTE derive introduces an implicit `T: Clone` bound value: Rc, } @@ -14,7 +14,6 @@ fn clone_me(x: &ContainsRc) -> ContainsRc { //~| NOTE expected `ContainsRc`, found `&ContainsRc` //~| NOTE expected struct `ContainsRc<_>` //~| NOTE `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead - //~| NOTE the trait `Clone` must be implemented } fn main() {} diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr index 516ef38f668d..6ecf4e7ca943 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr @@ -14,9 +14,14 @@ note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned | LL | x.clone() | ^ - = help: `Clone` is not implemented because the trait bound `T: Clone` is not satisfied -note: the trait `Clone` must be implemented - --> $SRC_DIR/core/src/clone.rs:LL:COL +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-clone-already-present-issue-146515.rs:6:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error: aborting due to 1 previous error