diff --git a/clippy_lints/src/methods/iter_once_empty.rs b/clippy_lints/src/methods/iter_once_empty.rs index d45dfc678..82fafb8a4 100644 --- a/clippy_lints/src/methods/iter_once_empty.rs +++ b/clippy_lints/src/methods/iter_once_empty.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_lang_ctor; +use clippy_utils::is_no_std_crate; use clippy_utils::source::snippet; use rustc_errors::Applicability; @@ -9,6 +10,22 @@ use rustc_lint::LateContext; use super::{ITER_EMPTY, ITER_ONCE}; +enum IterType { + Iter, + IterMut, + IntoIter, +} + +impl IterType { + fn ref_prefix(&self) -> &'static str { + match self { + Self::Iter => "&", + Self::IterMut => "&mut ", + Self::IntoIter => "", + } + } +} + pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) { let item = match &recv.kind { ExprKind::Array(v) if v.len() <= 1 => v.first(), @@ -32,39 +49,42 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: }, _ => return, }; + let iter_type = match method_name { + "iter" => IterType::Iter, + "iter_mut" => IterType::IterMut, + "into_iter" => IterType::IntoIter, + _ => return, + }; if let Some(i) = item { - let (sugg, msg) = match method_name { - "iter" => ( - format!("std::iter::once(&{})", snippet(cx, i.span, "...")), - "this `iter` call can be replaced with std::iter::once", - ), - "iter_mut" => ( - format!("std::iter::once(&mut {})", snippet(cx, i.span, "...")), - "this `iter_mut` call can be replaced with std::iter::once", - ), - "into_iter" => ( - format!("std::iter::once({})", snippet(cx, i.span, "...")), - "this `into_iter` call can be replaced with std::iter::once", - ), - _ => return, - }; - span_lint_and_sugg(cx, ITER_ONCE, expr.span, msg, "try", sugg, Applicability::Unspecified); + let sugg = format!( + "{}::iter::once({}{})", + if is_no_std_crate(cx) { "core" } else { "std" }, + iter_type.ref_prefix(), + snippet(cx, i.span, "...") + ); + span_lint_and_sugg( + cx, + ITER_ONCE, + expr.span, + &format!("`{method_name}` call on a collection with only one item"), + "try", + sugg, + Applicability::MaybeIncorrect, + ); } else { - let msg = match method_name { - "iter" => "this `iter call` can be replaced with std::iter::empty", - "iter_mut" => "this `iter_mut` call can be replaced with std::iter::empty", - "into_iter" => "this `into_iter` call can be replaced with std::iter::empty", - _ => return, - }; span_lint_and_sugg( cx, ITER_EMPTY, expr.span, - msg, + &format!("`{method_name}` call on an empty collection"), "try", - "std::iter::empty()".to_string(), - Applicability::Unspecified, + if is_no_std_crate(cx) { + "core::iter::empty()".to_string() + } else { + "std::iter::empty()".to_string() + }, + Applicability::MaybeIncorrect, ); } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e449ae0e4..015cd094a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2308,14 +2308,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// - /// Checks for usage of: - /// - /// - `[foo].iter()` - /// - `[foo].iter_mut()` - /// - `[foo].into_iter()` - /// - `Some(foo).iter()` - /// - `Some(foo).iter_mut()` - /// - `Some(foo).into_iter()` + /// Checks for calls to `iter`, `iter_mut` or `into_iter` on collections containing a single item /// /// ### Why is this bad? /// @@ -2346,14 +2339,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// - /// Checks for usage of: - /// - /// - `[].iter()` - /// - `[].iter_mut()` - /// - `[].into_iter()` - /// - `None.iter()` - /// - `None.iter_mut()` - /// - `None.into_iter()` + /// Checks for calls to `iter`, `iter_mut` or `into_iter` on empty collections /// /// ### Why is this bad? /// diff --git a/tests/ui/iter_empty.stderr b/tests/ui/iter_empty.stderr index f4f06e93b..40c08e6f8 100644 --- a/tests/ui/iter_empty.stderr +++ b/tests/ui/iter_empty.stderr @@ -1,4 +1,4 @@ -error: this `into_iter` call can be replaced with std::iter::empty +error: `into_iter` call on an empty collection --> $DIR/iter_empty.rs:6:16 | LL | assert_eq!([].into_iter().next(), Option::::None); @@ -6,31 +6,31 @@ LL | assert_eq!([].into_iter().next(), Option::::None); | = note: `-D clippy::iter-empty` implied by `-D warnings` -error: this `iter_mut` call can be replaced with std::iter::empty +error: `iter_mut` call on an empty collection --> $DIR/iter_empty.rs:7:16 | LL | assert_eq!([].iter_mut().next(), Option::<&mut i32>::None); | ^^^^^^^^^^^^^ help: try: `std::iter::empty()` -error: this `iter call` can be replaced with std::iter::empty +error: `iter` call on an empty collection --> $DIR/iter_empty.rs:8:16 | LL | assert_eq!([].iter().next(), Option::<&i32>::None); | ^^^^^^^^^ help: try: `std::iter::empty()` -error: this `into_iter` call can be replaced with std::iter::empty +error: `into_iter` call on an empty collection --> $DIR/iter_empty.rs:9:16 | LL | assert_eq!(None.into_iter().next(), Option::::None); | ^^^^^^^^^^^^^^^^ help: try: `std::iter::empty()` -error: this `iter_mut` call can be replaced with std::iter::empty +error: `iter_mut` call on an empty collection --> $DIR/iter_empty.rs:10:16 | LL | assert_eq!(None.iter_mut().next(), Option::<&mut i32>::None); | ^^^^^^^^^^^^^^^ help: try: `std::iter::empty()` -error: this `iter call` can be replaced with std::iter::empty +error: `iter` call on an empty collection --> $DIR/iter_empty.rs:11:16 | LL | assert_eq!(None.iter().next(), Option::<&i32>::None); diff --git a/tests/ui/iter_once.stderr b/tests/ui/iter_once.stderr index d9e8f96f7..b22c8a99f 100644 --- a/tests/ui/iter_once.stderr +++ b/tests/ui/iter_once.stderr @@ -1,4 +1,4 @@ -error: this `into_iter` call can be replaced with std::iter::once +error: `into_iter` call on a collection with only one item --> $DIR/iter_once.rs:6:16 | LL | assert_eq!([123].into_iter().next(), Some(123)); @@ -6,31 +6,31 @@ LL | assert_eq!([123].into_iter().next(), Some(123)); | = note: `-D clippy::iter-once` implied by `-D warnings` -error: this `iter_mut` call can be replaced with std::iter::once +error: `iter_mut` call on a collection with only one item --> $DIR/iter_once.rs:7:16 | LL | assert_eq!([123].iter_mut().next(), Some(&mut 123)); | ^^^^^^^^^^^^^^^^ help: try: `std::iter::once(&mut 123)` -error: this `iter` call can be replaced with std::iter::once +error: `iter` call on a collection with only one item --> $DIR/iter_once.rs:8:16 | LL | assert_eq!([123].iter().next(), Some(&123)); | ^^^^^^^^^^^^ help: try: `std::iter::once(&123)` -error: this `into_iter` call can be replaced with std::iter::once +error: `into_iter` call on a collection with only one item --> $DIR/iter_once.rs:9:16 | LL | assert_eq!(Some(123).into_iter().next(), Some(123)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::once(123)` -error: this `iter_mut` call can be replaced with std::iter::once +error: `iter_mut` call on a collection with only one item --> $DIR/iter_once.rs:10:16 | LL | assert_eq!(Some(123).iter_mut().next(), Some(&mut 123)); | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::once(&mut 123)` -error: this `iter` call can be replaced with std::iter::once +error: `iter` call on a collection with only one item --> $DIR/iter_once.rs:11:16 | LL | assert_eq!(Some(123).iter().next(), Some(&123));