Skip to content

Commit fc5eac5

Browse files
committed
Move NeedlessBitwiseBool into Operators lint pass
1 parent 71c2daa commit fc5eac5

File tree

6 files changed

+70
-89
lines changed

6 files changed

+70
-89
lines changed

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,6 @@ store.register_lints(&[
387387
mutex_atomic::MUTEX_ATOMIC,
388388
mutex_atomic::MUTEX_INTEGER,
389389
needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE,
390-
needless_bitwise_bool::NEEDLESS_BITWISE_BOOL,
391390
needless_bool::BOOL_COMPARISON,
392391
needless_bool::NEEDLESS_BOOL,
393392
needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
@@ -435,6 +434,7 @@ store.register_lints(&[
435434
operators::MISREFACTORED_ASSIGN_OP,
436435
operators::MODULO_ARITHMETIC,
437436
operators::MODULO_ONE,
437+
operators::NEEDLESS_BITWISE_BOOL,
438438
operators::OP_REF,
439439
operators::VERBOSE_BIT_MASK,
440440
option_env_unwrap::OPTION_ENV_UNWRAP,

clippy_lints/src/lib.register_pedantic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
6767
LintId::of(misc::USED_UNDERSCORE_BINDING),
6868
LintId::of(mismatching_type_param_order::MISMATCHING_TYPE_PARAM_ORDER),
6969
LintId::of(mut_mut::MUT_MUT),
70-
LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL),
7170
LintId::of(needless_continue::NEEDLESS_CONTINUE),
7271
LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
7372
LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
7473
LintId::of(no_effect::NO_EFFECT_UNDERSCORE_BINDING),
7574
LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
7675
LintId::of(non_expressive_names::SIMILAR_NAMES),
7776
LintId::of(operators::FLOAT_CMP),
77+
LintId::of(operators::NEEDLESS_BITWISE_BOOL),
7878
LintId::of(operators::VERBOSE_BIT_MASK),
7979
LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE),
8080
LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF),

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,6 @@ mod mut_reference;
302302
mod mutable_debug_assertion;
303303
mod mutex_atomic;
304304
mod needless_arbitrary_self_type;
305-
mod needless_bitwise_bool;
306305
mod needless_bool;
307306
mod needless_borrowed_ref;
308307
mod needless_continue;
@@ -569,7 +568,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
569568
))
570569
});
571570
store.register_late_pass(|| Box::new(booleans::NonminimalBool));
572-
store.register_late_pass(|| Box::new(needless_bitwise_bool::NeedlessBitwiseBool));
573571
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
574572
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
575573
store.register_late_pass(|| Box::new(ptr::Ptr));

clippy_lints/src/needless_bitwise_bool.rs

Lines changed: 0 additions & 85 deletions
This file was deleted.

clippy_lints/src/operators/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod integer_division;
1818
mod misrefactored_assign_op;
1919
mod modulo_arithmetic;
2020
mod modulo_one;
21+
mod needless_bitwise_bool;
2122
mod numeric_arithmetic;
2223
mod op_ref;
2324
mod verbose_bit_mask;
@@ -641,6 +642,35 @@ declare_clippy_lint! {
641642
"any modulo arithmetic statement"
642643
}
643644

645+
declare_clippy_lint! {
646+
/// ### What it does
647+
/// Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using
648+
/// a lazy and.
649+
///
650+
/// ### Why is this bad?
651+
/// The bitwise operators do not support short-circuiting, so it may hinder code performance.
652+
/// Additionally, boolean logic "masked" as bitwise logic is not caught by lints like `unnecessary_fold`
653+
///
654+
/// ### Known problems
655+
/// This lint evaluates only when the right side is determined to have no side effects. At this time, that
656+
/// determination is quite conservative.
657+
///
658+
/// ### Example
659+
/// ```rust
660+
/// let (x,y) = (true, false);
661+
/// if x & !y {} // where both x and y are booleans
662+
/// ```
663+
/// Use instead:
664+
/// ```rust
665+
/// let (x,y) = (true, false);
666+
/// if x && !y {}
667+
/// ```
668+
#[clippy::version = "1.54.0"]
669+
pub NEEDLESS_BITWISE_BOOL,
670+
pedantic,
671+
"Boolean expressions that use bitwise rather than lazy operators"
672+
}
673+
644674
pub struct Operators {
645675
arithmetic_context: numeric_arithmetic::Context,
646676
verbose_bit_mask_threshold: u64,
@@ -668,6 +698,7 @@ impl_lint_pass!(Operators => [
668698
FLOAT_CMP_CONST,
669699
MODULO_ONE,
670700
MODULO_ARITHMETIC,
701+
NEEDLESS_BITWISE_BOOL,
671702
]);
672703
impl Operators {
673704
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
@@ -690,6 +721,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
690721
}
691722
erasing_op::check(cx, e, op.node, lhs, rhs);
692723
identity_op::check(cx, e, op.node, lhs, rhs);
724+
needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
693725
}
694726
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
695727
bit_mask::check(cx, e, op.node, lhs, rhs);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::source::snippet_opt;
3+
use rustc_errors::Applicability;
4+
use rustc_hir::{BinOpKind, Expr, ExprKind};
5+
use rustc_lint::LateContext;
6+
7+
use super::NEEDLESS_BITWISE_BOOL;
8+
9+
pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) {
10+
let op_str = match op {
11+
BinOpKind::BitAnd => "&&",
12+
BinOpKind::BitOr => "||",
13+
_ => return,
14+
};
15+
if matches!(
16+
rhs.kind,
17+
ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Binary(..) | ExprKind::Unary(..)
18+
) && cx.typeck_results().expr_ty(e).is_bool()
19+
&& !rhs.can_have_side_effects()
20+
{
21+
span_lint_and_then(
22+
cx,
23+
NEEDLESS_BITWISE_BOOL,
24+
e.span,
25+
"use of bitwise operator instead of lazy operator between booleans",
26+
|diag| {
27+
if let Some(lhs_snip) = snippet_opt(cx, lhs.span)
28+
&& let Some(rhs_snip) = snippet_opt(cx, rhs.span)
29+
{
30+
let sugg = format!("{} {} {}", lhs_snip, op_str, rhs_snip);
31+
diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
32+
}
33+
},
34+
);
35+
}
36+
}

0 commit comments

Comments
 (0)