Skip to content

Commit ecc61c7

Browse files
committed
Move NeedlessBitwiseBool into Operators lint pass
1 parent a2f186d commit ecc61c7

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
@@ -378,7 +378,6 @@ store.register_lints(&[
378378
mutex_atomic::MUTEX_ATOMIC,
379379
mutex_atomic::MUTEX_INTEGER,
380380
needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE,
381-
needless_bitwise_bool::NEEDLESS_BITWISE_BOOL,
382381
needless_bool::BOOL_COMPARISON,
383382
needless_bool::NEEDLESS_BOOL,
384383
needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
@@ -425,6 +424,7 @@ store.register_lints(&[
425424
operators::MISREFACTORED_ASSIGN_OP,
426425
operators::MODULO_ARITHMETIC,
427426
operators::MODULO_ONE,
427+
operators::NEEDLESS_BITWISE_BOOL,
428428
operators::OP_REF,
429429
operators::VERBOSE_BIT_MASK,
430430
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;
@@ -537,7 +536,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
537536
))
538537
});
539538
store.register_late_pass(|| Box::new(booleans::NonminimalBool));
540-
store.register_late_pass(|| Box::new(needless_bitwise_bool::NeedlessBitwiseBool));
541539
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
542540
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
543541
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;
@@ -640,6 +641,35 @@ declare_clippy_lint! {
640641
"any modulo arithmetic statement"
641642
}
642643

644+
declare_clippy_lint! {
645+
/// ### What it does
646+
/// Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using
647+
/// a lazy and.
648+
///
649+
/// ### Why is this bad?
650+
/// The bitwise operators do not support short-circuiting, so it may hinder code performance.
651+
/// Additionally, boolean logic "masked" as bitwise logic is not caught by lints like `unnecessary_fold`
652+
///
653+
/// ### Known problems
654+
/// This lint evaluates only when the right side is determined to have no side effects. At this time, that
655+
/// determination is quite conservative.
656+
///
657+
/// ### Example
658+
/// ```rust
659+
/// let (x,y) = (true, false);
660+
/// if x & !y {} // where both x and y are booleans
661+
/// ```
662+
/// Use instead:
663+
/// ```rust
664+
/// let (x,y) = (true, false);
665+
/// if x && !y {}
666+
/// ```
667+
#[clippy::version = "1.54.0"]
668+
pub NEEDLESS_BITWISE_BOOL,
669+
pedantic,
670+
"Boolean expressions that use bitwise rather than lazy operators"
671+
}
672+
643673
pub struct Operators {
644674
arithmetic_context: numeric_arithmetic::Context,
645675
verbose_bit_mask_threshold: u64,
@@ -667,6 +697,7 @@ impl_lint_pass!(Operators => [
667697
FLOAT_CMP_CONST,
668698
MODULO_ONE,
669699
MODULO_ARITHMETIC,
700+
NEEDLESS_BITWISE_BOOL,
670701
]);
671702
impl Operators {
672703
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
@@ -689,6 +720,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
689720
}
690721
erasing_op::check(cx, e, op.node, lhs, rhs);
691722
identity_op::check(cx, e, op.node, lhs, rhs);
723+
needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
692724
}
693725
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
694726
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)