Skip to content

Commit 6d40b10

Browse files
committed
Add a function to check whether binary oprands are nontrivial
It's hard to check whether oprator is overrided through context of lint So assume nontrivial has overrided binary operator
1 parent da27c97 commit 6d40b10

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

clippy_lints/src/no_effect.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ 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+
// assume nontrivial oprand of `Binary` Expr can skip `check_unnecessary_operation`
91+
if has_nontrivial_oprand(expr) {
92+
return true;
93+
}
9094
if has_no_effect(cx, expr) {
9195
span_lint_hir_and_then(
9296
cx,
@@ -153,6 +157,61 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
153157
false
154158
}
155159

160+
fn has_nontrivial_oprand(expr: &Expr<'_>) -> bool {
161+
if expr.span.from_expansion() {
162+
return false;
163+
}
164+
return match peel_blocks(expr).kind {
165+
ExprKind::Binary(_, lhs, rhs) => !check_nontrivial_operand(lhs, rhs),
166+
_ => false,
167+
};
168+
}
169+
170+
fn check_nontrivial_operand(lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool {
171+
// It's seem that impossable to check whether operator is overrided through context of this lint,
172+
// so, this function assume user-defined binary operator is overrided with an side-effect.
173+
// The definition of user-defined structure here is `tuple`, `array`, `struct`,
174+
// it looks like a little bit simple, but useful.
175+
// Althrough this will weaken the ability of this lint,
176+
// less miss lint-fix happen.
177+
178+
// a closure to check whether expr belongs to user-defined structure
179+
let closure = |expr: &Expr<'_>| -> bool {
180+
match &expr.kind {
181+
// check whether expr is a user-defined sturcture
182+
ExprKind::Tup(..) | ExprKind::Array(..) | ExprKind::Struct(..) => true,
183+
// resolve expr's path
184+
ExprKind::Path(rustc_hir::QPath::Resolved(
185+
_,
186+
rustc_hir::Path {
187+
span: _,
188+
res,
189+
segments: _,
190+
},
191+
)) => {
192+
match res {
193+
Res::Def(defkind, _) => match defkind {
194+
// user-defined
195+
DefKind::Struct | DefKind::Ctor(_, _) => true,
196+
_ => false,
197+
},
198+
_ => false,
199+
};
200+
false
201+
},
202+
_ => false,
203+
}
204+
};
205+
206+
let lhs_ud = closure(lhs);
207+
let rhs_ud = closure(rhs);
208+
// one of lhs or rhs is user-defined structure
209+
if lhs_ud || rhs_ud {
210+
return false;
211+
}
212+
true
213+
}
214+
156215
fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
157216
if expr.span.from_expansion() {
158217
return false;

0 commit comments

Comments
 (0)