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}
;
10 /// This lint warns about boolean comparisons in assert-like macros.
12 /// ### Why is this bad?
13 /// It is shorter to use the equivalent.
18 /// assert_eq!("a".is_empty(), false);
19 /// assert_ne!("a".is_empty(), true);
22 /// assert!(!"a".is_empty());
24 pub BOOL_ASSERT_COMPARISON
,
26 "Using a boolean as comparison value in an assert_* macro when there is no need"
29 declare_lint_pass
!(BoolAssertComparison
=> [BOOL_ASSERT_COMPARISON
]);
31 fn is_bool_lit(e
: &Expr
) -> bool
{
35 kind
: LitKind
::Bool(_
),
38 ) && !e
.span
.from_expansion()
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"];
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;
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...
55 // Or there is simply no boolean and then we can leave things as is!
59 let non_eq_mac
= &mac
[..mac
.len() - 3];
62 BOOL_ASSERT_COMPARISON
,
64 &format
!("used `{}!` with a literal bool", mac
),
66 format
!("{}!(..)", non_eq_mac
),
67 Applicability
::MaybeIncorrect
,