]> git.lizzy.rs Git - rust.git/blob - src/identity_op.rs
Fix documentation
[rust.git] / src / identity_op.rs
1 use consts::{constant_simple, Constant};
2 use rustc::lint::*;
3 use rustc::hir::*;
4 use syntax::codemap::Span;
5 use utils::{span_lint, snippet, in_macro};
6 use rustc_const_math::ConstInt;
7
8 /// **What it does:** This lint checks for identity operations, e.g. `x + 0`.
9 ///
10 /// **Why is this bad?** This code can be removed without changing the meaning. So it just obscures what's going on. Delete it mercilessly.
11 ///
12 /// **Known problems:** None
13 ///
14 /// **Example:** `x / 1 + 0 * 1 - 0 | 0`
15 declare_lint! {
16     pub IDENTITY_OP, Warn,
17     "using identity operations, e.g. `x + 0` or `y / 1`"
18 }
19
20 #[derive(Copy,Clone)]
21 pub struct IdentityOp;
22
23 impl LintPass for IdentityOp {
24     fn get_lints(&self) -> LintArray {
25         lint_array!(IDENTITY_OP)
26     }
27 }
28
29 impl LateLintPass for IdentityOp {
30     fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
31         if in_macro(cx, e.span) {
32             return;
33         }
34         if let ExprBinary(ref cmp, ref left, ref right) = e.node {
35             match cmp.node {
36                 BiAdd | BiBitOr | BiBitXor => {
37                     check(cx, left, 0, e.span, right.span);
38                     check(cx, right, 0, e.span, left.span);
39                 }
40                 BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span),
41                 BiMul => {
42                     check(cx, left, 1, e.span, right.span);
43                     check(cx, right, 1, e.span, left.span);
44                 }
45                 BiDiv => check(cx, right, 1, e.span, left.span),
46                 BiBitAnd => {
47                     check(cx, left, -1, e.span, right.span);
48                     check(cx, right, -1, e.span, left.span);
49                 }
50                 _ => (),
51             }
52         }
53     }
54 }
55
56
57 fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
58     if let Some(v @ Constant::Int(_)) = constant_simple(e) {
59         if match m {
60             0 => v == Constant::Int(ConstInt::Infer(0)),
61             -1 => v == Constant::Int(ConstInt::InferSigned(-1)),
62             1 => v == Constant::Int(ConstInt::Infer(1)),
63             _ => unreachable!(),
64         } {
65             span_lint(cx,
66                       IDENTITY_OP,
67                       span,
68                       &format!("the operation is ineffective. Consider reducing it to `{}`",
69                                snippet(cx, arg, "..")));
70         }
71     }
72 }