|
35 | 35 | //! This lint is **warn** by default.
|
36 | 36 | use clippy_utils::diagnostics::span_lint_and_help;
|
37 | 37 | use clippy_utils::source::{indent_of, snippet, snippet_block};
|
38 |
| -use rustc_ast::ast; |
| 38 | +use rustc_ast::{ast, Block, Label}; |
39 | 39 | use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
40 | 40 | use rustc_session::{declare_lint_pass, declare_tool_lint};
|
41 | 41 | use rustc_span::Span;
|
@@ -361,24 +361,68 @@ fn suggestion_snippet_for_continue_inside_else(cx: &EarlyContext<'_>, data: &Lin
|
361 | 361 | )
|
362 | 362 | }
|
363 | 363 |
|
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 | + _ => {}, |
379 | 406 | }
|
380 | 407 | }
|
| 408 | +} |
| 409 | + |
| 410 | +fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) { |
381 | 411 | 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 | + |
382 | 426 | for (i, stmt) in loop_block.stmts.iter().enumerate() {
|
383 | 427 | with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {
|
384 | 428 | let data = &LintData {
|
|
0 commit comments