]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/neg_multiply.rs
fb986409a416ea9abb63da2b963d12318e2ba8a8
[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:** `x * -1`
15 declare_lint! {
16     pub NEG_MULTIPLY,
17     Warn,
18     "Warns on multiplying integers with -1"
19 }
20
21 #[derive(Copy, Clone)]
22 pub struct NegMultiply;
23
24 impl LintPass for NegMultiply {
25     fn get_lints(&self) -> LintArray {
26         lint_array!(NEG_MULTIPLY)
27     }
28 }
29
30 #[allow(match_same_arms)]
31 impl LateLintPass for NegMultiply {
32     fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
33         if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
34             match (&l.node, &r.node) {
35                 (&ExprUnary(..), &ExprUnary(..)) => (),
36                 (&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
37                 (_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
38                 _ => ()
39             }
40         }
41     }
42 }
43
44 fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
45     if_let_chain!([
46         let ExprLit(ref l) = lit.node,
47         let Constant::Int(ref ci) = consts::lit_to_constant(&l.node),
48         let Some(val) = ci.to_u64(),
49         val == 1,
50         cx.tcx.expr_ty(exp).is_integral()
51     ], {
52         span_lint(cx, 
53                   NEG_MULTIPLY,
54                   span,
55                   "Negation by multiplying with -1");
56     })
57 }