Skip to content

Commit 821e055

Browse files
committed
[needless_continue]: lint if the last stmt in for/while/loop is continue, recursively
Fixes: #4077
1 parent c556695 commit 821e055

7 files changed

+93
-24
lines changed

Diff for: clippy_lints/src/methods/unnecessary_to_owned.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
379379
for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) {
380380
match node {
381381
Node::Stmt(_) => return true,
382-
Node::Block(..) => continue,
382+
Node::Block(..) => {}
383383
Node::Item(item) => {
384384
if let ItemKind::Fn(_, _, body_id) = &item.kind
385385
&& let output_ty = return_ty(cx, item.owner_id)

Diff for: clippy_lints/src/needless_continue.rs

+60-16
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
//! This lint is **warn** by default.
3636
use clippy_utils::diagnostics::span_lint_and_help;
3737
use clippy_utils::source::{indent_of, snippet, snippet_block};
38-
use rustc_ast::ast;
38+
use rustc_ast::{ast, Block, Label};
3939
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
4040
use rustc_session::{declare_lint_pass, declare_tool_lint};
4141
use rustc_span::Span;
@@ -361,24 +361,68 @@ fn suggestion_snippet_for_continue_inside_else(cx: &EarlyContext<'_>, data: &Lin
361361
)
362362
}
363363

364-
fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) {
365-
if_chain! {
366-
if let ast::ExprKind::Loop(loop_block, ..) = &expr.kind;
367-
if let Some(last_stmt) = loop_block.stmts.last();
368-
if let ast::StmtKind::Expr(inner_expr) | ast::StmtKind::Semi(inner_expr) = &last_stmt.kind;
369-
if let ast::ExprKind::Continue(_) = inner_expr.kind;
370-
then {
371-
span_lint_and_help(
372-
cx,
373-
NEEDLESS_CONTINUE,
374-
last_stmt.span,
375-
MSG_REDUNDANT_CONTINUE_EXPRESSION,
376-
None,
377-
DROP_CONTINUE_EXPRESSION_MSG,
378-
);
364+
fn check_last_stmt<F>(b: &Block, func: &F)
365+
where
366+
F: Fn(Option<&ast::Label>, Span),
367+
{
368+
if let Some(last_stmt) = b.stmts.last() &&
369+
let ast::StmtKind::Expr(inner_expr) | ast::StmtKind::Semi(inner_expr) = &last_stmt.kind {
370+
match &inner_expr.kind {
371+
rustc_ast::ExprKind::Continue(continue_label) => {
372+
func(continue_label.as_ref(), last_stmt.span);
373+
},
374+
375+
rustc_ast::ExprKind::If(_, then_block, else_block) => {
376+
check_last_stmt(then_block, func);
377+
if let Some(else_block) = else_block {
378+
match &else_block.kind {
379+
rustc_ast::ExprKind::Continue(continue_label) => {
380+
func(continue_label.as_ref(), else_block.span);
381+
}
382+
rustc_ast::ExprKind::Block(b, _) => {
383+
check_last_stmt(b, func);
384+
}
385+
_ => {}
386+
387+
}
388+
}
389+
}
390+
rustc_ast::ExprKind::Match(_, arms) => {
391+
for arm in arms {
392+
match &arm.body.kind {
393+
rustc_ast::ExprKind::Continue(continue_label) => {
394+
func(continue_label.as_ref(), arm.body.span);
395+
}
396+
rustc_ast::ExprKind::Block(b, _) => {
397+
check_last_stmt(b, func);
398+
399+
}
400+
_ => {}
401+
}
402+
403+
}
404+
}
405+
_ => {},
379406
}
380407
}
408+
}
409+
410+
fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) {
381411
with_loop_block(expr, |loop_block, label| {
412+
let p = |continue_label: Option<&Label>, span: Span| {
413+
if compare_labels(label, continue_label) {
414+
span_lint_and_help(
415+
cx,
416+
NEEDLESS_CONTINUE,
417+
span,
418+
MSG_REDUNDANT_CONTINUE_EXPRESSION,
419+
None,
420+
DROP_CONTINUE_EXPRESSION_MSG,
421+
);
422+
}
423+
};
424+
check_last_stmt(loop_block, &p);
425+
382426
for (i, stmt) in loop_block.stmts.iter().enumerate() {
383427
with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {
384428
let data = &LintData {

Diff for: clippy_lints/src/redundant_else.rs

-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ impl EarlyLintPass for RedundantElse {
6969
ExprKind::If(_, next_then, Some(next_els)) => {
7070
then = next_then;
7171
els = next_els;
72-
continue;
7372
},
7473
// else if without else
7574
ExprKind::If(..) => return,

Diff for: clippy_lints/src/transmute/transmute_undefined_repr.rs

-4
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,16 @@ pub(super) fn check<'tcx>(
3030
| (ReducedTy::UnorderedFields(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) => {
3131
from_ty = from_sub_ty;
3232
to_ty = to_sub_ty;
33-
continue;
3433
},
3534
(ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) if reduced_tys.to_fat_ptr => {
3635
from_ty = from_sub_ty;
3736
to_ty = to_sub_ty;
38-
continue;
3937
},
4038
(ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty)))
4139
if reduced_tys.from_fat_ptr =>
4240
{
4341
from_ty = from_sub_ty;
4442
to_ty = to_sub_ty;
45-
continue;
4643
},
4744

4845
// ptr <-> ptr
@@ -52,7 +49,6 @@ pub(super) fn check<'tcx>(
5249
{
5350
from_ty = from_sub_ty;
5451
to_ty = to_sub_ty;
55-
continue;
5652
},
5753

5854
// fat ptr <-> (*size, *size)

Diff for: tests/missing-test-files.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fn explore_directory(dir: &Path) -> Vec<String> {
6060
missing_files.push(path.to_str().unwrap().to_string());
6161
}
6262
},
63-
_ => continue,
63+
_ => {},
6464
};
6565
}
6666
}

Diff for: tests/ui/needless_continue.rs

+22
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,25 @@ mod issue_2329 {
151151
}
152152
}
153153
}
154+
155+
mod issue_4077 {
156+
fn main() {
157+
loop {
158+
do_something();
159+
if some_expr() {
160+
continue;
161+
}
162+
}
163+
}
164+
165+
// The contents of these functions are irrelevant, the purpose of this file is
166+
// shown in main.
167+
168+
fn do_something() {
169+
std::process::exit(0);
170+
}
171+
172+
fn some_expr() -> bool {
173+
true
174+
}
175+
}

Diff for: tests/ui/needless_continue.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,13 @@ LL | | }
136136
println!("bar-5");
137137
}
138138

139-
error: aborting due to 8 previous errors
139+
error: this `continue` expression is redundant
140+
--> $DIR/needless_continue.rs:160:17
141+
|
142+
LL | continue;
143+
| ^^^^^^^^^
144+
|
145+
= help: consider dropping the `continue` expression
146+
147+
error: aborting due to 9 previous errors
140148

0 commit comments

Comments
 (0)