Skip to content

Commit 2b88d14

Browse files
committed
Suggest dereferencing &T == T and T == &T
1 parent de686cb commit 2b88d14

File tree

13 files changed

+665
-174
lines changed

13 files changed

+665
-174
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4580,6 +4580,7 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
45804580
name = "rustc_trait_selection"
45814581
version = "0.0.0"
45824582
dependencies = [
4583+
"itertools",
45834584
"rustc_ast",
45844585
"rustc_attr",
45854586
"rustc_data_structures",

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2441,7 +2441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24412441
}
24422442
};
24432443

2444-
// Suggest dereferencing the lhs for expressions such as `&T == T`
2444+
// Suggest dereferencing the lhs for expressions such as `&T <= T`
24452445
if let Some(hir::Node::Expr(hir::Expr {
24462446
kind: hir::ExprKind::Binary(_, lhs, ..),
24472447
..

compiler/rustc_hir_typeck/src/op.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4747
if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
4848
if self
4949
.lookup_op_method(
50-
lhs_deref_ty,
50+
(lhs, lhs_deref_ty),
5151
Some((rhs, rhs_ty)),
5252
Op::Binary(op, IsAssign::Yes),
5353
expected,
@@ -58,7 +58,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5858
// emitted a better suggestion during error handling in check_overloaded_binop.
5959
if self
6060
.lookup_op_method(
61-
lhs_ty,
61+
(lhs, lhs_ty),
6262
Some((rhs, rhs_ty)),
6363
Op::Binary(op, IsAssign::Yes),
6464
expected,
@@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
246246
});
247247

248248
let result = self.lookup_op_method(
249-
lhs_ty,
249+
(lhs_expr, lhs_ty),
250250
Some((rhs_expr, rhs_ty_var)),
251251
Op::Binary(op, is_assign),
252252
expected,
@@ -391,7 +391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
391391
|err: &mut DiagnosticBuilder<'_, _>, lhs_deref_ty: Ty<'tcx>| {
392392
if self
393393
.lookup_op_method(
394-
lhs_deref_ty,
394+
(lhs_expr, lhs_deref_ty),
395395
Some((rhs_expr, rhs_ty)),
396396
Op::Binary(op, is_assign),
397397
expected,
@@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
424424
rhs_new_mutbl: Option<ast::Mutability>| {
425425
if self
426426
.lookup_op_method(
427-
lhs_adjusted_ty,
427+
(lhs_expr, lhs_adjusted_ty),
428428
Some((rhs_expr, rhs_adjusted_ty)),
429429
Op::Binary(op, is_assign),
430430
expected,
@@ -479,7 +479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
479479

480480
let is_compatible_after_call = |lhs_ty, rhs_ty| {
481481
self.lookup_op_method(
482-
lhs_ty,
482+
(lhs_expr, lhs_ty),
483483
Some((rhs_expr, rhs_ty)),
484484
Op::Binary(op, is_assign),
485485
expected,
@@ -578,7 +578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
578578
// suggestion for the user.
579579
let errors = self
580580
.lookup_op_method(
581-
lhs_ty,
581+
(lhs_expr, lhs_ty),
582582
Some((rhs_expr, rhs_ty)),
583583
Op::Binary(op, is_assign),
584584
expected,
@@ -779,7 +779,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
779779
expected: Expectation<'tcx>,
780780
) -> Ty<'tcx> {
781781
assert!(op.is_by_value());
782-
match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) {
782+
match self.lookup_op_method((ex, operand_ty), None, Op::Unary(op, ex.span), expected) {
783783
Ok(method) => {
784784
self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method);
785785
method.sig.output()
@@ -865,7 +865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
865865

866866
fn lookup_op_method(
867867
&self,
868-
lhs_ty: Ty<'tcx>,
868+
(lhs_expr, lhs_ty): (&'tcx hir::Expr<'tcx>, Ty<'tcx>),
869869
opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>,
870870
op: Op,
871871
expected: Expectation<'tcx>,
@@ -910,8 +910,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
910910
let cause = self.cause(
911911
span,
912912
traits::BinOp {
913+
lhs_hir_id: lhs_expr.hir_id,
914+
rhs_hir_id: opt_rhs_expr.map(|expr| expr.hir_id),
913915
rhs_span: opt_rhs_expr.map(|expr| expr.span),
914-
is_lit: opt_rhs_expr.is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
916+
rhs_is_lit: opt_rhs_expr
917+
.is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
915918
output_ty: expected.only_has_type(self),
916919
},
917920
);

compiler/rustc_middle/src/traits/mod.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,10 @@ pub enum ObligationCauseCode<'tcx> {
429429
MatchImpl(ObligationCause<'tcx>, DefId),
430430

431431
BinOp {
432+
lhs_hir_id: hir::HirId,
433+
rhs_hir_id: Option<hir::HirId>,
432434
rhs_span: Option<Span>,
433-
is_lit: bool,
435+
rhs_is_lit: bool,
434436
output_ty: Option<Ty<'tcx>>,
435437
},
436438

@@ -510,6 +512,21 @@ impl<'tcx> ObligationCauseCode<'tcx> {
510512
base_cause
511513
}
512514

515+
/// Returns the base obligation and the base trait predicate, if any, ignoring
516+
/// derived obligations.
517+
pub fn peel_derives_with_predicate(&self) -> (&Self, Option<ty::PolyTraitPredicate<'tcx>>) {
518+
let mut base_cause = self;
519+
let mut base_trait_pred = None;
520+
while let Some((parent_code, parent_pred)) = base_cause.parent() {
521+
base_cause = parent_code;
522+
if let Some(parent_pred) = parent_pred {
523+
base_trait_pred = Some(parent_pred);
524+
}
525+
}
526+
527+
(base_cause, base_trait_pred)
528+
}
529+
513530
pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
514531
match self {
515532
FunctionArgumentObligation { parent_code, .. } => Some((parent_code, None)),

compiler/rustc_trait_selection/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
# tidy-alphabetical-start
8+
itertools = "0.11.0"
89
rustc_ast = { path = "../rustc_ast" }
910
rustc_attr = { path = "../rustc_attr" }
1011
rustc_data_structures = { path = "../rustc_data_structures" }

0 commit comments

Comments
 (0)