1 use super::SINGLE_ELEMENT_LOOP;
2 use clippy_utils::diagnostics::span_lint_and_sugg;
3 use clippy_utils::source::{indent_of, snippet_with_applicability};
4 use if_chain::if_chain;
5 use rustc_ast::util::parser::PREC_PREFIX;
6 use rustc_ast::Mutability;
7 use rustc_errors::Applicability;
8 use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat};
9 use rustc_lint::LateContext;
10 use rustc_span::edition::Edition;
12 pub(super) fn check<'tcx>(
13 cx: &LateContext<'tcx>,
19 let (arg_expression, prefix) = match arg.kind {
24 kind: ExprKind::Array([arg]),
32 kind: ExprKind::Array([arg]),
39 kind: ExprKind::Array([arg]),
44 ) if method.ident.name == rustc_span::sym::iter => (arg, "&"),
48 kind: ExprKind::Array([arg]),
53 ) if method.ident.name.as_str() == "iter_mut" => (arg, "&mut "),
57 kind: ExprKind::Array([arg]),
62 ) if method.ident.name == rustc_span::sym::into_iter => (arg, ""),
63 // Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise.
64 ExprKind::Array([arg]) if cx.tcx.sess.edition() >= Edition::Edition2021 => (arg, ""),
68 if let ExprKind::Block(block, _) = body.kind;
69 if !block.stmts.is_empty();
71 let mut applicability = Applicability::MachineApplicable;
72 let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
73 let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability);
74 let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned();
77 let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0));
79 // Reference iterator from `&(mut) []` or `[].iter(_mut)()`.
80 if !prefix.is_empty() && (
81 // Precedence of internal expression is less than or equal to precedence of `&expr`.
82 arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression)
84 arg_snip = format!("({arg_snip})").into();
91 "for loop over a single element",
93 format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"),