• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 mod absurd_extreme_comparisons;
2 mod assign_op_pattern;
3 mod bit_mask;
4 mod cmp_owned;
5 mod double_comparison;
6 mod duration_subsec;
7 mod eq_op;
8 mod erasing_op;
9 mod float_cmp;
10 mod float_equality_without_abs;
11 mod identity_op;
12 mod integer_division;
13 mod misrefactored_assign_op;
14 mod modulo_arithmetic;
15 mod modulo_one;
16 mod needless_bitwise_bool;
17 mod numeric_arithmetic;
18 mod op_ref;
19 mod ptr_eq;
20 mod self_assignment;
21 mod verbose_bit_mask;
22 
23 pub(crate) mod arithmetic_side_effects;
24 
25 use rustc_hir::{Body, Expr, ExprKind, UnOp};
26 use rustc_lint::{LateContext, LateLintPass};
27 use rustc_session::{declare_tool_lint, impl_lint_pass};
28 
29 declare_clippy_lint! {
30     /// ### What it does
31     /// Checks for comparisons where one side of the relation is
32     /// either the minimum or maximum value for its type and warns if it involves a
33     /// case that is always true or always false. Only integer and boolean types are
34     /// checked.
35     ///
36     /// ### Why is this bad?
37     /// An expression like `min <= x` may misleadingly imply
38     /// that it is possible for `x` to be less than the minimum. Expressions like
39     /// `max < x` are probably mistakes.
40     ///
41     /// ### Known problems
42     /// For `usize` the size of the current compile target will
43     /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such
44     /// a comparison to detect target pointer width will trigger this lint. One can
45     /// use `mem::sizeof` and compare its value or conditional compilation
46     /// attributes
47     /// like `#[cfg(target_pointer_width = "64")] ..` instead.
48     ///
49     /// ### Example
50     /// ```rust
51     /// let vec: Vec<isize> = Vec::new();
52     /// if vec.len() <= 0 {}
53     /// if 100 > i32::MAX {}
54     /// ```
55     #[clippy::version = "pre 1.29.0"]
56     pub ABSURD_EXTREME_COMPARISONS,
57     correctness,
58     "a comparison with a maximum or minimum value that is always true or false"
59 }
60 
61 declare_clippy_lint! {
62     /// ### What it does
63     /// Checks any kind of arithmetic operation of any type.
64     ///
65     /// Operators like `+`, `-`, `*` or `<<` are usually capable of overflowing according to the [Rust
66     /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
67     /// or can panic (`/`, `%`).
68     ///
69     /// Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant
70     /// environments, allowed types and non-constant operations that won't overflow are ignored.
71     ///
72     /// ### Why is this bad?
73     /// For integers, overflow will trigger a panic in debug builds or wrap the result in
74     /// release mode; division by zero will cause a panic in either mode. As a result, it is
75     /// desirable to explicitly call checked, wrapping or saturating arithmetic methods.
76     ///
77     /// #### Example
78     /// ```rust
79     /// // `n` can be any number, including `i32::MAX`.
80     /// fn foo(n: i32) -> i32 {
81     ///   n + 1
82     /// }
83     /// ```
84     ///
85     /// Third-party types can also overflow or present unwanted side-effects.
86     ///
87     /// #### Example
88     /// ```ignore,rust
89     /// use rust_decimal::Decimal;
90     /// let _n = Decimal::MAX + Decimal::MAX;
91     /// ```
92     #[clippy::version = "1.64.0"]
93     pub ARITHMETIC_SIDE_EFFECTS,
94     restriction,
95     "any arithmetic expression that can cause side effects like overflows or panics"
96 }
97 
98 declare_clippy_lint! {
99     /// ### What it does
100     /// Checks for float arithmetic.
101     ///
102     /// ### Why is this bad?
103     /// For some embedded systems or kernel development, it
104     /// can be useful to rule out floating-point numbers.
105     ///
106     /// ### Example
107     /// ```rust
108     /// # let a = 0.0;
109     /// a + 1.0;
110     /// ```
111     #[clippy::version = "pre 1.29.0"]
112     pub FLOAT_ARITHMETIC,
113     restriction,
114     "any floating-point arithmetic statement"
115 }
116 
117 declare_clippy_lint! {
118     /// ### What it does
119     /// Checks for `a = a op b` or `a = b commutative_op a`
120     /// patterns.
121     ///
122     /// ### Why is this bad?
123     /// These can be written as the shorter `a op= b`.
124     ///
125     /// ### Known problems
126     /// While forbidden by the spec, `OpAssign` traits may have
127     /// implementations that differ from the regular `Op` impl.
128     ///
129     /// ### Example
130     /// ```rust
131     /// let mut a = 5;
132     /// let b = 0;
133     /// // ...
134     ///
135     /// a = a + b;
136     /// ```
137     ///
138     /// Use instead:
139     /// ```rust
140     /// let mut a = 5;
141     /// let b = 0;
142     /// // ...
143     ///
144     /// a += b;
145     /// ```
146     #[clippy::version = "pre 1.29.0"]
147     pub ASSIGN_OP_PATTERN,
148     style,
149     "assigning the result of an operation on a variable to that same variable"
150 }
151 
152 declare_clippy_lint! {
153     /// ### What it does
154     /// Checks for `a op= a op b` or `a op= b op a` patterns.
155     ///
156     /// ### Why is this bad?
157     /// Most likely these are bugs where one meant to write `a
158     /// op= b`.
159     ///
160     /// ### Known problems
161     /// Clippy cannot know for sure if `a op= a op b` should have
162     /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both.
163     /// If `a op= a op b` is really the correct behavior it should be
164     /// written as `a = a op a op b` as it's less confusing.
165     ///
166     /// ### Example
167     /// ```rust
168     /// let mut a = 5;
169     /// let b = 2;
170     /// // ...
171     /// a += a + b;
172     /// ```
173     #[clippy::version = "pre 1.29.0"]
174     pub MISREFACTORED_ASSIGN_OP,
175     suspicious,
176     "having a variable on both sides of an assign op"
177 }
178 
179 declare_clippy_lint! {
180     /// ### What it does
181     /// Checks for incompatible bit masks in comparisons.
182     ///
183     /// The formula for detecting if an expression of the type `_ <bit_op> m
184     /// <cmp_op> c` (where `<bit_op>` is one of {`&`, `|`} and `<cmp_op>` is one of
185     /// {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following
186     /// table:
187     ///
188     /// |Comparison  |Bit Op|Example      |is always|Formula               |
189     /// |------------|------|-------------|---------|----------------------|
190     /// |`==` or `!=`| `&`  |`x & 2 == 3` |`false`  |`c & m != c`          |
191     /// |`<`  or `>=`| `&`  |`x & 2 < 3`  |`true`   |`m < c`               |
192     /// |`>`  or `<=`| `&`  |`x & 1 > 1`  |`false`  |`m <= c`              |
193     /// |`==` or `!=`| `\|` |`x \| 1 == 0`|`false`  |`c \| m != c`         |
194     /// |`<`  or `>=`| `\|` |`x \| 1 < 1` |`false`  |`m >= c`              |
195     /// |`<=` or `>` | `\|` |`x \| 1 > 0` |`true`   |`m > c`               |
196     ///
197     /// ### Why is this bad?
198     /// If the bits that the comparison cares about are always
199     /// set to zero or one by the bit mask, the comparison is constant `true` or
200     /// `false` (depending on mask, compared value, and operators).
201     ///
202     /// So the code is actively misleading, and the only reason someone would write
203     /// this intentionally is to win an underhanded Rust contest or create a
204     /// test-case for this lint.
205     ///
206     /// ### Example
207     /// ```rust
208     /// # let x = 1;
209     /// if (x & 1 == 2) { }
210     /// ```
211     #[clippy::version = "pre 1.29.0"]
212     pub BAD_BIT_MASK,
213     correctness,
214     "expressions of the form `_ & mask == select` that will only ever return `true` or `false`"
215 }
216 
217 declare_clippy_lint! {
218     /// ### What it does
219     /// Checks for bit masks in comparisons which can be removed
220     /// without changing the outcome. The basic structure can be seen in the
221     /// following table:
222     ///
223     /// |Comparison| Bit Op   |Example     |equals |
224     /// |----------|----------|------------|-------|
225     /// |`>` / `<=`|`\|` / `^`|`x \| 2 > 3`|`x > 3`|
226     /// |`<` / `>=`|`\|` / `^`|`x ^ 1 < 4` |`x < 4`|
227     ///
228     /// ### Why is this bad?
229     /// Not equally evil as [`bad_bit_mask`](#bad_bit_mask),
230     /// but still a bit misleading, because the bit mask is ineffective.
231     ///
232     /// ### Known problems
233     /// False negatives: This lint will only match instances
234     /// where we have figured out the math (which is for a power-of-two compared
235     /// value). This means things like `x | 1 >= 7` (which would be better written
236     /// as `x >= 6`) will not be reported (but bit masks like this are fairly
237     /// uncommon).
238     ///
239     /// ### Example
240     /// ```rust
241     /// # let x = 1;
242     /// if (x | 1 > 3) {  }
243     /// ```
244     #[clippy::version = "pre 1.29.0"]
245     pub INEFFECTIVE_BIT_MASK,
246     correctness,
247     "expressions where a bit mask will be rendered useless by a comparison, e.g., `(x | 1) > 2`"
248 }
249 
250 declare_clippy_lint! {
251     /// ### What it does
252     /// Checks for bit masks that can be replaced by a call
253     /// to `trailing_zeros`
254     ///
255     /// ### Why is this bad?
256     /// `x.trailing_zeros() > 4` is much clearer than `x & 15
257     /// == 0`
258     ///
259     /// ### Known problems
260     /// llvm generates better code for `x & 15 == 0` on x86
261     ///
262     /// ### Example
263     /// ```rust
264     /// # let x = 1;
265     /// if x & 0b1111 == 0 { }
266     /// ```
267     #[clippy::version = "pre 1.29.0"]
268     pub VERBOSE_BIT_MASK,
269     pedantic,
270     "expressions where a bit mask is less readable than the corresponding method call"
271 }
272 
273 declare_clippy_lint! {
274     /// ### What it does
275     /// Checks for double comparisons that could be simplified to a single expression.
276     ///
277     ///
278     /// ### Why is this bad?
279     /// Readability.
280     ///
281     /// ### Example
282     /// ```rust
283     /// # let x = 1;
284     /// # let y = 2;
285     /// if x == y || x < y {}
286     /// ```
287     ///
288     /// Use instead:
289     ///
290     /// ```rust
291     /// # let x = 1;
292     /// # let y = 2;
293     /// if x <= y {}
294     /// ```
295     #[clippy::version = "pre 1.29.0"]
296     pub DOUBLE_COMPARISONS,
297     complexity,
298     "unnecessary double comparisons that can be simplified"
299 }
300 
301 declare_clippy_lint! {
302     /// ### What it does
303     /// Checks for calculation of subsecond microseconds or milliseconds
304     /// from other `Duration` methods.
305     ///
306     /// ### Why is this bad?
307     /// It's more concise to call `Duration::subsec_micros()` or
308     /// `Duration::subsec_millis()` than to calculate them.
309     ///
310     /// ### Example
311     /// ```rust
312     /// # use std::time::Duration;
313     /// # let duration = Duration::new(5, 0);
314     /// let micros = duration.subsec_nanos() / 1_000;
315     /// let millis = duration.subsec_nanos() / 1_000_000;
316     /// ```
317     ///
318     /// Use instead:
319     /// ```rust
320     /// # use std::time::Duration;
321     /// # let duration = Duration::new(5, 0);
322     /// let micros = duration.subsec_micros();
323     /// let millis = duration.subsec_millis();
324     /// ```
325     #[clippy::version = "pre 1.29.0"]
326     pub DURATION_SUBSEC,
327     complexity,
328     "checks for calculation of subsecond microseconds or milliseconds"
329 }
330 
331 declare_clippy_lint! {
332     /// ### What it does
333     /// Checks for equal operands to comparison, logical and
334     /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`,
335     /// `||`, `&`, `|`, `^`, `-` and `/`).
336     ///
337     /// ### Why is this bad?
338     /// This is usually just a typo or a copy and paste error.
339     ///
340     /// ### Known problems
341     /// False negatives: We had some false positives regarding
342     /// calls (notably [racer](https://github.com/phildawes/racer) had one instance
343     /// of `x.pop() && x.pop()`), so we removed matching any function or method
344     /// calls. We may introduce a list of known pure functions in the future.
345     ///
346     /// ### Example
347     /// ```rust
348     /// # let x = 1;
349     /// if x + 1 == x + 1 {}
350     ///
351     /// // or
352     ///
353     /// # let a = 3;
354     /// # let b = 4;
355     /// assert_eq!(a, a);
356     /// ```
357     #[clippy::version = "pre 1.29.0"]
358     pub EQ_OP,
359     correctness,
360     "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)"
361 }
362 
363 declare_clippy_lint! {
364     /// ### What it does
365     /// Checks for arguments to `==` which have their address
366     /// taken to satisfy a bound
367     /// and suggests to dereference the other argument instead
368     ///
369     /// ### Why is this bad?
370     /// It is more idiomatic to dereference the other argument.
371     ///
372     /// ### Example
373     /// ```rust,ignore
374     /// &x == y
375     /// ```
376     ///
377     /// Use instead:
378     /// ```rust,ignore
379     /// x == *y
380     /// ```
381     #[clippy::version = "pre 1.29.0"]
382     pub OP_REF,
383     style,
384     "taking a reference to satisfy the type constraints on `==`"
385 }
386 
387 declare_clippy_lint! {
388     /// ### What it does
389     /// Checks for erasing operations, e.g., `x * 0`.
390     ///
391     /// ### Why is this bad?
392     /// The whole expression can be replaced by zero.
393     /// This is most likely not the intended outcome and should probably be
394     /// corrected
395     ///
396     /// ### Example
397     /// ```rust
398     /// let x = 1;
399     /// 0 / x;
400     /// 0 * x;
401     /// x & 0;
402     /// ```
403     #[clippy::version = "pre 1.29.0"]
404     pub ERASING_OP,
405     correctness,
406     "using erasing operations, e.g., `x * 0` or `y & 0`"
407 }
408 
409 declare_clippy_lint! {
410     /// ### What it does
411     /// Checks for statements of the form `(a - b) < f32::EPSILON` or
412     /// `(a - b) < f64::EPSILON`. Notes the missing `.abs()`.
413     ///
414     /// ### Why is this bad?
415     /// The code without `.abs()` is more likely to have a bug.
416     ///
417     /// ### Known problems
418     /// If the user can ensure that b is larger than a, the `.abs()` is
419     /// technically unnecessary. However, it will make the code more robust and doesn't have any
420     /// large performance implications. If the abs call was deliberately left out for performance
421     /// reasons, it is probably better to state this explicitly in the code, which then can be done
422     /// with an allow.
423     ///
424     /// ### Example
425     /// ```rust
426     /// pub fn is_roughly_equal(a: f32, b: f32) -> bool {
427     ///     (a - b) < f32::EPSILON
428     /// }
429     /// ```
430     /// Use instead:
431     /// ```rust
432     /// pub fn is_roughly_equal(a: f32, b: f32) -> bool {
433     ///     (a - b).abs() < f32::EPSILON
434     /// }
435     /// ```
436     #[clippy::version = "1.48.0"]
437     pub FLOAT_EQUALITY_WITHOUT_ABS,
438     suspicious,
439     "float equality check without `.abs()`"
440 }
441 
442 declare_clippy_lint! {
443     /// ### What it does
444     /// Checks for identity operations, e.g., `x + 0`.
445     ///
446     /// ### Why is this bad?
447     /// This code can be removed without changing the
448     /// meaning. So it just obscures what's going on. Delete it mercilessly.
449     ///
450     /// ### Example
451     /// ```rust
452     /// # let x = 1;
453     /// x / 1 + 0 * 1 - 0 | 0;
454     /// ```
455     #[clippy::version = "pre 1.29.0"]
456     pub IDENTITY_OP,
457     complexity,
458     "using identity operations, e.g., `x + 0` or `y / 1`"
459 }
460 
461 declare_clippy_lint! {
462     /// ### What it does
463     /// Checks for division of integers
464     ///
465     /// ### Why is this bad?
466     /// When outside of some very specific algorithms,
467     /// integer division is very often a mistake because it discards the
468     /// remainder.
469     ///
470     /// ### Example
471     /// ```rust
472     /// let x = 3 / 2;
473     /// println!("{}", x);
474     /// ```
475     ///
476     /// Use instead:
477     /// ```rust
478     /// let x = 3f32 / 2f32;
479     /// println!("{}", x);
480     /// ```
481     #[clippy::version = "1.37.0"]
482     pub INTEGER_DIVISION,
483     restriction,
484     "integer division may cause loss of precision"
485 }
486 
487 declare_clippy_lint! {
488     /// ### What it does
489     /// Checks for conversions to owned values just for the sake
490     /// of a comparison.
491     ///
492     /// ### Why is this bad?
493     /// The comparison can operate on a reference, so creating
494     /// an owned value effectively throws it away directly afterwards, which is
495     /// needlessly consuming code and heap space.
496     ///
497     /// ### Example
498     /// ```rust
499     /// # let x = "foo";
500     /// # let y = String::from("foo");
501     /// if x.to_owned() == y {}
502     /// ```
503     ///
504     /// Use instead:
505     /// ```rust
506     /// # let x = "foo";
507     /// # let y = String::from("foo");
508     /// if x == y {}
509     /// ```
510     #[clippy::version = "pre 1.29.0"]
511     pub CMP_OWNED,
512     perf,
513     "creating owned instances for comparing with others, e.g., `x == \"foo\".to_string()`"
514 }
515 
516 declare_clippy_lint! {
517     /// ### What it does
518     /// Checks for (in-)equality comparisons on floating-point
519     /// values (apart from zero), except in functions called `*eq*` (which probably
520     /// implement equality for a type involving floats).
521     ///
522     /// ### Why is this bad?
523     /// Floating point calculations are usually imprecise, so
524     /// asking if two values are *exactly* equal is asking for trouble. For a good
525     /// guide on what to do, see [the floating point
526     /// guide](http://www.floating-point-gui.de/errors/comparison).
527     ///
528     /// ### Example
529     /// ```rust
530     /// let x = 1.2331f64;
531     /// let y = 1.2332f64;
532     ///
533     /// if y == 1.23f64 { }
534     /// if y != x {} // where both are floats
535     /// ```
536     ///
537     /// Use instead:
538     /// ```rust
539     /// # let x = 1.2331f64;
540     /// # let y = 1.2332f64;
541     /// let error_margin = f64::EPSILON; // Use an epsilon for comparison
542     /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead.
543     /// // let error_margin = std::f64::EPSILON;
544     /// if (y - 1.23f64).abs() < error_margin { }
545     /// if (y - x).abs() > error_margin { }
546     /// ```
547     #[clippy::version = "pre 1.29.0"]
548     pub FLOAT_CMP,
549     pedantic,
550     "using `==` or `!=` on float values instead of comparing difference with an epsilon"
551 }
552 
553 declare_clippy_lint! {
554     /// ### What it does
555     /// Checks for (in-)equality comparisons on floating-point
556     /// value and constant, except in functions called `*eq*` (which probably
557     /// implement equality for a type involving floats).
558     ///
559     /// ### Why is this bad?
560     /// Floating point calculations are usually imprecise, so
561     /// asking if two values are *exactly* equal is asking for trouble. For a good
562     /// guide on what to do, see [the floating point
563     /// guide](http://www.floating-point-gui.de/errors/comparison).
564     ///
565     /// ### Example
566     /// ```rust
567     /// let x: f64 = 1.0;
568     /// const ONE: f64 = 1.00;
569     ///
570     /// if x == ONE { } // where both are floats
571     /// ```
572     ///
573     /// Use instead:
574     /// ```rust
575     /// # let x: f64 = 1.0;
576     /// # const ONE: f64 = 1.00;
577     /// let error_margin = f64::EPSILON; // Use an epsilon for comparison
578     /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead.
579     /// // let error_margin = std::f64::EPSILON;
580     /// if (x - ONE).abs() < error_margin { }
581     /// ```
582     #[clippy::version = "pre 1.29.0"]
583     pub FLOAT_CMP_CONST,
584     restriction,
585     "using `==` or `!=` on float constants instead of comparing difference with an epsilon"
586 }
587 
588 declare_clippy_lint! {
589     /// ### What it does
590     /// Checks for getting the remainder of a division by one or minus
591     /// one.
592     ///
593     /// ### Why is this bad?
594     /// The result for a divisor of one can only ever be zero; for
595     /// minus one it can cause panic/overflow (if the left operand is the minimal value of
596     /// the respective integer type) or results in zero. No one will write such code
597     /// deliberately, unless trying to win an Underhanded Rust Contest. Even for that
598     /// contest, it's probably a bad idea. Use something more underhanded.
599     ///
600     /// ### Example
601     /// ```rust
602     /// # let x = 1;
603     /// let a = x % 1;
604     /// let a = x % -1;
605     /// ```
606     #[clippy::version = "pre 1.29.0"]
607     pub MODULO_ONE,
608     correctness,
609     "taking a number modulo +/-1, which can either panic/overflow or always returns 0"
610 }
611 
612 declare_clippy_lint! {
613     /// ### What it does
614     /// Checks for modulo arithmetic.
615     ///
616     /// ### Why is this bad?
617     /// The results of modulo (%) operation might differ
618     /// depending on the language, when negative numbers are involved.
619     /// If you interop with different languages it might be beneficial
620     /// to double check all places that use modulo arithmetic.
621     ///
622     /// For example, in Rust `17 % -3 = 2`, but in Python `17 % -3 = -1`.
623     ///
624     /// ### Example
625     /// ```rust
626     /// let x = -17 % 3;
627     /// ```
628     #[clippy::version = "1.42.0"]
629     pub MODULO_ARITHMETIC,
630     restriction,
631     "any modulo arithmetic statement"
632 }
633 
634 declare_clippy_lint! {
635     /// ### What it does
636     /// Checks for usage of bitwise and/or operators between booleans, where performance may be improved by using
637     /// a lazy and.
638     ///
639     /// ### Why is this bad?
640     /// The bitwise operators do not support short-circuiting, so it may hinder code performance.
641     /// Additionally, boolean logic "masked" as bitwise logic is not caught by lints like `unnecessary_fold`
642     ///
643     /// ### Known problems
644     /// This lint evaluates only when the right side is determined to have no side effects. At this time, that
645     /// determination is quite conservative.
646     ///
647     /// ### Example
648     /// ```rust
649     /// let (x,y) = (true, false);
650     /// if x & !y {} // where both x and y are booleans
651     /// ```
652     /// Use instead:
653     /// ```rust
654     /// let (x,y) = (true, false);
655     /// if x && !y {}
656     /// ```
657     #[clippy::version = "1.54.0"]
658     pub NEEDLESS_BITWISE_BOOL,
659     pedantic,
660     "Boolean expressions that use bitwise rather than lazy operators"
661 }
662 
663 declare_clippy_lint! {
664     /// ### What it does
665     /// Use `std::ptr::eq` when applicable
666     ///
667     /// ### Why is this bad?
668     /// `ptr::eq` can be used to compare `&T` references
669     /// (which coerce to `*const T` implicitly) by their address rather than
670     /// comparing the values they point to.
671     ///
672     /// ### Example
673     /// ```rust
674     /// let a = &[1, 2, 3];
675     /// let b = &[1, 2, 3];
676     ///
677     /// assert!(a as *const _ as usize == b as *const _ as usize);
678     /// ```
679     /// Use instead:
680     /// ```rust
681     /// let a = &[1, 2, 3];
682     /// let b = &[1, 2, 3];
683     ///
684     /// assert!(std::ptr::eq(a, b));
685     /// ```
686     #[clippy::version = "1.49.0"]
687     pub PTR_EQ,
688     style,
689     "use `std::ptr::eq` when comparing raw pointers"
690 }
691 
692 declare_clippy_lint! {
693     /// ### What it does
694     /// Checks for explicit self-assignments.
695     ///
696     /// ### Why is this bad?
697     /// Self-assignments are redundant and unlikely to be
698     /// intentional.
699     ///
700     /// ### Known problems
701     /// If expression contains any deref coercions or
702     /// indexing operations they are assumed not to have any side effects.
703     ///
704     /// ### Example
705     /// ```rust
706     /// struct Event {
707     ///     x: i32,
708     /// }
709     ///
710     /// fn copy_position(a: &mut Event, b: &Event) {
711     ///     a.x = a.x;
712     /// }
713     /// ```
714     ///
715     /// Should be:
716     /// ```rust
717     /// struct Event {
718     ///     x: i32,
719     /// }
720     ///
721     /// fn copy_position(a: &mut Event, b: &Event) {
722     ///     a.x = b.x;
723     /// }
724     /// ```
725     #[clippy::version = "1.48.0"]
726     pub SELF_ASSIGNMENT,
727     correctness,
728     "explicit self-assignment"
729 }
730 
731 pub struct Operators {
732     arithmetic_context: numeric_arithmetic::Context,
733     verbose_bit_mask_threshold: u64,
734 }
735 impl_lint_pass!(Operators => [
736     ABSURD_EXTREME_COMPARISONS,
737     ARITHMETIC_SIDE_EFFECTS,
738     FLOAT_ARITHMETIC,
739     ASSIGN_OP_PATTERN,
740     MISREFACTORED_ASSIGN_OP,
741     BAD_BIT_MASK,
742     INEFFECTIVE_BIT_MASK,
743     VERBOSE_BIT_MASK,
744     DOUBLE_COMPARISONS,
745     DURATION_SUBSEC,
746     EQ_OP,
747     OP_REF,
748     ERASING_OP,
749     FLOAT_EQUALITY_WITHOUT_ABS,
750     IDENTITY_OP,
751     INTEGER_DIVISION,
752     CMP_OWNED,
753     FLOAT_CMP,
754     FLOAT_CMP_CONST,
755     MODULO_ONE,
756     MODULO_ARITHMETIC,
757     NEEDLESS_BITWISE_BOOL,
758     PTR_EQ,
759     SELF_ASSIGNMENT,
760 ]);
761 impl Operators {
new(verbose_bit_mask_threshold: u64) -> Self762     pub fn new(verbose_bit_mask_threshold: u64) -> Self {
763         Self {
764             arithmetic_context: numeric_arithmetic::Context::default(),
765             verbose_bit_mask_threshold,
766         }
767     }
768 }
769 impl<'tcx> LateLintPass<'tcx> for Operators {
check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>)770     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
771         eq_op::check_assert(cx, e);
772         match e.kind {
773             ExprKind::Binary(op, lhs, rhs) => {
774                 if !e.span.from_expansion() {
775                     absurd_extreme_comparisons::check(cx, e, op.node, lhs, rhs);
776                     if !(macro_with_not_op(lhs) || macro_with_not_op(rhs)) {
777                         eq_op::check(cx, e, op.node, lhs, rhs);
778                         op_ref::check(cx, e, op.node, lhs, rhs);
779                     }
780                     erasing_op::check(cx, e, op.node, lhs, rhs);
781                     identity_op::check(cx, e, op.node, lhs, rhs);
782                     needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
783                     ptr_eq::check(cx, e, op.node, lhs, rhs);
784                 }
785                 self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
786                 bit_mask::check(cx, e, op.node, lhs, rhs);
787                 verbose_bit_mask::check(cx, e, op.node, lhs, rhs, self.verbose_bit_mask_threshold);
788                 double_comparison::check(cx, op.node, lhs, rhs, e.span);
789                 duration_subsec::check(cx, e, op.node, lhs, rhs);
790                 float_equality_without_abs::check(cx, e, op.node, lhs, rhs);
791                 integer_division::check(cx, e, op.node, lhs, rhs);
792                 cmp_owned::check(cx, op.node, lhs, rhs);
793                 float_cmp::check(cx, e, op.node, lhs, rhs);
794                 modulo_one::check(cx, e, op.node, rhs);
795                 modulo_arithmetic::check(cx, e, op.node, lhs, rhs);
796             },
797             ExprKind::AssignOp(op, lhs, rhs) => {
798                 self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
799                 misrefactored_assign_op::check(cx, e, op.node, lhs, rhs);
800                 modulo_arithmetic::check(cx, e, op.node, lhs, rhs);
801             },
802             ExprKind::Assign(lhs, rhs, _) => {
803                 assign_op_pattern::check(cx, e, lhs, rhs);
804                 self_assignment::check(cx, e, lhs, rhs);
805             },
806             ExprKind::Unary(op, arg) => {
807                 if op == UnOp::Neg {
808                     self.arithmetic_context.check_negate(cx, e, arg);
809                 }
810             },
811             _ => (),
812         }
813     }
814 
check_expr_post(&mut self, _: &LateContext<'_>, e: &Expr<'_>)815     fn check_expr_post(&mut self, _: &LateContext<'_>, e: &Expr<'_>) {
816         self.arithmetic_context.expr_post(e.hir_id);
817     }
818 
check_body(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>)819     fn check_body(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>) {
820         self.arithmetic_context.enter_body(cx, b);
821     }
822 
check_body_post(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>)823     fn check_body_post(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>) {
824         self.arithmetic_context.body_post(cx, b);
825     }
826 }
827 
macro_with_not_op(e: &Expr<'_>) -> bool828 fn macro_with_not_op(e: &Expr<'_>) -> bool {
829     if let ExprKind::Unary(_, e) = e.kind {
830         e.span.from_expansion()
831     } else {
832         false
833     }
834 }
835