Skip to content

Commit

Permalink
Provide better suggestions for T == &T and &T == T
Browse files Browse the repository at this point in the history
  • Loading branch information
sjwang05 committed Dec 17, 2023
1 parent de686cb commit 2618e0f
Show file tree
Hide file tree
Showing 13 changed files with 668 additions and 174 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4580,6 +4580,7 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
name = "rustc_trait_selection"
version = "0.0.0"
dependencies = [
"itertools",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2441,7 +2441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};

// Suggest dereferencing the lhs for expressions such as `&T == T`
// Suggest dereferencing the lhs for expressions such as `&T <= T`
if let Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Binary(_, lhs, ..),
..
Expand Down
23 changes: 13 additions & 10 deletions compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
if self
.lookup_op_method(
lhs_deref_ty,
(lhs, lhs_deref_ty),
Some((rhs, rhs_ty)),
Op::Binary(op, IsAssign::Yes),
expected,
Expand All @@ -58,7 +58,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// emitted a better suggestion during error handling in check_overloaded_binop.
if self
.lookup_op_method(
lhs_ty,
(lhs, lhs_ty),
Some((rhs, rhs_ty)),
Op::Binary(op, IsAssign::Yes),
expected,
Expand Down Expand Up @@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});

let result = self.lookup_op_method(
lhs_ty,
(lhs_expr, lhs_ty),
Some((rhs_expr, rhs_ty_var)),
Op::Binary(op, is_assign),
expected,
Expand Down Expand Up @@ -391,7 +391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|err: &mut DiagnosticBuilder<'_, _>, lhs_deref_ty: Ty<'tcx>| {
if self
.lookup_op_method(
lhs_deref_ty,
(lhs_expr, lhs_deref_ty),
Some((rhs_expr, rhs_ty)),
Op::Binary(op, is_assign),
expected,
Expand Down Expand Up @@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rhs_new_mutbl: Option<ast::Mutability>| {
if self
.lookup_op_method(
lhs_adjusted_ty,
(lhs_expr, lhs_adjusted_ty),
Some((rhs_expr, rhs_adjusted_ty)),
Op::Binary(op, is_assign),
expected,
Expand Down Expand Up @@ -479,7 +479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let is_compatible_after_call = |lhs_ty, rhs_ty| {
self.lookup_op_method(
lhs_ty,
(lhs_expr, lhs_ty),
Some((rhs_expr, rhs_ty)),
Op::Binary(op, is_assign),
expected,
Expand Down Expand Up @@ -578,7 +578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// suggestion for the user.
let errors = self
.lookup_op_method(
lhs_ty,
(lhs_expr, lhs_ty),
Some((rhs_expr, rhs_ty)),
Op::Binary(op, is_assign),
expected,
Expand Down Expand Up @@ -779,7 +779,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
assert!(op.is_by_value());
match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) {
match self.lookup_op_method((ex, operand_ty), None, Op::Unary(op, ex.span), expected) {
Ok(method) => {
self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method);
method.sig.output()
Expand Down Expand Up @@ -865,7 +865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

fn lookup_op_method(
&self,
lhs_ty: Ty<'tcx>,
(lhs_expr, lhs_ty): (&'tcx hir::Expr<'tcx>, Ty<'tcx>),
opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>,
op: Op,
expected: Expectation<'tcx>,
Expand Down Expand Up @@ -910,8 +910,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let cause = self.cause(
span,
traits::BinOp {
lhs_hir_id: lhs_expr.hir_id,
rhs_hir_id: opt_rhs_expr.map(|expr| expr.hir_id),
rhs_span: opt_rhs_expr.map(|expr| expr.span),
is_lit: opt_rhs_expr.is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
rhs_is_lit: opt_rhs_expr
.is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
output_ty: expected.only_has_type(self),
},
);
Expand Down
19 changes: 18 additions & 1 deletion compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,10 @@ pub enum ObligationCauseCode<'tcx> {
MatchImpl(ObligationCause<'tcx>, DefId),

BinOp {
lhs_hir_id: hir::HirId,
rhs_hir_id: Option<hir::HirId>,
rhs_span: Option<Span>,
is_lit: bool,
rhs_is_lit: bool,
output_ty: Option<Ty<'tcx>>,
},

Expand Down Expand Up @@ -510,6 +512,21 @@ impl<'tcx> ObligationCauseCode<'tcx> {
base_cause
}

/// Returns the base obligation and the base trait predicate, if any, ignoring
/// derived obligations.
pub fn peel_derives_with_predicate(&self) -> (&Self, Option<ty::PolyTraitPredicate<'tcx>>) {
let mut base_cause = self;
let mut base_trait_pred = None;
while let Some((parent_code, parent_pred)) = base_cause.parent() {
base_cause = parent_code;
if let Some(parent_pred) = parent_pred {
base_trait_pred = Some(parent_pred);
}
}

(base_cause, base_trait_pred)
}

pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
match self {
FunctionArgumentObligation { parent_code, .. } => Some((parent_code, None)),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
# tidy-alphabetical-start
itertools = "0.11.0"
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
Expand Down
Loading

0 comments on commit 2618e0f

Please sign in to comment.