Skip to content

Commit 66697e8

Browse files
authored
needless_match: do not pretend that return is not significant in an expression (#14757)
A `return` in an expression makes it divergent and cannot be removed blindly. While this stripping might have been introduced as a way to catch more cases, it was improperly used, and no tests exhibit a failure when this special handling is removed. changelog: [`needless_match`]: do not strip `return` as it might make the `if let` or `match` divergent in some cases Fixes #14754
2 parents b87e90b + 82f8b1c commit 66697e8

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

clippy_lints/src/matches/needless_match.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ fn check_all_arms(cx: &LateContext<'_>, match_expr: &Expr<'_>, arms: &[Arm<'_>])
7474
}
7575

7676
if let PatKind::Wild = arm.pat.kind {
77-
if !eq_expr_value(cx, match_expr, strip_return(arm_expr)) {
77+
if !eq_expr_value(cx, match_expr, arm_expr) {
7878
return false;
7979
}
8080
} else if !pat_same_as_expr(arm.pat, arm_expr) {
@@ -103,27 +103,18 @@ fn check_if_let_inner(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool
103103
if matches!(else_expr.kind, ExprKind::Block(..)) {
104104
return false;
105105
}
106-
let ret = strip_return(else_expr);
107106
let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr);
108107
if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) {
109-
return is_res_lang_ctor(cx, path_res(cx, ret), OptionNone) || eq_expr_value(cx, if_let.let_expr, ret);
108+
return is_res_lang_ctor(cx, path_res(cx, else_expr), OptionNone)
109+
|| eq_expr_value(cx, if_let.let_expr, else_expr);
110110
}
111-
return eq_expr_value(cx, if_let.let_expr, ret);
111+
return eq_expr_value(cx, if_let.let_expr, else_expr);
112112
}
113113
}
114114

115115
false
116116
}
117117

118-
/// Strip `return` keyword if the expression type is `ExprKind::Ret`.
119-
fn strip_return<'hir>(expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
120-
if let ExprKind::Ret(Some(ret)) = expr.kind {
121-
ret
122-
} else {
123-
expr
124-
}
125-
}
126-
127118
/// Manually check for coercion casting by checking if the type of the match operand or let expr
128119
/// differs with the assigned local variable or the function return type.
129120
fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>) -> bool {
@@ -161,7 +152,6 @@ fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>
161152
}
162153

163154
fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
164-
let expr = strip_return(expr);
165155
match (&pat.kind, &expr.kind) {
166156
// Example: `Some(val) => Some(val)`
167157
(PatKind::TupleStruct(QPath::Resolved(_, path), tuple_params, _), ExprKind::Call(call_expr, call_params)) => {

tests/ui/needless_match.fixed

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,16 @@ pub fn issue13574() -> Option<()> {
301301
None
302302
}
303303

304+
fn issue14754(t: Result<i32, &'static str>) -> Result<i32, &'static str> {
305+
let _ = match t {
306+
Ok(v) => Ok::<_, &'static str>(v),
307+
err @ Err(_) => return err,
308+
};
309+
println!("Still here");
310+
let x = t;
311+
//~^^^^ needless_match
312+
println!("Still here");
313+
x
314+
}
315+
304316
fn main() {}

tests/ui/needless_match.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,19 @@ pub fn issue13574() -> Option<()> {
364364
None
365365
}
366366

367+
fn issue14754(t: Result<i32, &'static str>) -> Result<i32, &'static str> {
368+
let _ = match t {
369+
Ok(v) => Ok::<_, &'static str>(v),
370+
err @ Err(_) => return err,
371+
};
372+
println!("Still here");
373+
let x = match t {
374+
Ok(v) => Ok::<_, &'static str>(v),
375+
err @ Err(_) => err,
376+
};
377+
//~^^^^ needless_match
378+
println!("Still here");
379+
x
380+
}
381+
367382
fn main() {}

tests/ui/needless_match.stderr

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,15 @@ LL | | None
151151
LL | | }
152152
| |_________^ help: replace it with: `A`
153153

154-
error: aborting due to 14 previous errors
154+
error: this match expression is unnecessary
155+
--> tests/ui/needless_match.rs:373:13
156+
|
157+
LL | let x = match t {
158+
| _____________^
159+
LL | | Ok(v) => Ok::<_, &'static str>(v),
160+
LL | | err @ Err(_) => err,
161+
LL | | };
162+
| |_____^ help: replace it with: `t`
163+
164+
error: aborting due to 15 previous errors
155165

0 commit comments

Comments
 (0)