Skip to content

Commit 1c8cbe7

Browse files
committed
Auto merge of #11907 - cocodery:issue11885, r=y21,xFrednet
Add a function to check whether binary oprands are nontrivial fixes [#issue11885](#11885) It's hard to check whether operator is overrided through context of lint. So, assume non-trivial structure like tuple, array or sturt, using a overrided binary operator in this lint, which might cause a side effict. This is not detected before. Althrough this might weaken the ability of this lint, it may more useful than before. Maybe this lint will cause an error, but now, it not. And assuming side effect of non-trivial structure with operator is not a bad thing, right? changelog: Fix: [`no_effect`] check if binary operands are nontrivial
2 parents 2793e8d + 56d20c2 commit 1c8cbe7

File tree

6 files changed

+147
-52
lines changed

6 files changed

+147
-52
lines changed

clippy_lints/src/no_effect.rs

+30-4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
8787

8888
fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
8989
if let StmtKind::Semi(expr) = stmt.kind {
90+
// move `expr.span.from_expansion()` ahead
91+
if expr.span.from_expansion() {
92+
return false;
93+
}
94+
let expr = peel_blocks(expr);
95+
96+
if is_operator_overridden(cx, expr) {
97+
// Return `true`, to prevent `check_unnecessary_operation` from
98+
// linting on this statement as well.
99+
return true;
100+
}
90101
if has_no_effect(cx, expr) {
91102
span_lint_hir_and_then(
92103
cx,
@@ -153,11 +164,26 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
153164
false
154165
}
155166

156-
fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
157-
if expr.span.from_expansion() {
158-
return false;
167+
fn is_operator_overridden(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
168+
// It's very hard or impossable to check whether overridden operator have side-effect this lint.
169+
// So, this function assume user-defined operator is overridden with an side-effect.
170+
// The definition of user-defined structure here is ADT-type,
171+
// Althrough this will weaken the ability of this lint, less error lint-fix happen.
172+
match expr.kind {
173+
ExprKind::Binary(..) | ExprKind::Unary(..) => {
174+
// No need to check type of `lhs` and `rhs`
175+
// because if the operator is overridden, at least one operand is ADT type
176+
177+
// reference: rust/compiler/rustc_middle/src/ty/typeck_results.rs: `is_method_call`.
178+
// use this function to check whether operator is overridden in `ExprKind::{Binary, Unary}`.
179+
cx.typeck_results().is_method_call(expr)
180+
},
181+
_ => false,
159182
}
160-
match peel_blocks(expr).kind {
183+
}
184+
185+
fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
186+
match expr.kind {
161187
ExprKind::Lit(..) | ExprKind::Closure { .. } => true,
162188
ExprKind::Path(..) => !has_drop(cx, cx.typeck_results().expr_ty(expr)),
163189
ExprKind::Index(a, b, _) | ExprKind::Binary(_, a, b) => has_no_effect(cx, a) && has_no_effect(cx, b),

tests/ui/no_effect.rs

+31
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,30 @@
99
clippy::useless_vec
1010
)]
1111

12+
use std::fmt::Display;
13+
use std::ops::{Neg, Shl};
14+
15+
struct Cout;
16+
17+
impl<T> Shl<T> for Cout
18+
where
19+
T: Display,
20+
{
21+
type Output = Self;
22+
fn shl(self, rhs: T) -> Self::Output {
23+
println!("{}", rhs);
24+
self
25+
}
26+
}
27+
28+
impl Neg for Cout {
29+
type Output = Self;
30+
fn neg(self) -> Self::Output {
31+
println!("hello world");
32+
self
33+
}
34+
}
35+
1236
struct Unit;
1337
struct Tuple(i32);
1438
struct Struct {
@@ -174,4 +198,11 @@ fn main() {
174198
GreetStruct1("world");
175199
GreetStruct2()("world");
176200
GreetStruct3 {}("world");
201+
202+
fn n() -> i32 {
203+
42
204+
}
205+
206+
Cout << 142;
207+
-Cout;
177208
}

tests/ui/no_effect.stderr

+29-29
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: statement with no effect
2-
--> $DIR/no_effect.rs:98:5
2+
--> $DIR/no_effect.rs:122:5
33
|
44
LL | 0;
55
| ^^
@@ -8,151 +8,151 @@ LL | 0;
88
= help: to override `-D warnings` add `#[allow(clippy::no_effect)]`
99

1010
error: statement with no effect
11-
--> $DIR/no_effect.rs:101:5
11+
--> $DIR/no_effect.rs:125:5
1212
|
1313
LL | s2;
1414
| ^^^
1515

1616
error: statement with no effect
17-
--> $DIR/no_effect.rs:103:5
17+
--> $DIR/no_effect.rs:127:5
1818
|
1919
LL | Unit;
2020
| ^^^^^
2121

2222
error: statement with no effect
23-
--> $DIR/no_effect.rs:105:5
23+
--> $DIR/no_effect.rs:129:5
2424
|
2525
LL | Tuple(0);
2626
| ^^^^^^^^^
2727

2828
error: statement with no effect
29-
--> $DIR/no_effect.rs:107:5
29+
--> $DIR/no_effect.rs:131:5
3030
|
3131
LL | Struct { field: 0 };
3232
| ^^^^^^^^^^^^^^^^^^^^
3333

3434
error: statement with no effect
35-
--> $DIR/no_effect.rs:109:5
35+
--> $DIR/no_effect.rs:133:5
3636
|
3737
LL | Struct { ..s };
3838
| ^^^^^^^^^^^^^^^
3939

4040
error: statement with no effect
41-
--> $DIR/no_effect.rs:111:5
41+
--> $DIR/no_effect.rs:135:5
4242
|
4343
LL | Union { a: 0 };
4444
| ^^^^^^^^^^^^^^^
4545

4646
error: statement with no effect
47-
--> $DIR/no_effect.rs:113:5
47+
--> $DIR/no_effect.rs:137:5
4848
|
4949
LL | Enum::Tuple(0);
5050
| ^^^^^^^^^^^^^^^
5151

5252
error: statement with no effect
53-
--> $DIR/no_effect.rs:115:5
53+
--> $DIR/no_effect.rs:139:5
5454
|
5555
LL | Enum::Struct { field: 0 };
5656
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
5757

5858
error: statement with no effect
59-
--> $DIR/no_effect.rs:117:5
59+
--> $DIR/no_effect.rs:141:5
6060
|
6161
LL | 5 + 6;
6262
| ^^^^^^
6363

6464
error: statement with no effect
65-
--> $DIR/no_effect.rs:119:5
65+
--> $DIR/no_effect.rs:143:5
6666
|
6767
LL | *&42;
6868
| ^^^^^
6969

7070
error: statement with no effect
71-
--> $DIR/no_effect.rs:121:5
71+
--> $DIR/no_effect.rs:145:5
7272
|
7373
LL | &6;
7474
| ^^^
7575

7676
error: statement with no effect
77-
--> $DIR/no_effect.rs:123:5
77+
--> $DIR/no_effect.rs:147:5
7878
|
7979
LL | (5, 6, 7);
8080
| ^^^^^^^^^^
8181

8282
error: statement with no effect
83-
--> $DIR/no_effect.rs:125:5
83+
--> $DIR/no_effect.rs:149:5
8484
|
8585
LL | ..;
8686
| ^^^
8787

8888
error: statement with no effect
89-
--> $DIR/no_effect.rs:127:5
89+
--> $DIR/no_effect.rs:151:5
9090
|
9191
LL | 5..;
9292
| ^^^^
9393

9494
error: statement with no effect
95-
--> $DIR/no_effect.rs:129:5
95+
--> $DIR/no_effect.rs:153:5
9696
|
9797
LL | ..5;
9898
| ^^^^
9999

100100
error: statement with no effect
101-
--> $DIR/no_effect.rs:131:5
101+
--> $DIR/no_effect.rs:155:5
102102
|
103103
LL | 5..6;
104104
| ^^^^^
105105

106106
error: statement with no effect
107-
--> $DIR/no_effect.rs:133:5
107+
--> $DIR/no_effect.rs:157:5
108108
|
109109
LL | 5..=6;
110110
| ^^^^^^
111111

112112
error: statement with no effect
113-
--> $DIR/no_effect.rs:135:5
113+
--> $DIR/no_effect.rs:159:5
114114
|
115115
LL | [42, 55];
116116
| ^^^^^^^^^
117117

118118
error: statement with no effect
119-
--> $DIR/no_effect.rs:137:5
119+
--> $DIR/no_effect.rs:161:5
120120
|
121121
LL | [42, 55][1];
122122
| ^^^^^^^^^^^^
123123

124124
error: statement with no effect
125-
--> $DIR/no_effect.rs:139:5
125+
--> $DIR/no_effect.rs:163:5
126126
|
127127
LL | (42, 55).1;
128128
| ^^^^^^^^^^^
129129

130130
error: statement with no effect
131-
--> $DIR/no_effect.rs:141:5
131+
--> $DIR/no_effect.rs:165:5
132132
|
133133
LL | [42; 55];
134134
| ^^^^^^^^^
135135

136136
error: statement with no effect
137-
--> $DIR/no_effect.rs:143:5
137+
--> $DIR/no_effect.rs:167:5
138138
|
139139
LL | [42; 55][13];
140140
| ^^^^^^^^^^^^^
141141

142142
error: statement with no effect
143-
--> $DIR/no_effect.rs:146:5
143+
--> $DIR/no_effect.rs:170:5
144144
|
145145
LL | || x += 5;
146146
| ^^^^^^^^^^
147147

148148
error: statement with no effect
149-
--> $DIR/no_effect.rs:149:5
149+
--> $DIR/no_effect.rs:173:5
150150
|
151151
LL | FooString { s: s };
152152
| ^^^^^^^^^^^^^^^^^^^
153153

154154
error: binding to `_` prefixed variable with no side-effect
155-
--> $DIR/no_effect.rs:151:5
155+
--> $DIR/no_effect.rs:175:5
156156
|
157157
LL | let _unused = 1;
158158
| ^^^^^^^^^^^^^^^^
@@ -161,19 +161,19 @@ LL | let _unused = 1;
161161
= help: to override `-D warnings` add `#[allow(clippy::no_effect_underscore_binding)]`
162162

163163
error: binding to `_` prefixed variable with no side-effect
164-
--> $DIR/no_effect.rs:154:5
164+
--> $DIR/no_effect.rs:178:5
165165
|
166166
LL | let _penguin = || println!("Some helpful closure");
167167
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
168168

169169
error: binding to `_` prefixed variable with no side-effect
170-
--> $DIR/no_effect.rs:156:5
170+
--> $DIR/no_effect.rs:180:5
171171
|
172172
LL | let _duck = Struct { field: 0 };
173173
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
174174

175175
error: binding to `_` prefixed variable with no side-effect
176-
--> $DIR/no_effect.rs:158:5
176+
--> $DIR/no_effect.rs:182:5
177177
|
178178
LL | let _cat = [2, 4, 6, 8][2];
179179
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/unnecessary_operation.fixed

+19
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
)]
88
#![warn(clippy::unnecessary_operation)]
99

10+
use std::fmt::Display;
11+
use std::ops::Shl;
12+
1013
struct Tuple(i32);
1114
struct Struct {
1215
field: i32,
@@ -50,6 +53,19 @@ fn get_drop_struct() -> DropStruct {
5053
DropStruct { field: 0 }
5154
}
5255

56+
struct Cout;
57+
58+
impl<T> Shl<T> for Cout
59+
where
60+
T: Display,
61+
{
62+
type Output = Self;
63+
fn shl(self, rhs: T) -> Self::Output {
64+
println!("{}", rhs);
65+
self
66+
}
67+
}
68+
5369
fn main() {
5470
get_number();
5571
get_number();
@@ -87,4 +103,7 @@ fn main() {
87103
($($e:expr),*) => {{ $($e;)* }}
88104
}
89105
use_expr!(isize::MIN / -(one() as isize), i8::MIN / -one());
106+
107+
// Issue #11885
108+
Cout << 16;
90109
}

tests/ui/unnecessary_operation.rs

+19
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
)]
88
#![warn(clippy::unnecessary_operation)]
99

10+
use std::fmt::Display;
11+
use std::ops::Shl;
12+
1013
struct Tuple(i32);
1114
struct Struct {
1215
field: i32,
@@ -50,6 +53,19 @@ fn get_drop_struct() -> DropStruct {
5053
DropStruct { field: 0 }
5154
}
5255

56+
struct Cout;
57+
58+
impl<T> Shl<T> for Cout
59+
where
60+
T: Display,
61+
{
62+
type Output = Self;
63+
fn shl(self, rhs: T) -> Self::Output {
64+
println!("{}", rhs);
65+
self
66+
}
67+
}
68+
5369
fn main() {
5470
Tuple(get_number());
5571
Struct { field: get_number() };
@@ -91,4 +107,7 @@ fn main() {
91107
($($e:expr),*) => {{ $($e;)* }}
92108
}
93109
use_expr!(isize::MIN / -(one() as isize), i8::MIN / -one());
110+
111+
// Issue #11885
112+
Cout << 16;
94113
}

0 commit comments

Comments
 (0)