]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
Merge commit 'c4416f20dcaec5d93077f72470e83e150fb923b1' into sync-rustfmt
[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::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 }