mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-02 10:04:23 +00:00
Fix a bad binop error when we need a call
This commit is contained in:
parent
015acc2611
commit
3125979b78
@ -27,8 +27,8 @@ use rustc_middle::traits::util::supertraits;
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
|
||||
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
|
||||
use rustc_middle::ty::IsSuggestable;
|
||||
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
|
||||
@ -2068,7 +2068,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let mut derives = Vec::<(String, Span, Symbol)>::new();
|
||||
let mut traits = Vec::new();
|
||||
for (pred, _, _) in unsatisfied_predicates {
|
||||
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
|
||||
let Some(ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))) =
|
||||
pred.kind().no_bound_vars()
|
||||
else {
|
||||
continue
|
||||
};
|
||||
let adt = match trait_pred.self_ty().ty_adt_def() {
|
||||
Some(adt) if adt.did().is_local() => adt,
|
||||
_ => continue,
|
||||
@ -2085,22 +2089,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
| sym::Hash
|
||||
| sym::Debug => true,
|
||||
_ => false,
|
||||
} && match trait_pred.trait_ref.substs.as_slice() {
|
||||
// Only suggest deriving if lhs == rhs...
|
||||
[lhs, rhs] => {
|
||||
if let Some(lhs) = lhs.as_type()
|
||||
&& let Some(rhs) = rhs.as_type()
|
||||
{
|
||||
self.can_eq(self.param_env, lhs, rhs)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
// Unary ops can always be derived
|
||||
[_] => true,
|
||||
_ => false,
|
||||
};
|
||||
if can_derive {
|
||||
let self_name = trait_pred.self_ty().to_string();
|
||||
let self_span = self.tcx.def_span(adt.did());
|
||||
if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
|
||||
for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
|
||||
for super_trait in
|
||||
supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
|
||||
{
|
||||
if let Some(parent_diagnostic_name) =
|
||||
self.tcx.get_diagnostic_name(super_trait.def_id())
|
||||
{
|
||||
if let Some(parent_diagnostic_name) =
|
||||
self.tcx.get_diagnostic_name(super_trait.def_id())
|
||||
{
|
||||
derives.push((
|
||||
self_name.clone(),
|
||||
self_span,
|
||||
parent_diagnostic_name,
|
||||
));
|
||||
}
|
||||
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
|
||||
}
|
||||
}
|
||||
derives.push((self_name, self_span, diagnostic_name));
|
||||
|
@ -408,7 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let is_compatible = |lhs_ty, rhs_ty| {
|
||||
let is_compatible_after_call = |lhs_ty, rhs_ty| {
|
||||
self.lookup_op_method(
|
||||
lhs_ty,
|
||||
Some((rhs_expr, rhs_ty)),
|
||||
@ -416,6 +416,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected,
|
||||
)
|
||||
.is_ok()
|
||||
// Suggest calling even if, after calling, the types don't
|
||||
// implement the operator, since it'll lead to better
|
||||
// diagnostics later.
|
||||
|| self.can_eq(self.param_env, lhs_ty, rhs_ty)
|
||||
};
|
||||
|
||||
// We should suggest `a + b` => `*a + b` if `a` is copy, and suggest
|
||||
@ -436,16 +440,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
suggest_deref_binop(*lhs_deref_ty);
|
||||
}
|
||||
} else if self.suggest_fn_call(&mut err, lhs_expr, lhs_ty, |lhs_ty| {
|
||||
is_compatible(lhs_ty, rhs_ty)
|
||||
is_compatible_after_call(lhs_ty, rhs_ty)
|
||||
}) || self.suggest_fn_call(&mut err, rhs_expr, rhs_ty, |rhs_ty| {
|
||||
is_compatible(lhs_ty, rhs_ty)
|
||||
is_compatible_after_call(lhs_ty, rhs_ty)
|
||||
}) || self.suggest_two_fn_call(
|
||||
&mut err,
|
||||
rhs_expr,
|
||||
rhs_ty,
|
||||
lhs_expr,
|
||||
lhs_ty,
|
||||
|lhs_ty, rhs_ty| is_compatible(lhs_ty, rhs_ty),
|
||||
|lhs_ty, rhs_ty| is_compatible_after_call(lhs_ty, rhs_ty),
|
||||
) {
|
||||
// Cool
|
||||
}
|
||||
|
@ -11,11 +11,12 @@ note: an implementation of `PartialEq<fn(()) -> A {A::Value}>` might be missing
|
||||
|
|
||||
LL | enum A {
|
||||
| ^^^^^^ must implement `PartialEq<fn(()) -> A {A::Value}>`
|
||||
help: consider annotating `A` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
LL | enum A {
|
||||
note: the trait `PartialEq` must be implemented
|
||||
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
||||
help: use parentheses to construct this tuple variant
|
||||
|
|
||||
LL | a == A::Value(/* () */);
|
||||
| ++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user