]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/assertions_on_constants.rs
Auto merge of #3744 - phansch:fix3144, r=oli-obk
[rust.git] / clippy_lints / src / assertions_on_constants.rs
1 use crate::consts::{constant, Constant};
2 use crate::rustc::hir::{Expr, ExprKind};
3 use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
4 use crate::rustc::{declare_tool_lint, lint_array};
5 use crate::syntax::ast::LitKind;
6 use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint};
7 use if_chain::if_chain;
8
9 /// **What it does:** Check to call assert!(true/false)
10 ///
11 /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
12 /// panic!() or unreachable!()
13 ///
14 /// **Known problems:** None
15 ///
16 /// **Example:**
17 /// ```rust
18 /// assert!(false)
19 /// // or
20 /// assert!(true)
21 /// // or
22 /// const B: bool = false;
23 /// assert!(B)
24 /// ```
25 declare_clippy_lint! {
26     pub ASSERTIONS_ON_CONSTANTS,
27     style,
28     "assert!(true/false) will be optimized out by the compiler/should probably be replaced by a panic!() or unreachable!()"
29 }
30
31 pub struct AssertionsOnConstants;
32
33 impl LintPass for AssertionsOnConstants {
34     fn get_lints(&self) -> LintArray {
35         lint_array![ASSERTIONS_ON_CONSTANTS]
36     }
37
38     fn name(&self) -> &'static str {
39         "AssertionsOnConstants"
40     }
41 }
42
43 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
44     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
45         if_chain! {
46             if let Some(assert_span) = is_direct_expn_of(e.span, "assert");
47             if !in_macro(assert_span)
48                 || is_direct_expn_of(assert_span, "debug_assert").map_or(false, |span| !in_macro(span));
49             if let ExprKind::Unary(_, ref lit) = e.node;
50             then {
51                 if let ExprKind::Lit(ref inner) = lit.node {
52                     match inner.node {
53                         LitKind::Bool(true) => {
54                             span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
55                                 "assert!(true) will be optimized out by the compiler",
56                                 "remove it");
57                         },
58                         LitKind::Bool(false) => {
59                             span_help_and_lint(
60                                 cx, ASSERTIONS_ON_CONSTANTS, e.span,
61                                 "assert!(false) should probably be replaced",
62                                 "use panic!() or unreachable!()");
63                         },
64                         _ => (),
65                     }
66                 } else if let Some(bool_const) = constant(cx, cx.tables, lit) {
67                     match bool_const.0 {
68                         Constant::Bool(true) => {
69                             span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
70                                 "assert!(const: true) will be optimized out by the compiler",
71                                 "remove it");
72                         },
73                         Constant::Bool(false) => {
74                             span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
75                                 "assert!(const: false) should probably be replaced",
76                                 "use panic!() or unreachable!()");
77                         },
78                         _ => (),
79                     }
80                 }
81             }
82         }
83     }
84 }