From 98d24b5b5601d60f113ea14232416ce545f0cf73 Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 19 Aug 2015 09:07:50 +0200 Subject: [PATCH] fixed #203 and #197 --- src/bit_mask.rs | 40 ++++++++++++++++++++++++--------- tests/compile-fail/bit_masks.rs | 11 ++++++--- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index ec937dbab6c..7789381da23 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -39,7 +39,13 @@ declare_lint! { /// This lint is **deny** by default /// /// There is also a lint that warns on ineffective masks that is *warn* -/// by default +/// by default. +/// +/// |Comparison|Bit-Op |Example |equals |Formula| +/// |`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|`¹ && m <= c`| +/// |`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|`¹ && m < c` | +/// +/// `¹ power_of_two(c + 1)` #[derive(Copy,Clone)] pub struct BitMask; @@ -127,12 +133,10 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, "incompatible bit mask: `_ | {}` will never be lower than `{}`", mask_value, cmp_value)); } else { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: `x | {}` compared to `{}` is the same as x compared directly", - mask_value, cmp_value)); - } + check_ineffective_lt(cx, *span, mask_value, cmp_value, "|"); }, + BiBitXor => + check_ineffective_lt(cx, *span, mask_value, cmp_value, "^"), _ => () }, BiLe | BiGt => match bit_op { @@ -151,18 +155,32 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_, "incompatible bit mask: `_ | {}` will always be higher than `{}`", mask_value, cmp_value)); } else { - if mask_value < cmp_value { - span_lint(cx, INEFFECTIVE_BIT_MASK, *span, &format!( - "ineffective bit mask: `x | {}` compared to `{}` is the same as x compared directly", - mask_value, cmp_value)); - } + check_ineffective_gt(cx, *span, mask_value, cmp_value, "|"); }, + BiBitXor => + check_ineffective_gt(cx, *span, mask_value, cmp_value, "^"), _ => () }, _ => () } } +fn check_ineffective_lt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { + if c.is_power_of_two() && m < c { + span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( + "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, m, c)); + } +} + +fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) { + if (c + 1).is_power_of_two() && m <= c { + span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!( + "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly", + op, m, c)); + } +} + fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option { match &lit.node { &ExprLit(ref lit_ptr) => { diff --git a/tests/compile-fail/bit_masks.rs b/tests/compile-fail/bit_masks.rs index bcbfe99e42e..47e9c11138a 100755 --- a/tests/compile-fail/bit_masks.rs +++ b/tests/compile-fail/bit_masks.rs @@ -46,8 +46,13 @@ fn main() { fn ineffective() { let x = 5; - x | 1 > 2; //~ERROR ineffective bit mask - x | 1 < 3; //~ERROR ineffective bit mask + x | 1 > 3; //~ERROR ineffective bit mask + x | 1 < 4; //~ERROR ineffective bit mask x | 1 <= 3; //~ERROR ineffective bit mask - x | 1 >= 2; //~ERROR ineffective bit mask + x | 1 >= 8; //~ERROR ineffective bit mask + + x | 1 > 2; // not an error (yet), better written as x >= 2 + x | 1 >= 7; // not an error (yet), better written as x >= 6 + x | 3 > 4; // not an error (yet), better written as x >= 4 + x | 4 <= 19; }