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