]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/assertions_on_constants.rs
Auto merge of #102068 - cjgillot:erased-lifetime-print, r=eholk
[rust.git] / clippy_lints / src / assertions_on_constants.rs
1 use clippy_utils::consts::{constant, Constant};
2 use clippy_utils::diagnostics::span_lint_and_help;
3 use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
4 use rustc_hir::Expr;
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7 use rustc_span::sym;
8
9 declare_clippy_lint! {
10     /// ### What it does
11     /// Checks for `assert!(true)` and `assert!(false)` calls.
12     ///
13     /// ### Why is this bad?
14     /// Will be optimized out by the compiler or should probably be replaced by a
15     /// `panic!()` or `unreachable!()`
16     ///
17     /// ### Example
18     /// ```rust,ignore
19     /// assert!(false)
20     /// assert!(true)
21     /// const B: bool = false;
22     /// assert!(B)
23     /// ```
24     #[clippy::version = "1.34.0"]
25     pub ASSERTIONS_ON_CONSTANTS,
26     style,
27     "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
28 }
29
30 declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);
31
32 impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
33     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
34         let Some(macro_call) = root_macro_call_first_node(cx, e) else { return };
35         let is_debug = match cx.tcx.get_diagnostic_name(macro_call.def_id) {
36             Some(sym::debug_assert_macro) => true,
37             Some(sym::assert_macro) => false,
38             _ => return,
39         };
40         let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return };
41         let Some((Constant::Bool(val), _)) = constant(cx, cx.typeck_results(), condition) else { return };
42         if val {
43             span_lint_and_help(
44                 cx,
45                 ASSERTIONS_ON_CONSTANTS,
46                 macro_call.span,
47                 &format!(
48                     "`{}!(true)` will be optimized out by the compiler",
49                     cx.tcx.item_name(macro_call.def_id)
50                 ),
51                 None,
52                 "remove it",
53             );
54         } else if !is_debug {
55             let (assert_arg, panic_arg) = match panic_expn {
56                 PanicExpn::Empty => ("", ""),
57                 _ => (", ..", ".."),
58             };
59             span_lint_and_help(
60                 cx,
61                 ASSERTIONS_ON_CONSTANTS,
62                 macro_call.span,
63                 &format!("`assert!(false{})` should probably be replaced", assert_arg),
64                 None,
65                 &format!("use `panic!({})` or `unreachable!({0})`", panic_arg),
66             );
67         }
68     }
69 }