]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
New upstream version 1.56.0~beta.4+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / bool_assert_comparison.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::{ast_utils, is_direct_expn_of};
3 use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
4 use rustc_errors::Applicability;
5 use rustc_lint::{EarlyContext, EarlyLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7
8 declare_clippy_lint! {
9 /// ### What it does
10 /// This lint warns about boolean comparisons in assert-like macros.
11 ///
12 /// ### Why is this bad?
13 /// It is shorter to use the equivalent.
14 ///
15 /// ### Example
16 /// ```rust
17 /// // Bad
18 /// assert_eq!("a".is_empty(), false);
19 /// assert_ne!("a".is_empty(), true);
20 ///
21 /// // Good
22 /// assert!(!"a".is_empty());
23 /// ```
24 pub BOOL_ASSERT_COMPARISON,
25 style,
26 "Using a boolean as comparison value in an assert_* macro when there is no need"
27 }
28
29 declare_lint_pass!(BoolAssertComparison => [BOOL_ASSERT_COMPARISON]);
30
31 fn is_bool_lit(e: &Expr) -> bool {
32 matches!(
33 e.kind,
34 ExprKind::Lit(Lit {
35 kind: LitKind::Bool(_),
36 ..
37 })
38 ) && !e.span.from_expansion()
39 }
40
41 impl EarlyLintPass for BoolAssertComparison {
42 fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
43 let macros = ["assert_eq", "debug_assert_eq"];
44 let inverted_macros = ["assert_ne", "debug_assert_ne"];
45
46 for mac in macros.iter().chain(inverted_macros.iter()) {
47 if let Some(span) = is_direct_expn_of(e.span, mac) {
48 if let Some([a, b]) = ast_utils::extract_assert_macro_args(e) {
49 let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize;
50
51 if nb_bool_args != 1 {
52 // If there are two boolean arguments, we definitely don't understand
53 // what's going on, so better leave things as is...
54 //
55 // Or there is simply no boolean and then we can leave things as is!
56 return;
57 }
58
59 let non_eq_mac = &mac[..mac.len() - 3];
60 span_lint_and_sugg(
61 cx,
62 BOOL_ASSERT_COMPARISON,
63 span,
64 &format!("used `{}!` with a literal bool", mac),
65 "replace it with",
66 format!("{}!(..)", non_eq_mac),
67 Applicability::MaybeIncorrect,
68 );
69 return;
70 }
71 }
72 }
73 }
74 }