Skip to content

Commit c9b0707

Browse files
committed
Make derive(Trait) suggestion more accurate
Only suggest `derive(PartialEq)` when both LHS and RHS types are the same, otherwise the suggestion is not useful.
1 parent a861c89 commit c9b0707

File tree

4 files changed

+27
-16
lines changed

4 files changed

+27
-16
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -2252,6 +2252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22522252
&self,
22532253
err: &mut Diagnostic,
22542254
errors: Vec<FulfillmentError<'tcx>>,
2255+
suggest_derive: bool,
22552256
) {
22562257
let all_local_types_needing_impls =
22572258
errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
@@ -2322,18 +2323,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23222323
.iter()
23232324
.map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
23242325
.collect();
2325-
self.suggest_derive(err, &preds);
2326+
if suggest_derive {
2327+
self.suggest_derive(err, &preds);
2328+
} else {
2329+
// The predicate comes from a binop where the lhs and rhs have different types.
2330+
let _ = self.note_predicate_source_and_get_derives(err, &preds);
2331+
}
23262332
}
23272333

2328-
pub fn suggest_derive(
2334+
fn note_predicate_source_and_get_derives(
23292335
&self,
23302336
err: &mut Diagnostic,
23312337
unsatisfied_predicates: &[(
23322338
ty::Predicate<'tcx>,
23332339
Option<ty::Predicate<'tcx>>,
23342340
Option<ObligationCause<'tcx>>,
23352341
)],
2336-
) {
2342+
) -> Vec<(String, Span, String)> {
23372343
let mut derives = Vec::<(String, Span, Symbol)>::new();
23382344
let mut traits = Vec::new();
23392345
for (pred, _, _) in unsatisfied_predicates {
@@ -2419,6 +2425,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24192425
);
24202426
}
24212427

2428+
derives_grouped
2429+
}
2430+
2431+
pub fn suggest_derive(
2432+
&self,
2433+
err: &mut Diagnostic,
2434+
unsatisfied_predicates: &[(
2435+
ty::Predicate<'tcx>,
2436+
Option<ty::Predicate<'tcx>>,
2437+
Option<ObligationCause<'tcx>>,
2438+
)],
2439+
) {
2440+
let derives_grouped =
2441+
self.note_predicate_source_and_get_derives(err, unsatisfied_predicates);
24222442
for (self_name, self_span, traits) in &derives_grouped {
24232443
err.span_suggestion_verbose(
24242444
self_span.shrink_to_lo(),

compiler/rustc_hir_typeck/src/op.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
318318
lhs_expr.span,
319319
format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty),
320320
);
321-
self.note_unmet_impls_on_type(&mut err, errors);
321+
self.note_unmet_impls_on_type(&mut err, errors, false);
322322
(err, None)
323323
}
324324
IsAssign::No => {
@@ -375,7 +375,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
375375
err.span_label(lhs_expr.span, lhs_ty.to_string());
376376
err.span_label(rhs_expr.span, rhs_ty.to_string());
377377
}
378-
self.note_unmet_impls_on_type(&mut err, errors);
378+
let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty);
379+
self.note_unmet_impls_on_type(&mut err, errors, suggest_derive);
379380
(err, output_def_id)
380381
}
381382
};
@@ -852,7 +853,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
852853
Str | Never | Char | Tuple(_) | Array(_, _) => {}
853854
Ref(_, lty, _) if *lty.kind() == Str => {}
854855
_ => {
855-
self.note_unmet_impls_on_type(&mut err, errors);
856+
self.note_unmet_impls_on_type(&mut err, errors, true);
856857
}
857858
}
858859
}

tests/ui/binop/binary-op-suggest-deref.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,6 @@ note: an implementation of `PartialEq<&&{integer}>` might be missing for `Foo`
270270
|
271271
LL | struct Foo;
272272
| ^^^^^^^^^^ must implement `PartialEq<&&{integer}>`
273-
help: consider annotating `Foo` with `#[derive(PartialEq)]`
274-
|
275-
LL + #[derive(PartialEq)]
276-
LL | struct Foo;
277-
|
278273

279274
error[E0277]: can't compare `&String` with `str`
280275
--> $DIR/binary-op-suggest-deref.rs:69:20

tests/ui/issues/issue-62375.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ note: an implementation of `PartialEq<fn(()) -> A {A::Value}>` might be missing
1111
|
1212
LL | enum A {
1313
| ^^^^^^ must implement `PartialEq<fn(()) -> A {A::Value}>`
14-
help: consider annotating `A` with `#[derive(PartialEq)]`
15-
|
16-
LL + #[derive(PartialEq)]
17-
LL | enum A {
18-
|
1914
help: use parentheses to construct this tuple variant
2015
|
2116
LL | a == A::Value(/* () */);

0 commit comments

Comments
 (0)