Skip to content

Commit

Permalink
Rollup merge of rust-lang#5424 - jpospychala:suspicious_op_assign_imp…
Browse files Browse the repository at this point in the history
…l, r=flip1995

Incorrect suspicious_op_assign_impl

fixes rust-lang#5255

changelog: In suspicious_op_assign_impl ignore all operators in expression if it's part of AssignOp
  • Loading branch information
flip1995 authored Apr 7, 2020
2 parents e55ec76 + 9c9af1d commit 1242808
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 6 deletions.
10 changes: 6 additions & 4 deletions clippy_lints/src/suspicious_trait_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) {
if let hir::ExprKind::Binary(binop, _, _) = expr.kind {
if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind {
match binop.node {
hir::BinOpKind::Eq
| hir::BinOpKind::Lt
Expand All @@ -65,14 +65,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl {
_ => {},
}
// Check if the binary expression is part of another bi/unary expression
// as a child node
// or operator assignment as a child node
let mut parent_expr = cx.tcx.hir().get_parent_node(expr.hir_id);
while parent_expr != hir::CRATE_HIR_ID {
if let hir::Node::Expr(e) = cx.tcx.hir().get(parent_expr) {
match e.kind {
hir::ExprKind::Binary(..)
| hir::ExprKind::Unary(hir::UnOp::UnNot, _)
| hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => return,
| hir::ExprKind::Unary(hir::UnOp::UnNeg, _)
| hir::ExprKind::AssignOp(..) => return,
_ => {},
}
}
Expand Down Expand Up @@ -191,7 +192,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BinaryExprVisitor {
match expr.kind {
hir::ExprKind::Binary(..)
| hir::ExprKind::Unary(hir::UnOp::UnNot, _)
| hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => self.in_binary_expr = true,
| hir::ExprKind::Unary(hir::UnOp::UnNeg, _)
| hir::ExprKind::AssignOp(..) => self.in_binary_expr = true,
_ => {},
}

Expand Down
21 changes: 20 additions & 1 deletion tests/ui/suspicious_arithmetic_impl.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![warn(clippy::suspicious_arithmetic_impl)]
use std::ops::{Add, AddAssign, Div, Mul, Sub};
use std::ops::{Add, AddAssign, BitOrAssign, Div, DivAssign, Mul, MulAssign, Sub};

#[derive(Copy, Clone)]
struct Foo(u32);
Expand All @@ -18,6 +18,25 @@ impl AddAssign for Foo {
}
}

impl BitOrAssign for Foo {
fn bitor_assign(&mut self, other: Foo) {
let idx = other.0;
self.0 |= 1 << idx; // OK: BinOpKind::Shl part of AssignOp as child node
}
}

impl MulAssign for Foo {
fn mul_assign(&mut self, other: Foo) {
self.0 /= other.0;
}
}

impl DivAssign for Foo {
fn div_assign(&mut self, other: Foo) {
self.0 /= other.0; // OK: BinOpKind::Div == DivAssign
}
}

impl Mul for Foo {
type Output = Foo;

Expand Down
8 changes: 7 additions & 1 deletion tests/ui/suspicious_arithmetic_impl.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,11 @@ LL | *self = *self - other;
|
= note: `#[deny(clippy::suspicious_op_assign_impl)]` on by default

error: aborting due to 2 previous errors
error: Suspicious use of binary operator in `MulAssign` impl
--> $DIR/suspicious_arithmetic_impl.rs:30:16
|
LL | self.0 /= other.0;
| ^^

error: aborting due to 3 previous errors

0 comments on commit 1242808

Please sign in to comment.