1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet;
3 use clippy_utils::{get_expr_use_or_unification_node, is_lang_ctor, is_no_std_crate};
5 use rustc_errors::Applicability;
6 use rustc_hir::LangItem::{OptionNone, OptionSome};
7 use rustc_hir::{Expr, ExprKind, Node};
8 use rustc_lint::LateContext;
10 use super::{ITER_ON_EMPTY_COLLECTIONS, ITER_ON_SINGLE_ITEMS};
19 fn ref_prefix(&self) -> &'static str {
22 Self::IterMut => "&mut ",
28 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
29 let item = match &recv.kind {
30 ExprKind::Array(v) if v.len() <= 1 => v.first(),
31 ExprKind::Path(p) => {
32 if is_lang_ctor(cx, p, OptionNone) {
38 ExprKind::Call(f, some_args) if some_args.len() == 1 => {
39 if let ExprKind::Path(p) = &f.kind {
40 if is_lang_ctor(cx, p, OptionSome) {
51 let iter_type = match method_name {
52 "iter" => IterType::Iter,
53 "iter_mut" => IterType::IterMut,
54 "into_iter" => IterType::IntoIter,
58 let is_unified = match get_expr_use_or_unification_node(cx.tcx, expr) {
59 Some((Node::Expr(parent), child_id)) => match parent.kind {
60 ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id == child_id => false,
62 | ExprKind::Match(_, _, _)
63 | ExprKind::Closure(_)
65 | ExprKind::Break(_, _) => true,
68 Some((Node::Stmt(_) | Node::Local(_), _)) => false,
76 if let Some(i) = item {
78 "{}::iter::once({}{})",
79 if is_no_std_crate(cx) { "core" } else { "std" },
80 iter_type.ref_prefix(),
81 snippet(cx, i.span, "...")
87 &format!("`{method_name}` call on a collection with only one item"),
90 Applicability::MaybeIncorrect,
95 ITER_ON_EMPTY_COLLECTIONS,
97 &format!("`{method_name}` call on an empty collection"),
99 if is_no_std_crate(cx) {
100 "core::iter::empty()".to_string()
102 "std::iter::empty()".to_string()
104 Applicability::MaybeIncorrect,