Skip to content

Commit c12748f

Browse files
committed
fix(needless_return): do not trigger on ambiguous match arms return
1 parent 2998706 commit c12748f

File tree

3 files changed

+34
-16
lines changed

3 files changed

+34
-16
lines changed

clippy_lints/src/returns.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_hir::intravisit::FnKind;
99
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, MatchSource, PatKind, QPath, StmtKind};
1010
use rustc_lint::{LateContext, LateLintPass, LintContext};
1111
use rustc_middle::lint::in_external_macro;
12-
use rustc_middle::ty::subst::GenericArgKind;
12+
use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
1313
use rustc_session::{declare_lint_pass, declare_tool_lint};
1414
use rustc_span::def_id::LocalDefId;
1515
use rustc_span::source_map::Span;
@@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
175175
} else {
176176
RetReplacement::Empty
177177
};
178-
check_final_expr(cx, body.value, vec![], replacement);
178+
check_final_expr(cx, body.value, vec![], replacement, None);
179179
},
180180
FnKind::ItemFn(..) | FnKind::Method(..) => {
181181
check_block_return(cx, &body.value.kind, sp, vec![]);
@@ -188,11 +188,11 @@ impl<'tcx> LateLintPass<'tcx> for Return {
188188
fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, sp: Span, mut semi_spans: Vec<Span>) {
189189
if let ExprKind::Block(block, _) = expr_kind {
190190
if let Some(block_expr) = block.expr {
191-
check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
191+
check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty, None);
192192
} else if let Some(stmt) = block.stmts.iter().last() {
193193
match stmt.kind {
194194
StmtKind::Expr(expr) => {
195-
check_final_expr(cx, expr, semi_spans, RetReplacement::Empty);
195+
check_final_expr(cx, expr, semi_spans, RetReplacement::Empty, None);
196196
},
197197
StmtKind::Semi(semi_expr) => {
198198
// Remove ending semicolons and any whitespace ' ' in between.
@@ -202,7 +202,7 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>,
202202
span_find_starting_semi(cx.sess().source_map(), semi_span.with_hi(sp.hi()));
203203
semi_spans.push(semi_span_to_remove);
204204
}
205-
check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty);
205+
check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty, None);
206206
},
207207
_ => (),
208208
}
@@ -216,6 +216,7 @@ fn check_final_expr<'tcx>(
216216
semi_spans: Vec<Span>, /* containing all the places where we would need to remove semicolons if finding an
217217
* needless return */
218218
replacement: RetReplacement<'tcx>,
219+
match_ty_opt: Option<Ty<'_>>,
219220
) {
220221
let peeled_drop_expr = expr.peel_drop_temps();
221222
match &peeled_drop_expr.kind {
@@ -244,7 +245,22 @@ fn check_final_expr<'tcx>(
244245
RetReplacement::Expr(snippet, applicability)
245246
}
246247
} else {
247-
replacement
248+
match match_ty_opt {
249+
Some(match_ty) => {
250+
match match_ty.kind() {
251+
// If the code got till here with
252+
// tuple not getting detected before it,
253+
// then we are sure it's going to be Unit
254+
// type
255+
ty::Tuple(_) => RetReplacement::Unit,
256+
// We don't want to anything in this case
257+
// cause we can't predict what the user would
258+
// want here
259+
_ => return,
260+
}
261+
},
262+
None => replacement,
263+
}
248264
};
249265

250266
if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
@@ -268,8 +284,9 @@ fn check_final_expr<'tcx>(
268284
// note, if without else is going to be a type checking error anyways
269285
// (except for unit type functions) so we don't match it
270286
ExprKind::Match(_, arms, MatchSource::Normal) => {
287+
let match_ty = cx.typeck_results().expr_ty(peeled_drop_expr);
271288
for arm in arms.iter() {
272-
check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit);
289+
check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Empty, Some(match_ty));
273290
}
274291
},
275292
// if it's a whole block, check it
@@ -293,6 +310,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec<Span>,
293310
if ret_span.from_expansion() {
294311
return;
295312
}
313+
296314
let applicability = replacement.applicability().unwrap_or(Applicability::MachineApplicable);
297315
let return_replacement = replacement.to_string();
298316
let sugg_help = replacement.sugg_help();

tests/ui/needless_return.fixed

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn test_void_if_fun(b: bool) {
8181
fn test_void_match(x: u32) {
8282
match x {
8383
0 => (),
84-
_ => (),
84+
_ =>(),
8585
}
8686
}
8787

@@ -91,7 +91,7 @@ fn test_nested_match(x: u32) {
9191
1 => {
9292
let _ = 42;
9393
},
94-
_ => (),
94+
_ =>(),
9595
}
9696
}
9797

@@ -196,7 +196,7 @@ async fn async_test_void_if_fun(b: bool) {
196196
async fn async_test_void_match(x: u32) {
197197
match x {
198198
0 => (),
199-
_ => (),
199+
_ =>(),
200200
}
201201
}
202202

tests/ui/needless_return.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ LL | | return;
118118
= help: remove `return`
119119

120120
error: unneeded `return` statement
121-
--> $DIR/needless_return.rs:87:14
121+
--> $DIR/needless_return.rs:87:13
122122
|
123123
LL | _ => return,
124-
| ^^^^^^
124+
| ^^^^^^^
125125
|
126126
= help: replace `return` with a unit value
127127

@@ -136,10 +136,10 @@ LL | | return;
136136
= help: remove `return`
137137

138138
error: unneeded `return` statement
139-
--> $DIR/needless_return.rs:98:14
139+
--> $DIR/needless_return.rs:98:13
140140
|
141141
LL | _ => return,
142-
| ^^^^^^
142+
| ^^^^^^^
143143
|
144144
= help: replace `return` with a unit value
145145

@@ -296,10 +296,10 @@ LL | | return;
296296
= help: remove `return`
297297

298298
error: unneeded `return` statement
299-
--> $DIR/needless_return.rs:207:14
299+
--> $DIR/needless_return.rs:207:13
300300
|
301301
LL | _ => return,
302-
| ^^^^^^
302+
| ^^^^^^^
303303
|
304304
= help: replace `return` with a unit value
305305

0 commit comments

Comments
 (0)