Skip to content

Commit 661b0e5

Browse files
authored
Rollup merge of #95525 - ohno418:suggest-derivable-trait-E0277, r=compiler-errors
Suggest derivable trait on E0277 error Closes #95099 .
2 parents 634770c + b831b60 commit 661b0e5

File tree

61 files changed

+340
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+340
-0
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
540540
);
541541
self.note_version_mismatch(&mut err, &trait_ref);
542542
self.suggest_remove_await(&obligation, &mut err);
543+
self.suggest_derive(&obligation, &mut err, trait_predicate);
543544

544545
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
545546
self.suggest_await_before_try(

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+69
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,13 @@ pub trait InferCtxtExt<'tcx> {
189189
err: &mut Diagnostic,
190190
trait_ref: &ty::PolyTraitRef<'tcx>,
191191
);
192+
193+
fn suggest_derive(
194+
&self,
195+
obligation: &PredicateObligation<'tcx>,
196+
err: &mut Diagnostic,
197+
trait_pred: ty::PolyTraitPredicate<'tcx>,
198+
);
192199
}
193200

194201
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
@@ -2651,6 +2658,68 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
26512658
_ => {}
26522659
}
26532660
}
2661+
2662+
fn suggest_derive(
2663+
&self,
2664+
obligation: &PredicateObligation<'tcx>,
2665+
err: &mut Diagnostic,
2666+
trait_pred: ty::PolyTraitPredicate<'tcx>,
2667+
) {
2668+
let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
2669+
return;
2670+
};
2671+
let (adt, substs) = match trait_pred.skip_binder().self_ty().kind() {
2672+
ty::Adt(adt, substs) if adt.did().is_local() => (adt, substs),
2673+
_ => return,
2674+
};
2675+
let can_derive = {
2676+
let is_derivable_trait = match diagnostic_name {
2677+
sym::Default => !adt.is_enum(),
2678+
sym::PartialEq | sym::PartialOrd => {
2679+
let rhs_ty = trait_pred.skip_binder().trait_ref.substs.type_at(1);
2680+
trait_pred.skip_binder().self_ty() == rhs_ty
2681+
}
2682+
sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
2683+
_ => false,
2684+
};
2685+
is_derivable_trait &&
2686+
// Ensure all fields impl the trait.
2687+
adt.all_fields().all(|field| {
2688+
let field_ty = field.ty(self.tcx, substs);
2689+
let trait_substs = match diagnostic_name {
2690+
sym::PartialEq | sym::PartialOrd => {
2691+
self.tcx.mk_substs_trait(field_ty, &[field_ty.into()])
2692+
}
2693+
_ => self.tcx.mk_substs_trait(field_ty, &[]),
2694+
};
2695+
let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
2696+
trait_ref: ty::TraitRef {
2697+
substs: trait_substs,
2698+
..trait_pred.skip_binder().trait_ref
2699+
},
2700+
..*tr
2701+
});
2702+
let field_obl = Obligation::new(
2703+
obligation.cause.clone(),
2704+
obligation.param_env,
2705+
trait_pred.to_predicate(self.tcx),
2706+
);
2707+
self.predicate_must_hold_modulo_regions(&field_obl)
2708+
})
2709+
};
2710+
if can_derive {
2711+
err.span_suggestion_verbose(
2712+
self.tcx.def_span(adt.did()).shrink_to_lo(),
2713+
&format!(
2714+
"consider annotating `{}` with `#[derive({})]`",
2715+
trait_pred.skip_binder().self_ty(),
2716+
diagnostic_name.to_string(),
2717+
),
2718+
format!("#[derive({})]\n", diagnostic_name.to_string()),
2719+
Applicability::MaybeIncorrect,
2720+
);
2721+
}
2722+
}
26542723
}
26552724

26562725
/// Collect all the returned expressions within the input expression.

src/test/ui/array-slice-vec/repeat_empty_ok.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | let headers = [Header{value: &[]}; 128];
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>`
66
|
77
= note: the `Copy` trait is required because the repeated element will be copied
8+
help: consider annotating `Header<'_>` with `#[derive(Copy)]`
9+
|
10+
LL | #[derive(Copy)]
11+
|
812

913
error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied
1014
--> $DIR/repeat_empty_ok.rs:13:19
@@ -13,6 +17,10 @@ LL | let headers = [Header{value: &[0]}; 128];
1317
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>`
1418
|
1519
= note: the `Copy` trait is required because the repeated element will be copied
20+
help: consider annotating `Header<'_>` with `#[derive(Copy)]`
21+
|
22+
LL | #[derive(Copy)]
23+
|
1624

1725
error: aborting due to 2 previous errors
1826

src/test/ui/associated-types/defaults-suitability.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ note: required by a bound in `Tr::Ty`
99
|
1010
LL | type Ty: Clone = NotClone;
1111
| ^^^^^ required by this bound in `Tr::Ty`
12+
help: consider annotating `NotClone` with `#[derive(Clone)]`
13+
|
14+
LL | #[derive(Clone)]
15+
|
1216

1317
error[E0277]: the trait bound `NotClone: Clone` is not satisfied
1418
--> $DIR/defaults-suitability.rs:22:15
@@ -24,6 +28,10 @@ LL | Self::Ty: Clone,
2428
LL | {
2529
LL | type Ty = NotClone;
2630
| -- required by a bound in this
31+
help: consider annotating `NotClone` with `#[derive(Clone)]`
32+
|
33+
LL | #[derive(Clone)]
34+
|
2735

2836
error[E0277]: the trait bound `T: Clone` is not satisfied
2937
--> $DIR/defaults-suitability.rs:28:23

src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | x: Error
88
| ^^^^^^^^ the trait `Clone` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Clone)]`
12+
|
13+
LL | #[derive(Clone)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Clone-enum.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | Error
88
| ^^^^^ the trait `Clone` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Clone)]`
12+
|
13+
LL | #[derive(Clone)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Clone-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | x: Error
88
| ^^^^^^^^ the trait `Clone` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Clone)]`
12+
|
13+
LL | #[derive(Clone)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Clone-tuple-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | Error
88
| ^^^^^ the trait `Clone` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Clone)]`
12+
|
13+
LL | #[derive(Clone)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ LL | x: Error
1010
= help: the trait `Debug` is not implemented for `Error`
1111
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1212
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
13+
help: consider annotating `Error` with `#[derive(Debug)]`
14+
|
15+
LL | #[derive(Debug)]
16+
|
1317

1418
error: aborting due to previous error
1519

src/test/ui/derives/derives-span-Debug-enum.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ LL | Error
1010
= help: the trait `Debug` is not implemented for `Error`
1111
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1212
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
13+
help: consider annotating `Error` with `#[derive(Debug)]`
14+
|
15+
LL | #[derive(Debug)]
16+
|
1317

1418
error: aborting due to previous error
1519

src/test/ui/derives/derives-span-Debug-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ LL | x: Error
1010
= help: the trait `Debug` is not implemented for `Error`
1111
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1212
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
13+
help: consider annotating `Error` with `#[derive(Debug)]`
14+
|
15+
LL | #[derive(Debug)]
16+
|
1317

1418
error: aborting due to previous error
1519

src/test/ui/derives/derives-span-Debug-tuple-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ LL | Error
1010
= help: the trait `Debug` is not implemented for `Error`
1111
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1212
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
13+
help: consider annotating `Error` with `#[derive(Debug)]`
14+
|
15+
LL | #[derive(Debug)]
16+
|
1317

1418
error: aborting due to previous error
1519

src/test/ui/derives/derives-span-Default-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | x: Error
88
| ^^^^^^^^ the trait `Default` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Default)]`
12+
|
13+
LL | #[derive(Default)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Default-tuple-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | Error
88
| ^^^^^ the trait `Default` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Default)]`
12+
|
13+
LL | #[derive(Default)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ note: required by a bound in `AssertParamIsEq`
1313
LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
1414
| ^^ required by this bound in `AssertParamIsEq`
1515
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
help: consider annotating `Error` with `#[derive(Eq)]`
17+
|
18+
LL | #[derive(Eq)]
19+
|
1620

1721
error: aborting due to previous error
1822

src/test/ui/derives/derives-span-Eq-enum.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ note: required by a bound in `AssertParamIsEq`
1313
LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
1414
| ^^ required by this bound in `AssertParamIsEq`
1515
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
help: consider annotating `Error` with `#[derive(Eq)]`
17+
|
18+
LL | #[derive(Eq)]
19+
|
1620

1721
error: aborting due to previous error
1822

src/test/ui/derives/derives-span-Eq-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ note: required by a bound in `AssertParamIsEq`
1313
LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
1414
| ^^ required by this bound in `AssertParamIsEq`
1515
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
help: consider annotating `Error` with `#[derive(Eq)]`
17+
|
18+
LL | #[derive(Eq)]
19+
|
1620

1721
error: aborting due to previous error
1822

src/test/ui/derives/derives-span-Eq-tuple-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ note: required by a bound in `AssertParamIsEq`
1313
LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
1414
| ^^ required by this bound in `AssertParamIsEq`
1515
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
help: consider annotating `Error` with `#[derive(Eq)]`
17+
|
18+
LL | #[derive(Eq)]
19+
|
1620

1721
error: aborting due to previous error
1822

src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | x: Error
88
| ^^^^^^^^ the trait `Hash` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Hash)]`
12+
|
13+
LL | #[derive(Hash)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Hash-enum.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | Error
88
| ^^^^^ the trait `Hash` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Hash)]`
12+
|
13+
LL | #[derive(Hash)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Hash-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | x: Error
88
| ^^^^^^^^ the trait `Hash` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Hash)]`
12+
|
13+
LL | #[derive(Hash)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Hash-tuple-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | Error
88
| ^^^^^ the trait `Hash` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Hash)]`
12+
|
13+
LL | #[derive(Hash)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | x: Error
88
| ^^^^^^^^ the trait `Ord` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Ord)]`
12+
|
13+
LL | #[derive(Ord)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Ord-enum.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | Error
88
| ^^^^^ the trait `Ord` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Ord)]`
12+
|
13+
LL | #[derive(Ord)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Ord-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | x: Error
88
| ^^^^^^^^ the trait `Ord` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Ord)]`
12+
|
13+
LL | #[derive(Ord)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-Ord-tuple-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | Error
88
| ^^^^^ the trait `Ord` is not implemented for `Error`
99
|
1010
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider annotating `Error` with `#[derive(Ord)]`
12+
|
13+
LL | #[derive(Ord)]
14+
|
1115

1216
error: aborting due to previous error
1317

src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ LL | x: Error
99
|
1010
= help: the trait `PartialOrd` is not implemented for `Error`
1111
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
12+
help: consider annotating `Error` with `#[derive(PartialOrd)]`
13+
|
14+
LL | #[derive(PartialOrd)]
15+
|
1216

1317
error: aborting due to previous error
1418

src/test/ui/derives/derives-span-PartialOrd-enum.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ LL | Error
99
|
1010
= help: the trait `PartialOrd` is not implemented for `Error`
1111
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
12+
help: consider annotating `Error` with `#[derive(PartialOrd)]`
13+
|
14+
LL | #[derive(PartialOrd)]
15+
|
1216

1317
error: aborting due to previous error
1418

0 commit comments

Comments
 (0)