1
- use crate :: consts:: constant;
1
+ use crate :: consts:: { constant, Constant } ;
2
+ use crate :: rustc_target:: abi:: LayoutOf ;
2
3
use crate :: utils:: { higher, is_copy, snippet_with_applicability, span_lint_and_sugg} ;
3
4
use if_chain:: if_chain;
4
5
use rustc_errors:: Applicability ;
5
6
use rustc_hir:: { BorrowKind , Expr , ExprKind } ;
6
7
use rustc_lint:: { LateContext , LateLintPass } ;
7
8
use rustc_middle:: ty:: { self , Ty } ;
8
- use rustc_session:: { declare_lint_pass , declare_tool_lint } ;
9
+ use rustc_session:: { declare_tool_lint , impl_lint_pass } ;
9
10
use rustc_span:: source_map:: Span ;
10
11
12
+ #[ allow( clippy:: module_name_repetitions) ]
13
+ #[ derive( Copy , Clone ) ]
14
+ pub struct UselessVec {
15
+ pub too_large_for_stack : u64 ,
16
+ }
17
+
11
18
declare_clippy_lint ! {
12
19
/// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
13
20
/// be possible.
@@ -31,7 +38,7 @@ declare_clippy_lint! {
31
38
"useless `vec!`"
32
39
}
33
40
34
- declare_lint_pass ! ( UselessVec => [ USELESS_VEC ] ) ;
41
+ impl_lint_pass ! ( UselessVec => [ USELESS_VEC ] ) ;
35
42
36
43
impl < ' tcx > LateLintPass < ' tcx > for UselessVec {
37
44
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
@@ -42,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
42
49
if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, ref addressee) = expr. kind;
43
50
if let Some ( vec_args) = higher:: vec_macro( cx, addressee) ;
44
51
then {
45
- check_vec_macro( cx, & vec_args, expr. span) ;
52
+ self . check_vec_macro( cx, & vec_args, expr. span) ;
46
53
}
47
54
}
48
55
@@ -60,46 +67,62 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
60
67
. ctxt( )
61
68
. outer_expn_data( )
62
69
. call_site;
63
- check_vec_macro( cx, & vec_args, span) ;
70
+ self . check_vec_macro( cx, & vec_args, span) ;
64
71
}
65
72
}
66
73
}
67
74
}
68
75
69
- fn check_vec_macro < ' tcx > ( cx : & LateContext < ' tcx > , vec_args : & higher:: VecArgs < ' tcx > , span : Span ) {
70
- let mut applicability = Applicability :: MachineApplicable ;
71
- let snippet = match * vec_args {
72
- higher:: VecArgs :: Repeat ( elem, len) => {
73
- if constant ( cx, cx. typeck_results ( ) , len) . is_some ( ) {
74
- format ! (
75
- "&[{}; {}]" ,
76
- snippet_with_applicability( cx, elem. span, "elem" , & mut applicability) ,
77
- snippet_with_applicability( cx, len. span, "len" , & mut applicability)
78
- )
79
- } else {
80
- return ;
81
- }
82
- } ,
83
- higher:: VecArgs :: Vec ( args) => {
84
- if let Some ( last) = args. iter ( ) . last ( ) {
85
- let span = args[ 0 ] . span . to ( last. span ) ;
76
+ impl UselessVec {
77
+ fn check_vec_macro < ' tcx > ( self , cx : & LateContext < ' tcx > , vec_args : & higher:: VecArgs < ' tcx > , span : Span ) {
78
+ let mut applicability = Applicability :: MachineApplicable ;
79
+ let snippet = match * vec_args {
80
+ higher:: VecArgs :: Repeat ( elem, len) => {
81
+ if let Some ( ( Constant :: Int ( len_constant) , _) ) = constant ( cx, cx. typeck_results ( ) , len) {
82
+ #[ allow( clippy:: cast_possible_truncation) ]
83
+ if len_constant as u64 * size_of ( cx, elem) > self . too_large_for_stack {
84
+ return ;
85
+ }
86
86
87
- format ! ( "&[{}]" , snippet_with_applicability( cx, span, ".." , & mut applicability) )
88
- } else {
89
- "&[]" . into ( )
90
- }
91
- } ,
92
- } ;
87
+ format ! (
88
+ "&[{}; {}]" ,
89
+ snippet_with_applicability( cx, elem. span, "elem" , & mut applicability) ,
90
+ snippet_with_applicability( cx, len. span, "len" , & mut applicability)
91
+ )
92
+ } else {
93
+ return ;
94
+ }
95
+ } ,
96
+ higher:: VecArgs :: Vec ( args) => {
97
+ if let Some ( last) = args. iter ( ) . last ( ) {
98
+ #[ allow( clippy:: cast_possible_truncation) ]
99
+ if args. len ( ) as u64 * size_of ( cx, last) > self . too_large_for_stack {
100
+ return ;
101
+ }
102
+ let span = args[ 0 ] . span . to ( last. span ) ;
103
+
104
+ format ! ( "&[{}]" , snippet_with_applicability( cx, span, ".." , & mut applicability) )
105
+ } else {
106
+ "&[]" . into ( )
107
+ }
108
+ } ,
109
+ } ;
110
+
111
+ span_lint_and_sugg (
112
+ cx,
113
+ USELESS_VEC ,
114
+ span,
115
+ "useless use of `vec!`" ,
116
+ "you can use a slice directly" ,
117
+ snippet,
118
+ applicability,
119
+ ) ;
120
+ }
121
+ }
93
122
94
- span_lint_and_sugg (
95
- cx,
96
- USELESS_VEC ,
97
- span,
98
- "useless use of `vec!`" ,
99
- "you can use a slice directly" ,
100
- snippet,
101
- applicability,
102
- ) ;
123
+ fn size_of ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> u64 {
124
+ let ty = cx. typeck_results ( ) . expr_ty_adjusted ( expr) ;
125
+ cx. layout_of ( ty) . map_or ( 0 , |l| l. size . bytes ( ) )
103
126
}
104
127
105
128
/// Returns the item type of the vector (i.e., the `T` in `Vec<T>`).
0 commit comments