1 use clippy_utils::diagnostics::span_lint_and_help;
2 use clippy_utils::source::snippet;
3 use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
4 use rustc_lint::{LateContext, LateLintPass};
5 use rustc_middle::ty::layout::LayoutOf;
6 use rustc_middle::ty::{self, ConstKind};
7 use rustc_session::{declare_tool_lint, impl_lint_pass};
11 /// Checks for local arrays that may be too large.
13 /// ### Why is this bad?
14 /// Large local arrays may cause stack overflow.
18 /// let a = [0u32; 1_000_000];
20 #[clippy::version = "1.41.0"]
21 pub LARGE_STACK_ARRAYS,
23 "allocating large arrays on stack may cause stack overflow"
26 pub struct LargeStackArrays {
27 maximum_allowed_size: u64,
30 impl LargeStackArrays {
32 pub fn new(maximum_allowed_size: u64) -> Self {
33 Self { maximum_allowed_size }
37 impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]);
39 impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
40 fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
41 if let ExprKind::Repeat(_, _) = expr.kind
42 && let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
43 && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
44 && let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx)
45 && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
46 && !cx.tcx.hir().parent_iter(expr.hir_id)
47 .any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. })))
48 && self.maximum_allowed_size < element_count * element_size {
54 "allocating a local array larger than {} bytes",
55 self.maximum_allowed_size
59 "consider allocating on the heap with `vec!{}.into_boxed_slice()`",
60 snippet(cx, expr.span, "[...]")