Skip to content

Commit 16ef044

Browse files
committed
Auto merge of #8183 - alex-ozdemir:limit-ident, r=camsteffen
Limit the ``[`identity_op`]`` lint to integral operands. changelog: limit ``[`identity_op`]`` to integral operands In the ``[`identity_op`]`` lint, if the operands are non-integers, then the lint is likely wrong.
2 parents a139949 + ee6d5c5 commit 16ef044

File tree

4 files changed

+56
-18
lines changed

4 files changed

+56
-18
lines changed

clippy_lints/src/identity_op.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,18 @@ impl<'tcx> LateLintPass<'tcx> for IdentityOp {
6161
}
6262

6363
fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool {
64-
// `1 << 0` is a common pattern in bit manipulation code
65-
cmp.node == BinOpKind::Shl
66-
&& constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0))
67-
&& constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1))
64+
// This lint applies to integers
65+
!cx.typeck_results().expr_ty(left).peel_refs().is_integral()
66+
|| !cx.typeck_results().expr_ty(right).peel_refs().is_integral()
67+
// `1 << 0` is a common pattern in bit manipulation code
68+
|| (cmp.node == BinOpKind::Shl
69+
&& constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0))
70+
&& constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1)))
6871
}
6972

7073
fn check(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) {
71-
if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e) {
72-
let check = match *cx.typeck_results().expr_ty(e).kind() {
74+
if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) {
75+
let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() {
7376
ty::Int(ity) => unsext(cx.tcx, -1_i128, ity),
7477
ty::Uint(uty) => clip(cx.tcx, !0, uty),
7578
_ => return,

clippy_utils/src/consts.rs

+8
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ impl Constant {
168168
None
169169
}
170170
}
171+
172+
#[must_use]
173+
pub fn peel_refs(mut self) -> Self {
174+
while let Constant::Ref(r) = self {
175+
self = *r;
176+
}
177+
self
178+
}
171179
}
172180

173181
/// Parses a `LitKind` to a `Constant`.

tests/ui/identity_op.rs

+15
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@ const ONE: i64 = 1;
22
const NEG_ONE: i64 = -1;
33
const ZERO: i64 = 0;
44

5+
struct A(String);
6+
7+
impl std::ops::Shl<i32> for A {
8+
type Output = A;
9+
fn shl(mut self, other: i32) -> Self {
10+
self.0.push_str(&format!("{}", other));
11+
self
12+
}
13+
}
514
#[allow(
615
clippy::eq_op,
716
clippy::no_effect,
817
clippy::unnecessary_operation,
18+
clippy::op_ref,
919
clippy::double_parens
1020
)]
1121
#[warn(clippy::identity_op)]
@@ -38,4 +48,9 @@ fn main() {
3848
42 << 0;
3949
1 >> 0;
4050
42 >> 0;
51+
&x >> 0;
52+
x >> &0;
53+
54+
let mut a = A("".into());
55+
let b = a << 0; // no error: non-integer
4156
}

tests/ui/identity_op.stderr

+24-12
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,82 @@
11
error: the operation is ineffective. Consider reducing it to `x`
2-
--> $DIR/identity_op.rs:16:5
2+
--> $DIR/identity_op.rs:26:5
33
|
44
LL | x + 0;
55
| ^^^^^
66
|
77
= note: `-D clippy::identity-op` implied by `-D warnings`
88

99
error: the operation is ineffective. Consider reducing it to `x`
10-
--> $DIR/identity_op.rs:17:5
10+
--> $DIR/identity_op.rs:27:5
1111
|
1212
LL | x + (1 - 1);
1313
| ^^^^^^^^^^^
1414

1515
error: the operation is ineffective. Consider reducing it to `x`
16-
--> $DIR/identity_op.rs:19:5
16+
--> $DIR/identity_op.rs:29:5
1717
|
1818
LL | 0 + x;
1919
| ^^^^^
2020

2121
error: the operation is ineffective. Consider reducing it to `x`
22-
--> $DIR/identity_op.rs:22:5
22+
--> $DIR/identity_op.rs:32:5
2323
|
2424
LL | x | (0);
2525
| ^^^^^^^
2626

2727
error: the operation is ineffective. Consider reducing it to `x`
28-
--> $DIR/identity_op.rs:25:5
28+
--> $DIR/identity_op.rs:35:5
2929
|
3030
LL | x * 1;
3131
| ^^^^^
3232

3333
error: the operation is ineffective. Consider reducing it to `x`
34-
--> $DIR/identity_op.rs:26:5
34+
--> $DIR/identity_op.rs:36:5
3535
|
3636
LL | 1 * x;
3737
| ^^^^^
3838

3939
error: the operation is ineffective. Consider reducing it to `x`
40-
--> $DIR/identity_op.rs:32:5
40+
--> $DIR/identity_op.rs:42:5
4141
|
4242
LL | -1 & x;
4343
| ^^^^^^
4444

4545
error: the operation is ineffective. Consider reducing it to `u`
46-
--> $DIR/identity_op.rs:35:5
46+
--> $DIR/identity_op.rs:45:5
4747
|
4848
LL | u & 255;
4949
| ^^^^^^^
5050

5151
error: the operation is ineffective. Consider reducing it to `42`
52-
--> $DIR/identity_op.rs:38:5
52+
--> $DIR/identity_op.rs:48:5
5353
|
5454
LL | 42 << 0;
5555
| ^^^^^^^
5656

5757
error: the operation is ineffective. Consider reducing it to `1`
58-
--> $DIR/identity_op.rs:39:5
58+
--> $DIR/identity_op.rs:49:5
5959
|
6060
LL | 1 >> 0;
6161
| ^^^^^^
6262

6363
error: the operation is ineffective. Consider reducing it to `42`
64-
--> $DIR/identity_op.rs:40:5
64+
--> $DIR/identity_op.rs:50:5
6565
|
6666
LL | 42 >> 0;
6767
| ^^^^^^^
6868

69-
error: aborting due to 11 previous errors
69+
error: the operation is ineffective. Consider reducing it to `&x`
70+
--> $DIR/identity_op.rs:51:5
71+
|
72+
LL | &x >> 0;
73+
| ^^^^^^^
74+
75+
error: the operation is ineffective. Consider reducing it to `x`
76+
--> $DIR/identity_op.rs:52:5
77+
|
78+
LL | x >> &0;
79+
| ^^^^^^^
80+
81+
error: aborting due to 13 previous errors
7082

0 commit comments

Comments
 (0)