Skip to content

Commit

Permalink
Auto merge of rust-lang#10162 - tamaroning:fix10018, r=xFrednet
Browse files Browse the repository at this point in the history
Fix FP of single-element-loop

closes rust-lang#10018

---

changelog: [`single_element_loop`]: No longer lints, if the loop contains a `break` or `continue`
[rust-lang#10162](rust-lang/rust-clippy#10162)
<!-- changelog_checked -->
  • Loading branch information
bors committed Jan 7, 2023
2 parents ef5a545 + ce56cf7 commit cf1d3d0
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 1 deletion.
2 changes: 2 additions & 0 deletions clippy_lints/src/loops/single_element_loop.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions clippy_utils/src/visitors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
27 changes: 27 additions & 0 deletions tests/ui/single_element_loop.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
};
}
}
26 changes: 26 additions & 0 deletions tests/ui/single_element_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
};
}
}
29 changes: 28 additions & 1 deletion tests/ui/single_element_loop.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit cf1d3d0

Please sign in to comment.