Skip to content

Commit 8419108

Browse files
committed
Auto merge of rust-lang#8204 - wigy-opensource-developer:fix-7210, r=xFrednet
[`erasing_op`] lint ignored when operation `Output` type is different from the type of constant `0` fixes rust-lang#7210 changelog: [`erasing_op`] lint ignored when operation `Output` type is different from the type of constant `0`
2 parents b25dbc6 + e8b6b2a commit 8419108

File tree

5 files changed

+95
-24
lines changed

5 files changed

+95
-24
lines changed

clippy_lints/src/erasing_op.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use clippy_utils::consts::{constant_simple, Constant};
22
use clippy_utils::diagnostics::span_lint;
3+
use clippy_utils::ty::same_type_and_consts;
4+
35
use rustc_hir::{BinOpKind, Expr, ExprKind};
46
use rustc_lint::{LateContext, LateLintPass};
7+
use rustc_middle::ty::TypeckResults;
58
use rustc_session::{declare_lint_pass, declare_tool_lint};
6-
use rustc_span::source_map::Span;
79

810
declare_clippy_lint! {
911
/// ### What it does
@@ -35,24 +37,34 @@ impl<'tcx> LateLintPass<'tcx> for ErasingOp {
3537
return;
3638
}
3739
if let ExprKind::Binary(ref cmp, left, right) = e.kind {
40+
let tck = cx.typeck_results();
3841
match cmp.node {
3942
BinOpKind::Mul | BinOpKind::BitAnd => {
40-
check(cx, left, e.span);
41-
check(cx, right, e.span);
43+
check(cx, tck, left, right, e);
44+
check(cx, tck, right, left, e);
4245
},
43-
BinOpKind::Div => check(cx, left, e.span),
46+
BinOpKind::Div => check(cx, tck, left, right, e),
4447
_ => (),
4548
}
4649
}
4750
}
4851
}
4952

50-
fn check(cx: &LateContext<'_>, e: &Expr<'_>, span: Span) {
51-
if constant_simple(cx, cx.typeck_results(), e) == Some(Constant::Int(0)) {
53+
fn different_types(tck: &TypeckResults<'tcx>, input: &'tcx Expr<'_>, output: &'tcx Expr<'_>) -> bool {
54+
let input_ty = tck.expr_ty(input).peel_refs();
55+
let output_ty = tck.expr_ty(output).peel_refs();
56+
!same_type_and_consts(input_ty, output_ty)
57+
}
58+
59+
fn check(cx: &LateContext<'cx>, tck: &TypeckResults<'cx>, op: &Expr<'cx>, other: &Expr<'cx>, parent: &Expr<'cx>) {
60+
if constant_simple(cx, tck, op) == Some(Constant::Int(0)) {
61+
if different_types(tck, other, parent) {
62+
return;
63+
}
5264
span_lint(
5365
cx,
5466
ERASING_OP,
55-
span,
67+
parent.span,
5668
"this operation will always return zero. This is likely not the intended outcome",
5769
);
5870
}

tests/ui/erasing_op.rs

+34
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
struct Length(u8);
2+
struct Meter;
3+
4+
impl core::ops::Mul<Meter> for u8 {
5+
type Output = Length;
6+
fn mul(self, _: Meter) -> Length {
7+
Length(self)
8+
}
9+
}
10+
11+
#[derive(Clone, Default, PartialEq, Eq, Hash)]
12+
struct Vec1 {
13+
x: i32,
14+
}
15+
16+
impl core::ops::Mul<Vec1> for i32 {
17+
type Output = Vec1;
18+
fn mul(self, mut right: Vec1) -> Vec1 {
19+
right.x *= self;
20+
right
21+
}
22+
}
23+
24+
impl core::ops::Mul<i32> for Vec1 {
25+
type Output = Vec1;
26+
fn mul(mut self, right: i32) -> Vec1 {
27+
self.x *= right;
28+
self
29+
}
30+
}
31+
132
#[allow(clippy::no_effect)]
233
#[warn(clippy::erasing_op)]
334
fn main() {
@@ -6,4 +37,7 @@ fn main() {
637
x * 0;
738
0 & x;
839
0 / x;
40+
0 * Meter; // no error: Output type is different from the non-zero argument
41+
0 * Vec1 { x: 5 };
42+
Vec1 { x: 5 } * 0;
943
}

tests/ui/erasing_op.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,34 @@
11
error: this operation will always return zero. This is likely not the intended outcome
2-
--> $DIR/erasing_op.rs:6:5
2+
--> $DIR/erasing_op.rs:37:5
33
|
44
LL | x * 0;
55
| ^^^^^
66
|
77
= note: `-D clippy::erasing-op` implied by `-D warnings`
88

99
error: this operation will always return zero. This is likely not the intended outcome
10-
--> $DIR/erasing_op.rs:7:5
10+
--> $DIR/erasing_op.rs:38:5
1111
|
1212
LL | 0 & x;
1313
| ^^^^^
1414

1515
error: this operation will always return zero. This is likely not the intended outcome
16-
--> $DIR/erasing_op.rs:8:5
16+
--> $DIR/erasing_op.rs:39:5
1717
|
1818
LL | 0 / x;
1919
| ^^^^^
2020

21-
error: aborting due to 3 previous errors
21+
error: this operation will always return zero. This is likely not the intended outcome
22+
--> $DIR/erasing_op.rs:41:5
23+
|
24+
LL | 0 * Vec1 { x: 5 };
25+
| ^^^^^^^^^^^^^^^^^
26+
27+
error: this operation will always return zero. This is likely not the intended outcome
28+
--> $DIR/erasing_op.rs:42:5
29+
|
30+
LL | Vec1 { x: 5 } * 0;
31+
| ^^^^^^^^^^^^^^^^^
32+
33+
error: aborting due to 5 previous errors
2234

tests/ui/identity_op.rs

+13
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ impl std::ops::Shl<i32> for A {
1111
self
1212
}
1313
}
14+
15+
struct Length(u8);
16+
struct Meter;
17+
18+
impl core::ops::Mul<Meter> for u8 {
19+
type Output = Length;
20+
fn mul(self, _: Meter) -> Length {
21+
Length(self)
22+
}
23+
}
24+
1425
#[allow(
1526
clippy::eq_op,
1627
clippy::no_effect,
@@ -53,4 +64,6 @@ fn main() {
5364

5465
let mut a = A("".into());
5566
let b = a << 0; // no error: non-integer
67+
68+
1 * Meter; // no error: non-integer
5669
}

tests/ui/identity_op.stderr

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,79 @@
11
error: the operation is ineffective. Consider reducing it to `x`
2-
--> $DIR/identity_op.rs:26:5
2+
--> $DIR/identity_op.rs:37: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:27:5
10+
--> $DIR/identity_op.rs:38: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:29:5
16+
--> $DIR/identity_op.rs:40:5
1717
|
1818
LL | 0 + x;
1919
| ^^^^^
2020

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

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

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

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

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

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

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

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

6969
error: the operation is ineffective. Consider reducing it to `&x`
70-
--> $DIR/identity_op.rs:51:5
70+
--> $DIR/identity_op.rs:62:5
7171
|
7272
LL | &x >> 0;
7373
| ^^^^^^^
7474

7575
error: the operation is ineffective. Consider reducing it to `x`
76-
--> $DIR/identity_op.rs:52:5
76+
--> $DIR/identity_op.rs:63:5
7777
|
7878
LL | x >> &0;
7979
| ^^^^^^^

0 commit comments

Comments
 (0)