1 #![warn(clippy::suspicious_arithmetic_impl)]
2 use std::ops::{
3     Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Div, DivAssign, Mul, MulAssign, Rem, Shl, Shr, Sub,
4 };
5 
6 #[derive(Copy, Clone)]
7 struct Foo(u32);
8 
9 impl Add for Foo {
10     type Output = Foo;
11 
add(self, other: Self) -> Self12     fn add(self, other: Self) -> Self {
13         Foo(self.0 - other.0)
14     }
15 }
16 
17 impl AddAssign for Foo {
add_assign(&mut self, other: Foo)18     fn add_assign(&mut self, other: Foo) {
19         *self = *self - other;
20     }
21 }
22 
23 impl BitOrAssign for Foo {
bitor_assign(&mut self, other: Foo)24     fn bitor_assign(&mut self, other: Foo) {
25         let idx = other.0;
26         self.0 |= 1 << idx; // OK: BinOpKind::Shl part of AssignOp as child node
27     }
28 }
29 
30 impl MulAssign for Foo {
mul_assign(&mut self, other: Foo)31     fn mul_assign(&mut self, other: Foo) {
32         self.0 /= other.0;
33     }
34 }
35 
36 impl DivAssign for Foo {
div_assign(&mut self, other: Foo)37     fn div_assign(&mut self, other: Foo) {
38         self.0 /= other.0; // OK: BinOpKind::Div == DivAssign
39     }
40 }
41 
42 impl Mul for Foo {
43     type Output = Foo;
44 
mul(self, other: Foo) -> Foo45     fn mul(self, other: Foo) -> Foo {
46         Foo(self.0 * other.0 % 42) // OK: BinOpKind::Rem part of BiExpr as parent node
47     }
48 }
49 
50 impl Sub for Foo {
51     type Output = Foo;
52 
sub(self, other: Self) -> Self53     fn sub(self, other: Self) -> Self {
54         Foo(self.0 * other.0 - 42) // OK: BinOpKind::Mul part of BiExpr as child node
55     }
56 }
57 
58 impl Div for Foo {
59     type Output = Foo;
60 
div(self, other: Self) -> Self61     fn div(self, other: Self) -> Self {
62         Foo(do_nothing(self.0 + other.0) / 42) // OK: BinOpKind::Add part of BiExpr as child node
63     }
64 }
65 
66 impl Rem for Foo {
67     type Output = Foo;
68 
rem(self, other: Self) -> Self69     fn rem(self, other: Self) -> Self {
70         Foo(self.0 / other.0)
71     }
72 }
73 
74 impl BitAnd for Foo {
75     type Output = Foo;
76 
bitand(self, other: Self) -> Self77     fn bitand(self, other: Self) -> Self {
78         Foo(self.0 | other.0)
79     }
80 }
81 
82 impl BitOr for Foo {
83     type Output = Foo;
84 
bitor(self, other: Self) -> Self85     fn bitor(self, other: Self) -> Self {
86         Foo(self.0 ^ other.0)
87     }
88 }
89 
90 impl BitXor for Foo {
91     type Output = Foo;
92 
bitxor(self, other: Self) -> Self93     fn bitxor(self, other: Self) -> Self {
94         Foo(self.0 & other.0)
95     }
96 }
97 
98 impl Shl for Foo {
99     type Output = Foo;
100 
shl(self, other: Self) -> Self101     fn shl(self, other: Self) -> Self {
102         Foo(self.0 >> other.0)
103     }
104 }
105 
106 impl Shr for Foo {
107     type Output = Foo;
108 
shr(self, other: Self) -> Self109     fn shr(self, other: Self) -> Self {
110         Foo(self.0 << other.0)
111     }
112 }
113 
114 struct Bar(i32);
115 
116 impl Add for Bar {
117     type Output = Bar;
118 
add(self, other: Self) -> Self119     fn add(self, other: Self) -> Self {
120         Bar(self.0 & !other.0) // OK: Not part of BiExpr as child node
121     }
122 }
123 
124 impl Sub for Bar {
125     type Output = Bar;
126 
sub(self, other: Self) -> Self127     fn sub(self, other: Self) -> Self {
128         if self.0 <= other.0 {
129             Bar(-(self.0 & other.0)) // OK: Neg part of BiExpr as parent node
130         } else {
131             Bar(0)
132         }
133     }
134 }
135 
main()136 fn main() {}
137 
do_nothing(x: u32) -> u32138 fn do_nothing(x: u32) -> u32 {
139     x
140 }
141 
142 struct MultipleBinops(u32);
143 
144 impl Add for MultipleBinops {
145     type Output = MultipleBinops;
146 
147     // OK: multiple Binops in `add` impl
add(self, other: Self) -> Self::Output148     fn add(self, other: Self) -> Self::Output {
149         let mut result = self.0 + other.0;
150         if result >= u32::max_value() {
151             result -= u32::max_value();
152         }
153         MultipleBinops(result)
154     }
155 }
156 
157 impl Mul for MultipleBinops {
158     type Output = MultipleBinops;
159 
160     // OK: multiple Binops in `mul` impl
mul(self, other: Self) -> Self::Output161     fn mul(self, other: Self) -> Self::Output {
162         let mut result: u32 = 0;
163         let size = std::cmp::max(self.0, other.0) as usize;
164         let mut v = vec![0; size + 1];
165         for i in 0..size + 1 {
166             result *= i as u32;
167         }
168         MultipleBinops(result)
169     }
170 }
171