mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 21:42:44 +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::DeepRejectCtxt;
|
||||||
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
|
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::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::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
|
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
|
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 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 {
|
||||||
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() {
|
let adt = match trait_pred.self_ty().ty_adt_def() {
|
||||||
Some(adt) if adt.did().is_local() => adt,
|
Some(adt) if adt.did().is_local() => adt,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
@ -2085,22 +2089,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
| sym::Hash
|
| sym::Hash
|
||||||
| sym::Debug => true,
|
| sym::Debug => true,
|
||||||
_ => false,
|
_ => 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 {
|
if can_derive {
|
||||||
let self_name = trait_pred.self_ty().to_string();
|
let self_name = trait_pred.self_ty().to_string();
|
||||||
let self_span = self.tcx.def_span(adt.did());
|
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
|
||||||
for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
|
supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
|
||||||
{
|
{
|
||||||
if let Some(parent_diagnostic_name) =
|
if let Some(parent_diagnostic_name) =
|
||||||
self.tcx.get_diagnostic_name(super_trait.def_id())
|
self.tcx.get_diagnostic_name(super_trait.def_id())
|
||||||
{
|
{
|
||||||
derives.push((
|
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
|
||||||
self_name.clone(),
|
|
||||||
self_span,
|
|
||||||
parent_diagnostic_name,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
derives.push((self_name, self_span, 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(
|
self.lookup_op_method(
|
||||||
lhs_ty,
|
lhs_ty,
|
||||||
Some((rhs_expr, rhs_ty)),
|
Some((rhs_expr, rhs_ty)),
|
||||||
@ -416,6 +416,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
expected,
|
expected,
|
||||||
)
|
)
|
||||||
.is_ok()
|
.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
|
// 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);
|
suggest_deref_binop(*lhs_deref_ty);
|
||||||
}
|
}
|
||||||
} else if self.suggest_fn_call(&mut err, lhs_expr, lhs_ty, |lhs_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| {
|
}) || 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(
|
}) || self.suggest_two_fn_call(
|
||||||
&mut err,
|
&mut err,
|
||||||
rhs_expr,
|
rhs_expr,
|
||||||
rhs_ty,
|
rhs_ty,
|
||||||
lhs_expr,
|
lhs_expr,
|
||||||
lhs_ty,
|
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
|
// Cool
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ 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)]`
|
note: the trait `PartialEq` must be implemented
|
||||||
|
|
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
||||||
LL + #[derive(PartialEq)]
|
help: use parentheses to construct this tuple variant
|
||||||
LL | enum A {
|
|
||||||
|
|
|
|
||||||
|
LL | a == A::Value(/* () */);
|
||||||
|
| ++++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user