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