]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs
Auto merge of #105252 - bjorn3:codegen_less_pair_values, r=nagisa
[rust.git] / src / tools / clippy / clippy_lints / src / matches / match_on_vec_items.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet;
3 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
4 use if_chain::if_chain;
5 use rustc_errors::Applicability;
6 use rustc_hir::{Expr, ExprKind, LangItem};
7 use rustc_lint::LateContext;
8 use rustc_span::sym;
9
10 use super::MATCH_ON_VEC_ITEMS;
11
12 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) {
13     if_chain! {
14         if let Some(idx_expr) = is_vec_indexing(cx, scrutinee);
15         if let ExprKind::Index(vec, idx) = idx_expr.kind;
16
17         then {
18             // FIXME: could be improved to suggest surrounding every pattern with Some(_),
19             // but only when `or_patterns` are stabilized.
20             span_lint_and_sugg(
21                 cx,
22                 MATCH_ON_VEC_ITEMS,
23                 scrutinee.span,
24                 "indexing into a vector may panic",
25                 "try this",
26                 format!(
27                     "{}.get({})",
28                     snippet(cx, vec.span, ".."),
29                     snippet(cx, idx.span, "..")
30                 ),
31                 Applicability::MaybeIncorrect
32             );
33         }
34     }
35 }
36
37 fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
38     if_chain! {
39         if let ExprKind::Index(array, index) = expr.kind;
40         if is_vector(cx, array);
41         if !is_full_range(cx, index);
42
43         then {
44             return Some(expr);
45         }
46     }
47
48     None
49 }
50
51 fn is_vector(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
52     let ty = cx.typeck_results().expr_ty(expr);
53     let ty = ty.peel_refs();
54     is_type_diagnostic_item(cx, ty, sym::Vec)
55 }
56
57 fn is_full_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
58     let ty = cx.typeck_results().expr_ty(expr);
59     let ty = ty.peel_refs();
60     is_type_lang_item(cx, ty, LangItem::RangeFull)
61 }