Skip to content

Commit 3125979

Browse files
Fix a bad binop error when we need a call
1 parent 015acc2 commit 3125979

File tree

3 files changed

+39
-21
lines changed

3 files changed

+39
-21
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+26-13
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ use rustc_middle::traits::util::supertraits;
2727
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
2828
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
2929
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
30+
use rustc_middle::ty::IsSuggestable;
3031
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
31-
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
3232
use rustc_span::symbol::{kw, sym, Ident};
3333
use rustc_span::Symbol;
3434
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
@@ -2068,7 +2068,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20682068
let mut derives = Vec::<(String, Span, Symbol)>::new();
20692069
let mut traits = Vec::new();
20702070
for (pred, _, _) in unsatisfied_predicates {
2071-
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
2071+
let Some(ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))) =
2072+
pred.kind().no_bound_vars()
2073+
else {
2074+
continue
2075+
};
20722076
let adt = match trait_pred.self_ty().ty_adt_def() {
20732077
Some(adt) if adt.did().is_local() => adt,
20742078
_ => continue,
@@ -2085,22 +2089,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20852089
| sym::Hash
20862090
| sym::Debug => true,
20872091
_ => false,
2092+
} && match trait_pred.trait_ref.substs.as_slice() {
2093+
// Only suggest deriving if lhs == rhs...
2094+
[lhs, rhs] => {
2095+
if let Some(lhs) = lhs.as_type()
2096+
&& let Some(rhs) = rhs.as_type()
2097+
{
2098+
self.can_eq(self.param_env, lhs, rhs)
2099+
} else {
2100+
false
2101+
}
2102+
},
2103+
// Unary ops can always be derived
2104+
[_] => true,
2105+
_ => false,
20882106
};
20892107
if can_derive {
20902108
let self_name = trait_pred.self_ty().to_string();
20912109
let self_span = self.tcx.def_span(adt.did());
2092-
if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
2093-
for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
2110+
for super_trait in
2111+
supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
2112+
{
2113+
if let Some(parent_diagnostic_name) =
2114+
self.tcx.get_diagnostic_name(super_trait.def_id())
20942115
{
2095-
if let Some(parent_diagnostic_name) =
2096-
self.tcx.get_diagnostic_name(super_trait.def_id())
2097-
{
2098-
derives.push((
2099-
self_name.clone(),
2100-
self_span,
2101-
parent_diagnostic_name,
2102-
));
2103-
}
2116+
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
21042117
}
21052118
}
21062119
derives.push((self_name, self_span, diagnostic_name));

compiler/rustc_hir_typeck/src/op.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -408,14 +408,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
408408
}
409409
};
410410

411-
let is_compatible = |lhs_ty, rhs_ty| {
411+
let is_compatible_after_call = |lhs_ty, rhs_ty| {
412412
self.lookup_op_method(
413413
lhs_ty,
414414
Some((rhs_expr, rhs_ty)),
415415
Op::Binary(op, is_assign),
416416
expected,
417417
)
418418
.is_ok()
419+
// Suggest calling even if, after calling, the types don't
420+
// implement the operator, since it'll lead to better
421+
// diagnostics later.
422+
|| self.can_eq(self.param_env, lhs_ty, rhs_ty)
419423
};
420424

421425
// We should suggest `a + b` => `*a + b` if `a` is copy, and suggest
@@ -436,16 +440,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
436440
suggest_deref_binop(*lhs_deref_ty);
437441
}
438442
} else if self.suggest_fn_call(&mut err, lhs_expr, lhs_ty, |lhs_ty| {
439-
is_compatible(lhs_ty, rhs_ty)
443+
is_compatible_after_call(lhs_ty, rhs_ty)
440444
}) || self.suggest_fn_call(&mut err, rhs_expr, rhs_ty, |rhs_ty| {
441-
is_compatible(lhs_ty, rhs_ty)
445+
is_compatible_after_call(lhs_ty, rhs_ty)
442446
}) || self.suggest_two_fn_call(
443447
&mut err,
444448
rhs_expr,
445449
rhs_ty,
446450
lhs_expr,
447451
lhs_ty,
448-
|lhs_ty, rhs_ty| is_compatible(lhs_ty, rhs_ty),
452+
|lhs_ty, rhs_ty| is_compatible_after_call(lhs_ty, rhs_ty),
449453
) {
450454
// Cool
451455
}

tests/ui/issues/issue-62375.stderr

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ 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 {
14+
note: the trait `PartialEq` must be implemented
15+
--> $SRC_DIR/core/src/cmp.rs:LL:COL
16+
help: use parentheses to construct this tuple variant
1817
|
18+
LL | a == A::Value(/* () */);
19+
| ++++++++++
1920

2021
error: aborting due to previous error
2122

0 commit comments

Comments
 (0)