#![warn(clippy::suspicious_arithmetic_impl)] use std::ops::{ Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Div, DivAssign, Mul, MulAssign, Rem, Shl, Shr, Sub, }; #[derive(Copy, Clone)] struct Foo(u32); impl Add for Foo { type Output = Foo; fn add(self, other: Self) -> Self { Foo(self.0 - other.0) //~^ ERROR: suspicious use of `-` in `Add` impl //~| NOTE: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` } } impl AddAssign for Foo { fn add_assign(&mut self, other: Foo) { *self = *self - other; //~^ ERROR: suspicious use of `-` in `AddAssign` impl //~| NOTE: `-D clippy::suspicious-op-assign-impl` implied by `-D warnings` } } 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; //~^ ERROR: suspicious use of `/` in `MulAssign` impl } } 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; fn mul(self, other: Foo) -> Foo { Foo(self.0 * other.0 % 42) // OK: BinOpKind::Rem part of BiExpr as parent node } } impl Sub for Foo { type Output = Foo; fn sub(self, other: Self) -> Self { Foo(self.0 * other.0 - 42) // OK: BinOpKind::Mul part of BiExpr as child node } } impl Div for Foo { type Output = Foo; fn div(self, other: Self) -> Self { Foo(do_nothing(self.0 + other.0) / 42) // OK: BinOpKind::Add part of BiExpr as child node } } impl Rem for Foo { type Output = Foo; fn rem(self, other: Self) -> Self { Foo(self.0 / other.0) //~^ ERROR: suspicious use of `/` in `Rem` impl } } impl BitAnd for Foo { type Output = Foo; fn bitand(self, other: Self) -> Self { Foo(self.0 | other.0) //~^ ERROR: suspicious use of `|` in `BitAnd` impl } } impl BitOr for Foo { type Output = Foo; fn bitor(self, other: Self) -> Self { Foo(self.0 ^ other.0) //~^ ERROR: suspicious use of `^` in `BitOr` impl } } impl BitXor for Foo { type Output = Foo; fn bitxor(self, other: Self) -> Self { Foo(self.0 & other.0) //~^ ERROR: suspicious use of `&` in `BitXor` impl } } impl Shl for Foo { type Output = Foo; fn shl(self, other: Self) -> Self { Foo(self.0 >> other.0) //~^ ERROR: suspicious use of `>>` in `Shl` impl } } impl Shr for Foo { type Output = Foo; fn shr(self, other: Self) -> Self { Foo(self.0 << other.0) //~^ ERROR: suspicious use of `<<` in `Shr` impl } } struct Bar(i32); impl Add for Bar { type Output = Bar; fn add(self, other: Self) -> Self { Bar(self.0 & !other.0) // OK: Not part of BiExpr as child node } } impl Sub for Bar { type Output = Bar; fn sub(self, other: Self) -> Self { if self.0 <= other.0 { Bar(-(self.0 & other.0)) // OK: Neg part of BiExpr as parent node } else { Bar(0) } } } fn main() {} fn do_nothing(x: u32) -> u32 { x } struct MultipleBinops(u32); impl Add for MultipleBinops { type Output = MultipleBinops; // OK: multiple Binops in `add` impl fn add(self, other: Self) -> Self::Output { let mut result = self.0 + other.0; if result >= u32::max_value() { result -= u32::max_value(); } MultipleBinops(result) } } impl Mul for MultipleBinops { type Output = MultipleBinops; // OK: multiple Binops in `mul` impl fn mul(self, other: Self) -> Self::Output { let mut result: u32 = 0; let size = std::cmp::max(self.0, other.0) as usize; let mut v = vec![0; size + 1]; for i in 0..size + 1 { result *= i as u32; } MultipleBinops(result) } }