1
+ use std:: collections:: { BTreeMap , BTreeSet } ;
1
2
use std:: ops:: ControlFlow ;
2
3
3
4
use clippy_config:: msrvs:: { self , Msrv } ;
@@ -20,6 +21,8 @@ use rustc_span::{sym, Span};
20
21
pub struct UselessVec {
21
22
pub too_large_for_stack : u64 ,
22
23
pub msrv : Msrv ,
24
+ pub span_to_lint_map : BTreeMap < Span , Option < ( SuggestedType , String , Applicability ) > > ,
25
+ pub spans_sure_to_lint : BTreeSet < Span > ,
23
26
}
24
27
25
28
declare_clippy_lint ! {
@@ -70,9 +73,7 @@ pub fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
70
73
impl < ' tcx > LateLintPass < ' tcx > for UselessVec {
71
74
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
72
75
// search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]`
73
- if adjusts_to_slice ( cx, expr)
74
- && let Some ( vec_args) = higher:: VecArgs :: hir ( cx, expr. peel_borrows ( ) )
75
- {
76
+ if let Some ( vec_args) = higher:: VecArgs :: hir ( cx, expr. peel_borrows ( ) ) {
76
77
let ( suggest_slice, span) = if let ExprKind :: AddrOf ( BorrowKind :: Ref , mutability, _) = expr. kind {
77
78
// `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
78
79
( SuggestedType :: SliceRef ( mutability) , expr. span )
@@ -82,7 +83,11 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
82
83
( SuggestedType :: Array , expr. span . ctxt ( ) . outer_expn_data ( ) . call_site )
83
84
} ;
84
85
85
- self . check_vec_macro ( cx, & vec_args, span, suggest_slice) ;
86
+ if adjusts_to_slice ( cx, expr) {
87
+ self . check_vec_macro ( cx, & vec_args, span, suggest_slice) ;
88
+ } else if !self . spans_sure_to_lint . contains ( & span) {
89
+ self . span_to_lint_map . insert ( span, None ) ;
90
+ }
86
91
}
87
92
88
93
// search for `let foo = vec![_]` expressions where all uses of `foo`
@@ -110,12 +115,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
110
115
. is_continue ( ) ;
111
116
112
117
if only_slice_uses {
113
- self . check_vec_macro (
114
- cx,
115
- & vec_args,
116
- expr. span . ctxt ( ) . outer_expn_data ( ) . call_site ,
117
- SuggestedType :: Array ,
118
- ) ;
118
+ let span = expr. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
119
+ self . spans_sure_to_lint . insert ( span) ;
120
+ self . check_vec_macro ( cx, & vec_args, span, SuggestedType :: Array ) ;
119
121
}
120
122
}
121
123
@@ -126,15 +128,38 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
126
128
{
127
129
// report the error around the `vec!` not inside `<std macros>:`
128
130
let span = arg. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
131
+ self . spans_sure_to_lint . insert ( span) ;
129
132
self . check_vec_macro ( cx, & vec_args, span, SuggestedType :: Array ) ;
130
133
}
131
134
}
132
135
136
+ fn check_crate_post ( & mut self , cx : & LateContext < ' tcx > ) {
137
+ for ( span, lint_opt) in self . span_to_lint_map . clone ( ) {
138
+ if let Some ( ( suggest_slice, snippet, applicability) ) = lint_opt {
139
+ span_lint_and_sugg (
140
+ cx,
141
+ USELESS_VEC ,
142
+ span,
143
+ "useless use of `vec!`" ,
144
+ & format ! (
145
+ "you can use {} directly" ,
146
+ match suggest_slice {
147
+ SuggestedType :: SliceRef ( _) => "a slice" ,
148
+ SuggestedType :: Array => "an array" ,
149
+ }
150
+ ) ,
151
+ snippet,
152
+ applicability,
153
+ ) ;
154
+ }
155
+ }
156
+ }
157
+
133
158
extract_msrv_attr ! ( LateContext ) ;
134
159
}
135
160
136
161
#[ derive( Copy , Clone ) ]
137
- enum SuggestedType {
162
+ pub enum SuggestedType {
138
163
/// Suggest using a slice `&[..]` / `&mut [..]`
139
164
SliceRef ( Mutability ) ,
140
165
/// Suggest using an array: `[..]`
@@ -204,21 +229,10 @@ impl UselessVec {
204
229
} ,
205
230
} ;
206
231
207
- span_lint_and_sugg (
208
- cx,
209
- USELESS_VEC ,
210
- span,
211
- "useless use of `vec!`" ,
212
- & format ! (
213
- "you can use {} directly" ,
214
- match suggest_slice {
215
- SuggestedType :: SliceRef ( _) => "a slice" ,
216
- SuggestedType :: Array => "an array" ,
217
- }
218
- ) ,
219
- snippet,
220
- applicability,
221
- ) ;
232
+ if !self . span_to_lint_map . contains_key ( & span) || self . spans_sure_to_lint . contains ( & span) {
233
+ self . span_to_lint_map
234
+ . insert ( span, Some ( ( suggest_slice, snippet, applicability) ) ) ;
235
+ }
222
236
}
223
237
}
224
238
0 commit comments