]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / methods / get_last_with_len.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet_with_applicability;
3 use clippy_utils::SpanlessEq;
4 use rustc_ast::LitKind;
5 use rustc_errors::Applicability;
6 use rustc_hir::{BinOpKind, Expr, ExprKind};
7 use rustc_lint::LateContext;
8 use rustc_middle::ty;
9 use rustc_span::source_map::Spanned;
10 use rustc_span::sym;
11
12 use super::GET_LAST_WITH_LEN;
13
14 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) {
15 // Argument to "get" is a subtraction
16 if let ExprKind::Binary(
17 Spanned {
18 node: BinOpKind::Sub, ..
19 },
20 lhs,
21 rhs,
22 ) = arg.kind
23
24 // LHS of subtraction is "x.len()"
25 && let ExprKind::MethodCall(lhs_path, lhs_recv, [], _) = &lhs.kind
26 && lhs_path.ident.name == sym::len
27
28 // RHS of subtraction is 1
29 && let ExprKind::Lit(rhs_lit) = &rhs.kind
30 && let LitKind::Int(1, ..) = rhs_lit.node
31
32 // check that recv == lhs_recv `recv.get(lhs_recv.len() - 1)`
33 && SpanlessEq::new(cx).eq_expr(recv, lhs_recv)
34 && !recv.can_have_side_effects()
35 {
36 let method = match cx.typeck_results().expr_ty_adjusted(recv).peel_refs().kind() {
37 ty::Adt(def, _) if cx.tcx.is_diagnostic_item(sym::VecDeque, def.did()) => "back",
38 ty::Slice(_) => "last",
39 _ => return,
40 };
41
42 let mut applicability = Applicability::MachineApplicable;
43 let recv_snippet = snippet_with_applicability(cx, recv.span, "_", &mut applicability);
44
45 span_lint_and_sugg(
46 cx,
47 GET_LAST_WITH_LEN,
48 expr.span,
49 &format!("accessing last element with `{recv_snippet}.get({recv_snippet}.len() - 1)`"),
50 "try",
51 format!("{recv_snippet}.{method}()"),
52 applicability,
53 );
54 }
55 }