]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
Merge commit '5ff7b632a95bac6955611d85040859128902c580' into sync-rustfmt-subtree
[rust.git] / src / tools / clippy / 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     /// ### Known problems
18     /// None
19     ///
20     /// ### Example
21     /// ```rust,ignore
22     /// assert!(false)
23     /// assert!(true)
24     /// const B: bool = false;
25     /// assert!(B)
26     /// ```
27     #[clippy::version = "1.34.0"]
28     pub ASSERTIONS_ON_CONSTANTS,
29     style,
30     "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
31 }
32
33 declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);
34
35 impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
36     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
37         let Some(macro_call) = root_macro_call_first_node(cx, e) else { return };
38         let is_debug = match cx.tcx.get_diagnostic_name(macro_call.def_id) {
39             Some(sym::debug_assert_macro) => true,
40             Some(sym::assert_macro) => false,
41             _ => return,
42         };
43         let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return };
44         let Some((Constant::Bool(val), _)) = constant(cx, cx.typeck_results(), condition) else { return };
45         if val {
46             span_lint_and_help(
47                 cx,
48                 ASSERTIONS_ON_CONSTANTS,
49                 macro_call.span,
50                 &format!(
51                     "`{}!(true)` will be optimized out by the compiler",
52                     cx.tcx.item_name(macro_call.def_id)
53                 ),
54                 None,
55                 "remove it",
56             );
57         } else if !is_debug {
58             let (assert_arg, panic_arg) = match panic_expn {
59                 PanicExpn::Empty => ("", ""),
60                 _ => (", ..", ".."),
61             };
62             span_lint_and_help(
63                 cx,
64                 ASSERTIONS_ON_CONSTANTS,
65                 macro_call.span,
66                 &format!("`assert!(false{})` should probably be replaced", assert_arg),
67                 None,
68                 &format!("use `panic!({})` or `unreachable!({0})`", panic_arg),
69             );
70         }
71     }
72 }