1 use clippy_utils::diagnostics::span_lint_and_then;
2 use clippy_utils::eq_expr_value;
3 use clippy_utils::source::snippet_opt;
4 use clippy_utils::sugg;
5 use rustc_errors::Applicability;
7 use rustc_lint::LateContext;
9 use super::MISREFACTORED_ASSIGN_OP;
11 pub(super) fn check<'tcx>(
12 cx: &LateContext<'tcx>,
13 expr: &'tcx hir::Expr<'_>,
15 lhs: &'tcx hir::Expr<'_>,
16 rhs: &'tcx hir::Expr<'_>,
18 if let hir::ExprKind::Binary(binop, l, r) = &rhs.kind {
23 if eq_expr_value(cx, lhs, l) {
24 lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, r);
26 // lhs op= l commutative_op r
27 if is_commutative(op) && eq_expr_value(cx, lhs, r) {
28 lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, l);
33 fn lint_misrefactored_assign_op(
38 assignee: &hir::Expr<'_>,
39 rhs_other: &hir::Expr<'_>,
43 MISREFACTORED_ASSIGN_OP,
45 "variable appears on both sides of an assignment operation",
47 if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
48 let a = &sugg::Sugg::hir(cx, assignee, "..");
49 let r = &sugg::Sugg::hir(cx, rhs, "..");
50 let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r));
54 "did you mean `{snip_a} = {snip_a} {} {snip_r}` or `{long}`? Consider replacing it with",
57 format!("{snip_a} {}= {snip_r}", op.as_str()),
58 Applicability::MaybeIncorrect,
64 Applicability::MaybeIncorrect, // snippet
72 fn is_commutative(op: hir::BinOpKind) -> bool {
73 use rustc_hir::BinOpKind::{
74 Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub,
77 Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true,
78 Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false,