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_lint::LateContext;
8 use rustc_middle::ty::TypeFoldable;
9 use rustc_span::symbol::sym;
10 use rustc_target::abi::LayoutOf;
11 use rustc_typeck::hir_ty_to_ty;
20 box_size_threshold: u64,
22 if cx.tcx.is_diagnostic_item(sym::vec_type, def_id) {
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),
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),
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;
51 "`Vec<T>` is already on the heap, the boxing is unnecessary",
53 format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
54 Applicability::MachineApplicable,