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