1
- use clippy_utils:: diagnostics:: span_lint_and_help;
1
+ use clippy_utils:: diagnostics:: span_lint_and_then;
2
+ use clippy_utils:: macros:: macro_backtrace;
2
3
use clippy_utils:: source:: snippet;
3
4
use rustc_hir:: { Expr , ExprKind , Item , ItemKind , Node } ;
4
5
use rustc_lint:: { LateContext , LateLintPass } ;
5
6
use rustc_middle:: ty:: layout:: LayoutOf ;
6
7
use rustc_middle:: ty:: { self , ConstKind } ;
7
8
use rustc_session:: impl_lint_pass;
9
+ use rustc_span:: { sym, Span } ;
8
10
9
11
declare_clippy_lint ! {
10
12
/// ### What it does
@@ -39,6 +41,7 @@ impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]);
39
41
impl < ' tcx > LateLintPass < ' tcx > for LargeStackArrays {
40
42
fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
41
43
if let ExprKind :: Repeat ( _, _) | ExprKind :: Array ( _) = expr. kind
44
+ && !is_from_vec_macro ( cx, expr. span )
42
45
&& let ty:: Array ( element_type, cst) = cx. typeck_results ( ) . expr_ty ( expr) . kind ( )
43
46
&& let ConstKind :: Value ( ty:: ValTree :: Leaf ( element_count) ) = cst. kind ( )
44
47
&& let Ok ( element_count) = element_count. try_to_target_usize ( cx. tcx )
@@ -54,20 +57,28 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
54
57
} )
55
58
&& self . maximum_allowed_size < u128:: from ( element_count) * u128:: from ( element_size)
56
59
{
57
- span_lint_and_help (
60
+ span_lint_and_then (
58
61
cx,
59
62
LARGE_STACK_ARRAYS ,
60
63
expr. span ,
61
64
format ! (
62
65
"allocating a local array larger than {} bytes" ,
63
66
self . maximum_allowed_size
64
67
) ,
65
- None ,
66
- format ! (
67
- "consider allocating on the heap with `vec!{}.into_boxed_slice()`" ,
68
- snippet( cx, expr. span, "[...]" )
69
- ) ,
68
+ |diag| {
69
+ if !expr. span . from_expansion ( ) {
70
+ diag. help ( format ! (
71
+ "consider allocating on the heap with `vec!{}.into_boxed_slice()`" ,
72
+ snippet( cx, expr. span, "[...]" )
73
+ ) ) ;
74
+ }
75
+ } ,
70
76
) ;
71
77
}
72
78
}
73
79
}
80
+
81
+ /// We shouldn't lint messages if the expr is already in a `vec!` call
82
+ fn is_from_vec_macro ( cx : & LateContext < ' _ > , expr_span : Span ) -> bool {
83
+ macro_backtrace ( expr_span) . any ( |mac| cx. tcx . is_diagnostic_item ( sym:: vec_macro, mac. def_id ) )
84
+ }
0 commit comments