about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRaiki Tamura <tamaron1203@gmail.com>2023-01-05 18:30:13 +0900
committerRaiki Tamura <tamaron1203@gmail.com>2023-01-05 18:30:13 +0900
commit79ed23ff815bc39d0062ade40b2c38dd37e77373 (patch)
treef8890068101fdaf4256e6ae937ec425d21b12b6c
parent61ff54e5c22736bad5fc4f41d3cc36208475510c (diff)
downloadrust-79ed23ff815bc39d0062ade40b2c38dd37e77373.tar.gz
rust-79ed23ff815bc39d0062ade40b2c38dd37e77373.zip
fix
-rw-r--r--clippy_lints/src/loops/single_element_loop.rs14
-rw-r--r--tests/ui/single_element_loop.fixed27
-rw-r--r--tests/ui/single_element_loop.rs26
-rw-r--r--tests/ui/single_element_loop.stderr29
4 files changed, 95 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..7cbc456244e 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 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