From 79ed23ff815bc39d0062ade40b2c38dd37e77373 Mon Sep 17 00:00:00 2001 From: Raiki Tamura Date: Thu, 5 Jan 2023 18:30:13 +0900 Subject: [PATCH 1/2] fix --- clippy_lints/src/loops/single_element_loop.rs | 14 +++++++++ tests/ui/single_element_loop.fixed | 27 +++++++++++++++++ tests/ui/single_element_loop.rs | 26 +++++++++++++++++ tests/ui/single_element_loop.stderr | 29 ++++++++++++++++++- 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index f4b47808d..7cbc45624 100644 --- a/clippy_lints/src/loops/single_element_loop.rs +++ b/clippy_lints/src/loops/single_element_loop.rs @@ -1,6 +1,7 @@ use super::SINGLE_ELEMENT_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, snippet_with_applicability}; +use clippy_utils::visitors::for_each_expr; use if_chain::if_chain; use rustc_ast::util::parser::PREC_PREFIX; use rustc_ast::Mutability; @@ -8,6 +9,18 @@ use rustc_errors::Applicability; use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat}; use rustc_lint::LateContext; use rustc_span::edition::Edition; +use std::ops::ControlFlow; + +fn contains_break_or_continue(expr: &Expr<'_>) -> bool { + for_each_expr(expr, |e| { + if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }) + .is_some() +} pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, @@ -67,6 +80,7 @@ pub(super) fn check<'tcx>( if_chain! { if let ExprKind::Block(block, _) = body.kind; if !block.stmts.is_empty(); + if !contains_break_or_continue(body); then { let mut applicability = Applicability::MachineApplicable; let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability); diff --git a/tests/ui/single_element_loop.fixed b/tests/ui/single_element_loop.fixed index 63d31ff83..a0dcc0172 100644 --- a/tests/ui/single_element_loop.fixed +++ b/tests/ui/single_element_loop.fixed @@ -33,4 +33,31 @@ fn main() { let item = 0..5; dbg!(item); } + + // should not lint (issue #10018) + for e in [42] { + if e > 0 { + continue; + } + } + + // should not lint (issue #10018) + for e in [42] { + if e > 0 { + break; + } + } + + // should lint (issue #10018) + { + let _ = 42; + let _f = |n: u32| { + for i in 0..n { + if i > 10 { + dbg!(i); + break; + } + } + }; + } } diff --git a/tests/ui/single_element_loop.rs b/tests/ui/single_element_loop.rs index 2cda5a329..bc014035c 100644 --- a/tests/ui/single_element_loop.rs +++ b/tests/ui/single_element_loop.rs @@ -27,4 +27,30 @@ fn main() { for item in [0..5].into_iter() { dbg!(item); } + + // should not lint (issue #10018) + for e in [42] { + if e > 0 { + continue; + } + } + + // should not lint (issue #10018) + for e in [42] { + if e > 0 { + break; + } + } + + // should lint (issue #10018) + for _ in [42] { + let _f = |n: u32| { + for i in 0..n { + if i > 10 { + dbg!(i); + break; + } + } + }; + } } diff --git a/tests/ui/single_element_loop.stderr b/tests/ui/single_element_loop.stderr index 0aeb8da1a..14437a597 100644 --- a/tests/ui/single_element_loop.stderr +++ b/tests/ui/single_element_loop.stderr @@ -95,5 +95,32 @@ LL + dbg!(item); LL + } | -error: aborting due to 6 previous errors +error: for loop over a single element + --> $DIR/single_element_loop.rs:46:5 + | +LL | / for _ in [42] { +LL | | let _f = |n: u32| { +LL | | for i in 0..n { +LL | | if i > 10 { +... | +LL | | }; +LL | | } + | |_____^ + | +help: try + | +LL ~ { +LL + let _ = 42; +LL + let _f = |n: u32| { +LL + for i in 0..n { +LL + if i > 10 { +LL + dbg!(i); +LL + break; +LL + } +LL + } +LL + }; +LL + } + | + +error: aborting due to 7 previous errors From ce56cf71d956ea78c319ff510651473ca8dce47c Mon Sep 17 00:00:00 2001 From: Raiki Tamura Date: Sat, 7 Jan 2023 20:44:02 +0900 Subject: [PATCH 2/2] chore --- clippy_lints/src/loops/single_element_loop.rs | 14 +------------- clippy_utils/src/visitors.rs | 11 +++++++++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index 7cbc45624..744fd61bd 100644 --- a/clippy_lints/src/loops/single_element_loop.rs +++ b/clippy_lints/src/loops/single_element_loop.rs @@ -1,7 +1,7 @@ use super::SINGLE_ELEMENT_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, snippet_with_applicability}; -use clippy_utils::visitors::for_each_expr; +use clippy_utils::visitors::contains_break_or_continue; use if_chain::if_chain; use rustc_ast::util::parser::PREC_PREFIX; use rustc_ast::Mutability; @@ -9,18 +9,6 @@ use rustc_errors::Applicability; use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat}; use rustc_lint::LateContext; use rustc_span::edition::Edition; -use std::ops::ControlFlow; - -fn contains_break_or_continue(expr: &Expr<'_>) -> bool { - for_each_expr(expr, |e| { - if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(()) - } - }) - .is_some() -} pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 863fb60fc..14c01a60b 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -724,3 +724,14 @@ pub fn for_each_local_assignment<'tcx, B>( ControlFlow::Continue(()) } } + +pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool { + for_each_expr(expr, |e| { + if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }) + .is_some() +}