Skip to content

Commit d73adea

Browse files
committed
needless_return: remove multiple semis on suggestion
1 parent 96e3068 commit d73adea

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

clippy_lints/src/returns.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
22
use clippy_utils::source::{snippet_opt, snippet_with_context};
33
use clippy_utils::visitors::{for_each_expr, Descend};
4-
use clippy_utils::{fn_def_id, path_to_local_id};
4+
use clippy_utils::{fn_def_id, path_to_local_id, span_find_starting_semi};
55
use core::ops::ControlFlow;
66
use if_chain::if_chain;
77
use rustc_errors::Applicability;
@@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
151151
kind: FnKind<'tcx>,
152152
_: &'tcx FnDecl<'tcx>,
153153
body: &'tcx Body<'tcx>,
154-
_: Span,
154+
sp: Span,
155155
_: HirId,
156156
) {
157157
match kind {
@@ -166,14 +166,14 @@ impl<'tcx> LateLintPass<'tcx> for Return {
166166
check_final_expr(cx, body.value, vec![], replacement);
167167
},
168168
FnKind::ItemFn(..) | FnKind::Method(..) => {
169-
check_block_return(cx, &body.value.kind, vec![]);
169+
check_block_return(cx, &body.value.kind, sp, vec![]);
170170
},
171171
}
172172
}
173173
}
174174

175175
// if `expr` is a block, check if there are needless returns in it
176-
fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, semi_spans: Vec<Span>) {
176+
fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, sp: Span, mut semi_spans: Vec<Span>) {
177177
if let ExprKind::Block(block, _) = expr_kind {
178178
if let Some(block_expr) = block.expr {
179179
check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
@@ -183,12 +183,14 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>,
183183
check_final_expr(cx, expr, semi_spans, RetReplacement::Empty);
184184
},
185185
StmtKind::Semi(semi_expr) => {
186-
let mut semi_spans_and_this_one = semi_spans;
187-
// we only want the span containing the semicolon so we can remove it later. From `entry.rs:382`
188-
if let Some(semicolon_span) = stmt.span.trim_start(semi_expr.span) {
189-
semi_spans_and_this_one.push(semicolon_span);
190-
check_final_expr(cx, semi_expr, semi_spans_and_this_one, RetReplacement::Empty);
186+
// Remove ending semicolons and any whitespace ' ' in between.
187+
// Without `return`, the suggestion might not compile if the semicolon is retained
188+
if let Some(semi_span) = stmt.span.trim_start(semi_expr.span) {
189+
let semi_span_to_remove =
190+
span_find_starting_semi(cx.sess().source_map(), semi_span.with_hi(sp.hi()));
191+
semi_spans.push(semi_span_to_remove);
191192
}
193+
check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty);
192194
},
193195
_ => (),
194196
}
@@ -231,9 +233,9 @@ fn check_final_expr<'tcx>(
231233
emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
232234
},
233235
ExprKind::If(_, then, else_clause_opt) => {
234-
check_block_return(cx, &then.kind, semi_spans.clone());
236+
check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
235237
if let Some(else_clause) = else_clause_opt {
236-
check_block_return(cx, &else_clause.kind, semi_spans);
238+
check_block_return(cx, &else_clause.kind, peeled_drop_expr.span, semi_spans);
237239
}
238240
},
239241
// a match expr, check all arms
@@ -246,7 +248,7 @@ fn check_final_expr<'tcx>(
246248
}
247249
},
248250
// if it's a whole block, check it
249-
other_expr_kind => check_block_return(cx, other_expr_kind, semi_spans),
251+
other_expr_kind => check_block_return(cx, other_expr_kind, peeled_drop_expr.span, semi_spans),
250252
}
251253
}
252254

clippy_utils/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,10 @@ pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
24882488
comments_buf.join("\n")
24892489
}
24902490

2491+
pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
2492+
sm.span_take_while(span, |&ch| ch == ' ' || ch == ';')
2493+
}
2494+
24912495
macro_rules! op_utils {
24922496
($($name:ident $assign:ident)*) => {
24932497
/// Binary operation traits like `LangItem::Add`

0 commit comments

Comments
 (0)