diff options
| author | bors <bors@rust-lang.org> | 2023-01-07 11:53:45 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-01-07 11:53:45 +0000 |
| commit | cf1d3d03700069d6a31fc142a1808a7f3dcde429 (patch) | |
| tree | 8f7dc6233b1f205d09ba1da3d38f76cf9a5c0980 | |
| parent | ef5a545f9860fbbea3f6c94bad60ab87f384d458 (diff) | |
| parent | ce56cf71d956ea78c319ff510651473ca8dce47c (diff) | |
| download | rust-cf1d3d03700069d6a31fc142a1808a7f3dcde429.tar.gz rust-cf1d3d03700069d6a31fc142a1808a7f3dcde429.zip | |
Auto merge of #10162 - tamaroning:fix10018, r=xFrednet
Fix FP of single-element-loop closes #10018 --- changelog: [`single_element_loop`]: No longer lints, if the loop contains a `break` or `continue` [#10162](https://github.com/rust-lang/rust-clippy/pull/10162) <!-- changelog_checked -->
| -rw-r--r-- | clippy_lints/src/loops/single_element_loop.rs | 2 | ||||
| -rw-r--r-- | clippy_utils/src/visitors.rs | 11 | ||||
| -rw-r--r-- | tests/ui/single_element_loop.fixed | 27 | ||||
| -rw-r--r-- | tests/ui/single_element_loop.rs | 26 | ||||
| -rw-r--r-- | tests/ui/single_element_loop.stderr | 29 |
5 files changed, 94 insertions, 1 deletions
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index f4b47808dfa..744fd61bd13 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::contains_break_or_continue; use if_chain::if_chain; use rustc_ast::util::parser::PREC_PREFIX; use rustc_ast::Mutability; @@ -67,6 +68,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/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 863fb60fcfc..14c01a60b4c 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() +} diff --git a/tests/ui/single_element_loop.fixed b/tests/ui/single_element_loop.fixed index 63d31ff83f9..a0dcc0172e8 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 2cda5a329d2..bc014035c98 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 0aeb8da1a2e..14437a59745 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 |
