1- use crate :: consts:: constant;
1+ use crate :: consts:: { constant, Constant } ;
2+ use crate :: rustc_target:: abi:: LayoutOf ;
23use crate :: utils:: { higher, is_copy, snippet_with_applicability, span_lint_and_sugg} ;
34use if_chain:: if_chain;
45use rustc_errors:: Applicability ;
56use rustc_hir:: { BorrowKind , Expr , ExprKind } ;
67use rustc_lint:: { LateContext , LateLintPass } ;
78use 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 } ;
910use rustc_span:: source_map:: Span ;
1011
12+ #[ allow( clippy:: module_name_repetitions) ]
13+ #[ derive( Copy , Clone ) ]
14+ pub struct UselessVec {
15+ pub too_large_for_stack : u64 ,
16+ }
17+
1118declare_clippy_lint ! {
1219 /// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
1320 /// be possible.
@@ -31,7 +38,7 @@ declare_clippy_lint! {
3138 "useless `vec!`"
3239}
3340
34- declare_lint_pass ! ( UselessVec => [ USELESS_VEC ] ) ;
41+ impl_lint_pass ! ( UselessVec => [ USELESS_VEC ] ) ;
3542
3643impl < ' tcx > LateLintPass < ' tcx > for UselessVec {
3744 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
@@ -42,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
4249 if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, ref addressee) = expr. kind;
4350 if let Some ( vec_args) = higher:: vec_macro( cx, addressee) ;
4451 then {
45- check_vec_macro( cx, & vec_args, expr. span) ;
52+ self . check_vec_macro( cx, & vec_args, expr. span) ;
4653 }
4754 }
4855
@@ -60,46 +67,62 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
6067 . ctxt( )
6168 . outer_expn_data( )
6269 . call_site;
63- check_vec_macro( cx, & vec_args, span) ;
70+ self . check_vec_macro( cx, & vec_args, span) ;
6471 }
6572 }
6673 }
6774}
6875
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+ }
8686
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+ }
93122
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 ( ) )
103126}
104127
105128/// Returns the item type of the vector (i.e., the `T` in `Vec<T>`).
0 commit comments