Skip to content

Commit 53a9805

Browse files
committed
Auto merge of rust-lang#5602 - ebroto:issue_3430, r=phansch
identity_op: allow `1 << 0` I went for accepting `1 << 0` verbatim instead of something more general as it seems to be what everyone in the issue thread needed. changelog: identity_op: allow `1 << 0` as it's a common pattern in bit manipulation code. Fixes rust-lang#3430
2 parents cac9ad0 + fc8ab09 commit 53a9805

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

clippy_lints/src/identity_op.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use rustc_hir::{BinOpKind, Expr, ExprKind};
1+
use if_chain::if_chain;
2+
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind};
23
use rustc_lint::{LateContext, LateLintPass};
34
use rustc_middle::ty;
45
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -32,7 +33,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
3233
if e.span.from_expansion() {
3334
return;
3435
}
35-
if let ExprKind::Binary(ref cmp, ref left, ref right) = e.kind {
36+
if let ExprKind::Binary(cmp, ref left, ref right) = e.kind {
37+
if is_allowed(cx, cmp, left, right) {
38+
return;
39+
}
3640
match cmp.node {
3741
BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
3842
check(cx, left, 0, e.span, right.span);
@@ -54,6 +58,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
5458
}
5559
}
5660

61+
fn is_allowed(cx: &LateContext<'_, '_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool {
62+
// `1 << 0` is a common pattern in bit manipulation code
63+
if_chain! {
64+
if let BinOpKind::Shl = cmp.node;
65+
if let Some(Constant::Int(0)) = constant_simple(cx, cx.tables, right);
66+
if let Some(Constant::Int(1)) = constant_simple(cx, cx.tables, left);
67+
then {
68+
return true;
69+
}
70+
}
71+
72+
false
73+
}
74+
5775
#[allow(clippy::cast_possible_wrap)]
5876
fn check(cx: &LateContext<'_, '_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) {
5977
if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) {

tests/ui/identity_op.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ fn main() {
3333

3434
let u: u8 = 0;
3535
u & 255;
36+
37+
1 << 0; // no error, this case is allowed, see issue 3430
38+
42 << 0;
39+
1 >> 0;
40+
42 >> 0;
3641
}

tests/ui/identity_op.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,23 @@ error: the operation is ineffective. Consider reducing it to `u`
4848
LL | u & 255;
4949
| ^^^^^^^
5050

51-
error: aborting due to 8 previous errors
51+
error: the operation is ineffective. Consider reducing it to `42`
52+
--> $DIR/identity_op.rs:38:5
53+
|
54+
LL | 42 << 0;
55+
| ^^^^^^^
56+
57+
error: the operation is ineffective. Consider reducing it to `1`
58+
--> $DIR/identity_op.rs:39:5
59+
|
60+
LL | 1 >> 0;
61+
| ^^^^^^
62+
63+
error: the operation is ineffective. Consider reducing it to `42`
64+
--> $DIR/identity_op.rs:40:5
65+
|
66+
LL | 42 >> 0;
67+
| ^^^^^^^
68+
69+
error: aborting due to 11 previous errors
5270

0 commit comments

Comments
 (0)