Skip to content

Commit e42e16d

Browse files
Rollup merge of rust-lang#119362 - estebank:restrict-derive-suggestion, r=fmease
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.
2 parents 2587388 + 2474b37 commit e42e16d

File tree

4 files changed

+41
-31
lines changed

4 files changed

+41
-31
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+37-18
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, Symbol)> {
23372343
let mut derives = Vec::<(String, Span, Symbol)>::new();
23382344
let mut traits = Vec::new();
23392345
for (pred, _, _) in unsatisfied_predicates {
@@ -2382,21 +2388,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23822388
traits.sort();
23832389
traits.dedup();
23842390

2385-
derives.sort();
2386-
derives.dedup();
2387-
2388-
let mut derives_grouped = Vec::<(String, Span, String)>::new();
2389-
for (self_name, self_span, trait_name) in derives.into_iter() {
2390-
if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
2391-
{
2392-
if last_self_name == &self_name {
2393-
last_trait_names.push_str(format!(", {trait_name}").as_str());
2394-
continue;
2395-
}
2396-
}
2397-
derives_grouped.push((self_name, self_span, trait_name.to_string()));
2398-
}
2399-
24002391
let len = traits.len();
24012392
if len > 0 {
24022393
let span =
@@ -2419,6 +2410,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24192410
);
24202411
}
24212412

2413+
derives
2414+
}
2415+
2416+
pub(crate) fn suggest_derive(
2417+
&self,
2418+
err: &mut Diagnostic,
2419+
unsatisfied_predicates: &[(
2420+
ty::Predicate<'tcx>,
2421+
Option<ty::Predicate<'tcx>>,
2422+
Option<ObligationCause<'tcx>>,
2423+
)],
2424+
) {
2425+
let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates);
2426+
derives.sort();
2427+
derives.dedup();
2428+
2429+
let mut derives_grouped = Vec::<(String, Span, String)>::new();
2430+
for (self_name, self_span, trait_name) in derives.into_iter() {
2431+
if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
2432+
{
2433+
if last_self_name == &self_name {
2434+
last_trait_names.push_str(format!(", {trait_name}").as_str());
2435+
continue;
2436+
}
2437+
}
2438+
derives_grouped.push((self_name, self_span, trait_name.to_string()));
2439+
}
2440+
24222441
for (self_name, self_span, traits) in &derives_grouped {
24232442
err.span_suggestion_verbose(
24242443
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)