]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs
New upstream version 1.63.0+dfsg1
[rustc.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 }