Added 'ineffective bit mask' lint
This commit is contained in:
parent
905509083c
commit
6bec4f35df
@ -13,6 +13,7 @@ Lints included in this crate:
|
||||
- `toplevel_ref_arg`: Warns when a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not `fn foo((ref x, ref y): (u8, u8))`)
|
||||
- `eq_op`: Warns on equal operands on both sides of a comparison or bitwise combination
|
||||
- `bad_bit_mask`: Denies expressions of the form `_ & mask == select` that will only ever return `true` or `false` (because in the example `select` containing bits that `mask` doesn't have)
|
||||
- `ineffective_bit_mask`: Warns on expressions where a bit mask will be rendered useless by a comparison, e.g. `(x | 1) > 2`
|
||||
- `needless_bool` : Warns on if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`
|
||||
- `ptr_arg`: Warns on fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively
|
||||
- `approx_constant`: Warns if the approximate of a known float constant (in `std::f64::consts` or `std::f32::consts`) is found and suggests to use the constant
|
||||
|
@ -32,12 +32,18 @@ declare_lint! {
|
||||
"Deny the use of incompatible bit masks in comparisons, e.g. '(a & 1) == 2'"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub INEFFECTIVE_BIT_MASK,
|
||||
Warn,
|
||||
"Warn on the use of an ineffective bit mask in comparisons, e.g. '(a & 1) > 2'"
|
||||
}
|
||||
|
||||
#[derive(Copy,Clone)]
|
||||
pub struct BitMask;
|
||||
|
||||
impl LintPass for BitMask {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(BAD_BIT_MASK)
|
||||
lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK)
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &Context, e: &Expr) {
|
||||
@ -102,31 +108,47 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64,
|
||||
},
|
||||
BiLt | BiGe => match bit_op {
|
||||
BiBitAnd => if mask_value < cmp_value {
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will always be lower than {}", mask_value,
|
||||
cmp_value));
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!(
|
||||
"incompatible bit mask: _ & {} will always be lower than {}",
|
||||
mask_value, cmp_value));
|
||||
} else {
|
||||
if mask_value == 0 {
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero"));
|
||||
}
|
||||
},
|
||||
BiBitOr => if mask_value >= cmp_value {
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will never be lower than {}", mask_value,
|
||||
cmp_value));
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!(
|
||||
"incompatible bit mask: _ | {} will never be lower than {}",
|
||||
mask_value, cmp_value));
|
||||
} else {
|
||||
if mask_value < cmp_value {
|
||||
cx.span_lint(INEFFECTIVE_BIT_MASK, *span, &format!(
|
||||
"ineffective bit mask: x | {} compared to {} is the same as x compared directly",
|
||||
mask_value, cmp_value));
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
BiLe | BiGt => match bit_op {
|
||||
BiBitAnd => if mask_value <= cmp_value {
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ & {} will never be higher than {}", mask_value,
|
||||
cmp_value));
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!(
|
||||
"incompatible bit mask: _ & {} will never be higher than {}",
|
||||
mask_value, cmp_value));
|
||||
} else {
|
||||
if mask_value == 0 {
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!("&-masking with zero"));
|
||||
}
|
||||
},
|
||||
BiBitOr => if mask_value > cmp_value {
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!("incompatible bit mask: _ | {} will always be higher than {}", mask_value,
|
||||
cmp_value));
|
||||
cx.span_lint(BAD_BIT_MASK, *span, &format!(
|
||||
"incompatible bit mask: _ | {} will always be higher than {}",
|
||||
mask_value, cmp_value));
|
||||
} else {
|
||||
if mask_value < cmp_value {
|
||||
cx.span_lint(INEFFECTIVE_BIT_MASK, *span, &format!(
|
||||
"ineffective bit mask: x | {} compared to {} is the same as x compared directly",
|
||||
mask_value, cmp_value));
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
|
@ -42,7 +42,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST,
|
||||
misc::SINGLE_MATCH, misc::STR_TO_STRING,
|
||||
misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP,
|
||||
bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG,
|
||||
bit_mask::BAD_BIT_MASK,
|
||||
bit_mask::INEFFECTIVE_BIT_MASK,
|
||||
ptr_arg::PTR_ARG,
|
||||
needless_bool::NEEDLESS_BOOL,
|
||||
approx_const::APPROX_CONSTANT,
|
||||
misc::CMP_NAN, misc::FLOAT_CMP,
|
||||
|
@ -5,6 +5,7 @@ const THREE_BITS : i64 = 7;
|
||||
const EVEN_MORE_REDIRECTION : i64 = THREE_BITS;
|
||||
|
||||
#[deny(bad_bit_mask)]
|
||||
#[allow(ineffective_bit_mask)]
|
||||
fn main() {
|
||||
let x = 5;
|
||||
|
||||
@ -34,4 +35,18 @@ fn main() {
|
||||
1 < 2 | x; //~ERROR
|
||||
2 == 3 | x; //~ERROR
|
||||
1 == x & 2; //~ERROR
|
||||
|
||||
x | 1 > 2; // no error, because we allowed ineffective bit masks
|
||||
ineffective();
|
||||
}
|
||||
|
||||
#[deny(ineffective_bit_mask)]
|
||||
#[allow(bad_bit_mask)]
|
||||
fn ineffective() {
|
||||
let x = 5;
|
||||
|
||||
x | 1 > 2; //~ERROR
|
||||
x | 1 < 3; //~ERROR
|
||||
x | 1 <= 3; //~ERROR
|
||||
x | 1 >= 2; //~ERROR
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user