]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/neg_multiply.rs
Improve docs
[rust.git] / clippy_lints / src / neg_multiply.rs
1 use rustc::hir::*;
2 use rustc::lint::*;
3 use syntax::codemap::{Span, Spanned};
4
5 use consts::{self, Constant};
6 use utils::span_lint;
7
8 /// **What it does:** Checks for multiplication by -1 as a form of negation.
9 ///
10 /// **Why is this bad?** It's more readable to just negate.
11 ///
12 /// **Known problems:** This only catches integers (for now)
13 ///
14 /// **Example:**
15 /// ```rust
16 /// x * -1
17 /// ```
18 declare_lint! {
19     pub NEG_MULTIPLY,
20     Warn,
21     "Warns on multiplying integers with -1"
22 }
23
24 #[derive(Copy, Clone)]
25 pub struct NegMultiply;
26
27 impl LintPass for NegMultiply {
28     fn get_lints(&self) -> LintArray {
29         lint_array!(NEG_MULTIPLY)
30     }
31 }
32
33 #[allow(match_same_arms)]
34 impl LateLintPass for NegMultiply {
35     fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
36         if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
37             match (&l.node, &r.node) {
38                 (&ExprUnary(..), &ExprUnary(..)) => (),
39                 (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
40                 (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
41                 _ => (),
42             }
43         }
44     }
45 }
46
47 fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
48     if_let_chain!([
49         let ExprLit(ref l) = lit.node,
50         let Constant::Int(ref ci) = consts::lit_to_constant(&l.node),
51         let Some(val) = ci.to_u64(),
52         val == 1,
53         cx.tcx.expr_ty(exp).is_integral()
54     ], {
55         span_lint(cx,
56                   NEG_MULTIPLY,
57                   span,
58                   "Negation by multiplying with -1");
59     })
60 }