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