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 caf6a86af098a..692ce240e36f8 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 0000000000000..a20e04d3afdce --- /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 0000000000000..b10e3a92c96b0 --- /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 c2260a4590975..665e0ddab1949 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 4c1bcffa1cf4c..b117fa8327296 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 279c34cb275d9..b3b06314e1a0f 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 d54f3812350d9..94876c6dd89f2 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 01329f69c3bef..3c5f67fee26a9 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 aecd97ef7763c..ea411741536f5 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 601d067e3d849..1e66daa7132d8 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 befff8802804e..f4cd4cff7f444 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 7847bbd813cd5..d6a794fa0b19e 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 b7aed4a8485a8..93fd2df0398e4 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 a48dd30d008a6..2b8c6baeeafe2 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 645d6ebb3961f..2bd56b7688f40 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 0000000000000..22fb68f37c5c4 --- /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 0000000000000..9805835bb07f5 --- /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 94876c6dd89f2..c9dc390ea0be8 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 3c5f67fee26a9..11d0c9d514ff5 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 ea411741536f5..1aaa7591a7bed 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 1e66daa7132d8..991a48917efb8 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 f4cd4cff7f444..1baacf85f6a21 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 d6a794fa0b19e..fd7dd774cf087 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 93fd2df0398e4..c3513e19981fd 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 2b8c6baeeafe2..800f07054af73 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 2bd56b7688f40..3f889f31484b5 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 9805835bb07f5..275cef7a94fd5 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 cd25b866b0983..f5ef5adff6bd1 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 13ba80243a5eb..e239ad4ef2091 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 b62c67d9a9da1..fff6269472bd3 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 18f862aaa7d6e..65488629b629b 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 3e4c194147f9f..285288e87ee00 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 301f3c3a458de..5de99cc6ca6ae 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 301f3c3a458de..5de99cc6ca6ae 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 0000000000000..a4c9e88ef5765 --- /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 0000000000000..0cec4ef7c6096 --- /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 | 4 +- 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 | 24 +++++----- 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, 347 insertions(+), 263 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 665e0ddab1949..bc86cdbc9f7ef 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 5212bc886f0df..35c371235e640 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 +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 -pub enum ColumnInsertValue where -//~^ 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 11d0c9d514ff5..58d06860fe301 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 0614ea97b1add..1900931b3f35e 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 fd1836802c4ae..084c64d273355 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 a1c8eccfb095f..a8f190609c043 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 ca2a693d48ceb..1219d5f04380a 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 d42ef90e1b180..e8a16be2197b2 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 442ec6b96cefa..6c8a506d1f40a 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 5db031cb900fc..f2d972612dc64 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 134dbba0d63ab..2538b811618bb 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 500e8e22b0e3d..71ac662cf580e 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 1aaa7591a7bed..f90f0b45d967a 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 991a48917efb8..aa9177d2b017b 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 5147605910d7b..64cd5bf594b01 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 771bbc9256958..f17d33ffbfedc 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 1baacf85f6a21..2261634744822 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 27691f5718849..c033a3d227c12 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 8e5cd4248f149..f4193f18352d0 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 cf9c0d0ad3bee..0d6aaaf5186d3 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 f3bf299aa65f4..e946c0c5350ed 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 32c3cf4403169..e80cf35d81e1d 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 @@ -32,25 +32,25 @@ note: struct defined here, with 0 generic parameters | 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 +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: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 @@ -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 0c448e4ad8bcf..64cc1f0d15382 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 1a7df9ac095ad..98b5305ad0dcd 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 fd7dd774cf087..d918bd62c2d72 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 53ca2bc973ff8..9966c24a7441e 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 7cde901ffd95a..3b4ad58b1f080 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 77fa2f566a8fc..f9dc98d9d270f 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 02036e8d4c90b..a5d7c3a4f8aaa 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 d420f2641daf5..0c66b47b39418 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 c3513e19981fd..e49cf6256cb26 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 234d7a64dc8b0..7dd91243082c5 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 2001c85c4348a..f38539cc648c0 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 2d597cce5ad56..79ba1842f62f5 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 71210379c79cd..1f3768ad8d84b 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 bce106bbfe79b..72c6cecc88d69 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 a58022ef7e4fd..53fe2fed0a616 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 8793a05c8a85a..841bd5e32b8a1 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 fe375b94781b5..a0b51be178634 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 4dc362f947875..17259dd687c6c 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 b3635000f1658..3e4331745be87 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 eb0355853daac..bed5ff90c1949 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 800f07054af73..872ce7105ce8c 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 74df1d7c7cfdd..bd1785e351123 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 8550a4d724761..36502044bd467 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 e3375b67c86dd..cc80e7297e48a 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 0ffc1b8f7a25e..60a9074e5c0d9 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 3f889f31484b5..f843fb0d6d7ea 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 275cef7a94fd5..02c7fe9e689e6 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 d45668312218b..6b04004621d82 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 815787c3bfecb..ebb22cb9cd745 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 ccd35a850f2d7..2f62906e9df3d 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 32c8b2cf3ac1f..1fb5e8b007830 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 2b4f7ba9fa29e..ceef87d76abb6 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 290b1df1665d3..912286a48fafe 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 29f29761b6055..57defac577d8a 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 ebb22cb9cd745..57661fda73079 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 c9dc390ea0be8..70a16b23d2764 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 58d06860fe301..fae388c98d36f 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 f90f0b45d967a..fc681e655e1a6 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 aa9177d2b017b..60402a4123626 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 2261634744822..f8d2859f211ed 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 d918bd62c2d72..f656756865329 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 e49cf6256cb26..d14f9eae69502 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 872ce7105ce8c..791e2d19f2f96 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 f843fb0d6d7ea..55d6391f975e6 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 02c7fe9e689e6..ee78cba5af27c 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 d9f8eba65c4a2..611aa070124a4 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 61562cc1e4f30..558d2ec84e4bd 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 2a77d0b997e2c..b90ccc6716d04 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 f33196bab6470..2fd3a6e738cfe 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 f17d33ffbfedc..ab2d086c7f5fc 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 98b5305ad0dcd..13294959bc3cf 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 285288e87ee00..349b2c756b644 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 0cec4ef7c6096..2fb039f965288 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 349b2c756b644..b8f99bbd7e17a 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 70a16b23d2764..1880465eff54c 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 fc681e655e1a6..f520413927c36 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 60402a4123626..853e10e0b35a3 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 f8d2859f211ed..40f96919121f4 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 f656756865329..63c4ba9008291 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 d14f9eae69502..b53ebe9f72718 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 ee78cba5af27c..fe2bc77b9529c 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 692ce240e36f8..72a35de73f322 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 8d40e6905e07f..595aefc9a2150 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 3fe1431fda714..a4d239090830c 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 d443dc9d4831b..c516597c81f95 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 b4b60d40d9143..9eb90e169fd39 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 b5dc01f180b2f..8dcb81273f897 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 c3b7b0b6080c6..c838c6512bc42 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 72580e7464b72..535550409dd87 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 a20e04d3afdce..12fd2129331b9 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 b10e3a92c96b0..31a55b448eb6d 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 bd6c1c44bfb36..85769e187691e 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 dde17d1f6523c..a5a218a0641d0 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 057ac6d7e3df9..959b1d1a3b840 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 5fda92634d8f3..5336352e0dbde 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 1e9b1d5209cb6..f2bc6bd4760a1 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 97d140515184a..3796b7e05fb4d 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 009e85a8031ee..af5cbdcf150f3 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 bdaa9449f913e..f0d6dd3d46927 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 3326af7486c5e..b55c8c16f611c 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 94f80da1b10a4..bde39ca6ca71e 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 2b21f6c59f0bc..561b3b331d9f4 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 9cfc4abdc0cb5..7c716fb9dd4ca 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 c4cbc834ad98c..528f311765df6 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 3f2913e9fe3c6..ac0f390bc54b1 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 70d99ea2cce5c..ac03e5ea9cd5a 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 fcfac399e0df5..48ede17dc26a8 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 b9fa0f4d17a5f..c001b9461ebf3 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 628a253e08593..89c3a5848423e 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 162d7ac031a67..7aafe081deaf2 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 8f2e01bdf1aba..965a4206253e2 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 3a93769ac4549..1c54d3997ed6d 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 815e91b0f4df2..3fc50c48315d5 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 906f7868bccbf..83f4f4320485b 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 de19a99d388ca..b3a1215fa2f73 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 8a030f0219207..7ef859200b213 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 a99bdb4fe9d41..b553938c6fede 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 496a298a36ce9..84c543921687b 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 bcb2ab84a239b..e84f754552175 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 cc438461a5d15..f9bef8d83f96f 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 bf9921343ee7d..523191655813b 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 3f46602098850..cf7d50091ba45 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 62f24324fcc17..5e447a57bfee0 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 f78d3cf678629..cd13592d652e8 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 461ee407e2ddb..5974441dd807d 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 d520fb00ea9d5..6266bb4770e0e 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 21d8de6ae8815..2a33a88bdd56a 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 f5ef5adff6bd1..517d73f517833 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 e239ad4ef2091..ca968910fde43 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 fff6269472bd3..6bd3fff39790a 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 65488629b629b..62ef35b761922 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 72a35de73f322..a39300f7030f2 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 595aefc9a2150..8d40e6905e07f 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 a4d239090830c..3fe1431fda714 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 c516597c81f95..d443dc9d4831b 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 9eb90e169fd39..b4b60d40d9143 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 8dcb81273f897..b5dc01f180b2f 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 c838c6512bc42..c3b7b0b6080c6 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 535550409dd87..72580e7464b72 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 12fd2129331b9..cd92ac1e9e598 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 31a55b448eb6d..246fd1eaf0752 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 85769e187691e..bd6c1c44bfb36 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 a5a218a0641d0..dde17d1f6523c 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 959b1d1a3b840..057ac6d7e3df9 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 5336352e0dbde..5fda92634d8f3 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 f2bc6bd4760a1..1e9b1d5209cb6 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 3796b7e05fb4d..97d140515184a 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 af5cbdcf150f3..009e85a8031ee 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 f0d6dd3d46927..bdaa9449f913e 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 b55c8c16f611c..863bcedd01e6d 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 bde39ca6ca71e..94f80da1b10a4 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 561b3b331d9f4..2b21f6c59f0bc 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 7c716fb9dd4ca..9cfc4abdc0cb5 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 528f311765df6..c4cbc834ad98c 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 ac0f390bc54b1..3f2913e9fe3c6 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 ac03e5ea9cd5a..70d99ea2cce5c 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 48ede17dc26a8..fcfac399e0df5 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 c001b9461ebf3..b9fa0f4d17a5f 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 89c3a5848423e..628a253e08593 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 7aafe081deaf2..162d7ac031a67 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 965a4206253e2..f115656d7c0dd 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 1c54d3997ed6d..8bde3b5c042db 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 3fc50c48315d5..815e91b0f4df2 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 83f4f4320485b..906f7868bccbf 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 b3a1215fa2f73..de19a99d388ca 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 7ef859200b213..8a030f0219207 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 b553938c6fede..a99bdb4fe9d41 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 84c543921687b..496a298a36ce9 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 e84f754552175..bcb2ab84a239b 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 f9bef8d83f96f..cc438461a5d15 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 523191655813b..bf9921343ee7d 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 cf7d50091ba45..3f46602098850 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 5e447a57bfee0..62f24324fcc17 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 cd13592d652e8..f78d3cf678629 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 5974441dd807d..461ee407e2ddb 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 6266bb4770e0e..d520fb00ea9d5 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 2a33a88bdd56a..21d8de6ae8815 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 1880465eff54c..764790a75bb44 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 fae388c98d36f..07b146f8bfca4 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 853e10e0b35a3..308d71f0f4bd6 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 40f96919121f4..20a73ffdcfbfe 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 63c4ba9008291..65e1dff479e54 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 083d73711a517..78b4c017251ef 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 516ef38f668dc..6ecf4e7ca9439 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