1 use crate::methods::derefs_to_slice;
2 use crate::utils::{get_parent_expr, higher, is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg};
3 use if_chain::if_chain;
5 use rustc_errors::Applicability;
7 use rustc_lint::LateContext;
9 use rustc_span::symbol::sym;
11 use super::ITER_NEXT_SLICE;
13 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) {
14 let caller_expr = &iter_args[0];
16 // Skip lint if the `iter().next()` expression is a for loop argument,
17 // since it is already covered by `&loops::ITER_NEXT_LOOP`
18 let mut parent_expr_opt = get_parent_expr(cx, expr);
19 while let Some(parent_expr) = parent_expr_opt {
20 if higher::for_loop(parent_expr).is_some() {
23 parent_expr_opt = get_parent_expr(cx, parent_expr);
26 if derefs_to_slice(cx, caller_expr, cx.typeck_results().expr_ty(caller_expr)).is_some() {
29 if let hir::ExprKind::Index(ref caller_var, ref index_expr) = &caller_expr.kind;
30 if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen })
31 = higher::range(index_expr);
32 if let hir::ExprKind::Lit(ref start_lit) = &start_expr.kind;
33 if let ast::LitKind::Int(start_idx, _) = start_lit.node;
35 let mut applicability = Applicability::MachineApplicable;
40 "using `.iter().next()` on a Slice without end index",
42 format!("{}.get({})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability), start_idx),
47 } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(caller_expr), sym::vec_type)
49 &cx.typeck_results().expr_ty(caller_expr).peel_refs().kind(),
53 // caller is a Vec or an Array
54 let mut applicability = Applicability::MachineApplicable;
59 "using `.iter().next()` on an array",
63 snippet_with_applicability(cx, caller_expr.span, "..", &mut applicability)