]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/types/vec_box.rs
Rollup merge of #102721 - nbdd0121:panic, r=Amanieu
[rust.git] / src / tools / clippy / clippy_lints / src / types / vec_box.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::last_path_segment;
3 use clippy_utils::source::snippet;
4 use if_chain::if_chain;
5 use rustc_errors::Applicability;
6 use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
7 use rustc_hir_analysis::hir_ty_to_ty;
8 use rustc_lint::LateContext;
9 use rustc_middle::ty::layout::LayoutOf;
10 use rustc_middle::ty::TypeVisitable;
11 use rustc_span::symbol::sym;
12
13 use super::VEC_BOX;
14
15 pub(super) fn check(
16     cx: &LateContext<'_>,
17     hir_ty: &hir::Ty<'_>,
18     qpath: &QPath<'_>,
19     def_id: DefId,
20     box_size_threshold: u64,
21 ) -> bool {
22     if cx.tcx.is_diagnostic_item(sym::Vec, def_id) {
23         if_chain! {
24             // Get the _ part of Vec<_>
25             if let Some(last) = last_path_segment(qpath).args;
26             if let Some(ty) = last.args.iter().find_map(|arg| match arg {
27                 GenericArg::Type(ty) => Some(ty),
28                 _ => None,
29             });
30             // ty is now _ at this point
31             if let TyKind::Path(ref ty_qpath) = ty.kind;
32             let res = cx.qpath_res(ty_qpath, ty.hir_id);
33             if let Some(def_id) = res.opt_def_id();
34             if Some(def_id) == cx.tcx.lang_items().owned_box();
35             // At this point, we know ty is Box<T>, now get T
36             if let Some(last) = last_path_segment(ty_qpath).args;
37             if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg {
38                 GenericArg::Type(ty) => Some(ty),
39                 _ => None,
40             });
41             let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
42             if !ty_ty.has_escaping_bound_vars();
43             if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env);
44             if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes());
45             if ty_ty_size <= box_size_threshold;
46             then {
47                 span_lint_and_sugg(
48                     cx,
49                     VEC_BOX,
50                     hir_ty.span,
51                     "`Vec<T>` is already on the heap, the boxing is unnecessary",
52                     "try",
53                     format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
54                     Applicability::MachineApplicable,
55                 );
56                 true
57             } else {
58                 false
59             }
60         }
61     } else {
62         false
63     }
64 }