Rollup merge of #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.
This commit is contained in:
commit
6526b164a3
@ -2252,6 +2252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
errors: Vec<FulfillmentError<'tcx>>,
|
errors: Vec<FulfillmentError<'tcx>>,
|
||||||
|
suggest_derive: bool,
|
||||||
) {
|
) {
|
||||||
let all_local_types_needing_impls =
|
let all_local_types_needing_impls =
|
||||||
errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
|
errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
|
||||||
@ -2322,10 +2323,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
|
.map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
|
||||||
.collect();
|
.collect();
|
||||||
|
if suggest_derive {
|
||||||
self.suggest_derive(err, &preds);
|
self.suggest_derive(err, &preds);
|
||||||
|
} else {
|
||||||
|
// The predicate comes from a binop where the lhs and rhs have different types.
|
||||||
|
let _ = self.note_predicate_source_and_get_derives(err, &preds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn suggest_derive(
|
fn note_predicate_source_and_get_derives(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
unsatisfied_predicates: &[(
|
unsatisfied_predicates: &[(
|
||||||
@ -2333,7 +2339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
Option<ty::Predicate<'tcx>>,
|
Option<ty::Predicate<'tcx>>,
|
||||||
Option<ObligationCause<'tcx>>,
|
Option<ObligationCause<'tcx>>,
|
||||||
)],
|
)],
|
||||||
) {
|
) -> Vec<(String, Span, Symbol)> {
|
||||||
let mut derives = Vec::<(String, Span, Symbol)>::new();
|
let mut derives = Vec::<(String, Span, Symbol)>::new();
|
||||||
let mut traits = Vec::new();
|
let mut traits = Vec::new();
|
||||||
for (pred, _, _) in unsatisfied_predicates {
|
for (pred, _, _) in unsatisfied_predicates {
|
||||||
@ -2382,21 +2388,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
traits.sort();
|
traits.sort();
|
||||||
traits.dedup();
|
traits.dedup();
|
||||||
|
|
||||||
derives.sort();
|
|
||||||
derives.dedup();
|
|
||||||
|
|
||||||
let mut derives_grouped = Vec::<(String, Span, String)>::new();
|
|
||||||
for (self_name, self_span, trait_name) in derives.into_iter() {
|
|
||||||
if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
|
|
||||||
{
|
|
||||||
if last_self_name == &self_name {
|
|
||||||
last_trait_names.push_str(format!(", {trait_name}").as_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
derives_grouped.push((self_name, self_span, trait_name.to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let len = traits.len();
|
let len = traits.len();
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
let span =
|
let span =
|
||||||
@ -2419,6 +2410,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
derives
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn suggest_derive(
|
||||||
|
&self,
|
||||||
|
err: &mut Diagnostic,
|
||||||
|
unsatisfied_predicates: &[(
|
||||||
|
ty::Predicate<'tcx>,
|
||||||
|
Option<ty::Predicate<'tcx>>,
|
||||||
|
Option<ObligationCause<'tcx>>,
|
||||||
|
)],
|
||||||
|
) {
|
||||||
|
let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates);
|
||||||
|
derives.sort();
|
||||||
|
derives.dedup();
|
||||||
|
|
||||||
|
let mut derives_grouped = Vec::<(String, Span, String)>::new();
|
||||||
|
for (self_name, self_span, trait_name) in derives.into_iter() {
|
||||||
|
if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
|
||||||
|
{
|
||||||
|
if last_self_name == &self_name {
|
||||||
|
last_trait_names.push_str(format!(", {trait_name}").as_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
derives_grouped.push((self_name, self_span, trait_name.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
for (self_name, self_span, traits) in &derives_grouped {
|
for (self_name, self_span, traits) in &derives_grouped {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
self_span.shrink_to_lo(),
|
self_span.shrink_to_lo(),
|
||||||
|
@ -318,7 +318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
lhs_expr.span,
|
lhs_expr.span,
|
||||||
format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty),
|
format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty),
|
||||||
);
|
);
|
||||||
self.note_unmet_impls_on_type(&mut err, errors);
|
self.note_unmet_impls_on_type(&mut err, errors, false);
|
||||||
(err, None)
|
(err, None)
|
||||||
}
|
}
|
||||||
IsAssign::No => {
|
IsAssign::No => {
|
||||||
@ -375,7 +375,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
err.span_label(lhs_expr.span, lhs_ty.to_string());
|
err.span_label(lhs_expr.span, lhs_ty.to_string());
|
||||||
err.span_label(rhs_expr.span, rhs_ty.to_string());
|
err.span_label(rhs_expr.span, rhs_ty.to_string());
|
||||||
}
|
}
|
||||||
self.note_unmet_impls_on_type(&mut err, errors);
|
let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty);
|
||||||
|
self.note_unmet_impls_on_type(&mut err, errors, suggest_derive);
|
||||||
(err, output_def_id)
|
(err, output_def_id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -852,7 +853,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
Str | Never | Char | Tuple(_) | Array(_, _) => {}
|
Str | Never | Char | Tuple(_) | Array(_, _) => {}
|
||||||
Ref(_, lty, _) if *lty.kind() == Str => {}
|
Ref(_, lty, _) if *lty.kind() == Str => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.note_unmet_impls_on_type(&mut err, errors);
|
self.note_unmet_impls_on_type(&mut err, errors, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,11 +270,6 @@ note: an implementation of `PartialEq<&&{integer}>` might be missing for `Foo`
|
|||||||
|
|
|
|
||||||
LL | struct Foo;
|
LL | struct Foo;
|
||||||
| ^^^^^^^^^^ must implement `PartialEq<&&{integer}>`
|
| ^^^^^^^^^^ must implement `PartialEq<&&{integer}>`
|
||||||
help: consider annotating `Foo` with `#[derive(PartialEq)]`
|
|
||||||
|
|
|
||||||
LL + #[derive(PartialEq)]
|
|
||||||
LL | struct Foo;
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0277]: can't compare `&String` with `str`
|
error[E0277]: can't compare `&String` with `str`
|
||||||
--> $DIR/binary-op-suggest-deref.rs:69:20
|
--> $DIR/binary-op-suggest-deref.rs:69:20
|
||||||
|
@ -11,11 +11,6 @@ note: an implementation of `PartialEq<fn(()) -> A {A::Value}>` might be missing
|
|||||||
|
|
|
|
||||||
LL | enum A {
|
LL | enum A {
|
||||||
| ^^^^^^ must implement `PartialEq<fn(()) -> A {A::Value}>`
|
| ^^^^^^ must implement `PartialEq<fn(()) -> A {A::Value}>`
|
||||||
help: consider annotating `A` with `#[derive(PartialEq)]`
|
|
||||||
|
|
|
||||||
LL + #[derive(PartialEq)]
|
|
||||||
LL | enum A {
|
|
||||||
|
|
|
||||||
help: use parentheses to construct this tuple variant
|
help: use parentheses to construct this tuple variant
|
||||||
|
|
|
|
||||||
LL | a == A::Value(/* () */);
|
LL | a == A::Value(/* () */);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user