@@ -37,15 +37,36 @@ use crate::rustc_errors::{Applicability};
37
37
declare_clippy_lint ! {
38
38
pub SLOW_VECTOR_INITIALIZATION ,
39
39
perf,
40
- "slow or unsafe vector initialization"
40
+ "slow vector initialization"
41
+ }
42
+
43
+ /// **What it does:** Checks unsafe vector initialization
44
+ ///
45
+ /// **Why is this bad?** Changing the length of a vector may expose uninitialized memory, which
46
+ /// can lead to memory safety issues
47
+ ///
48
+ /// **Known problems:** None.
49
+ ///
50
+ /// **Example:**
51
+ /// ```rust
52
+ /// let mut vec1 = Vec::with_capacity(len);
53
+ /// unsafe { vec1.set_len(len); }
54
+ /// ```
55
+ declare_clippy_lint ! {
56
+ pub UNSAFE_VECTOR_INITIALIZATION ,
57
+ correctness,
58
+ "unsafe vector initialization"
41
59
}
42
60
43
61
#[ derive( Copy , Clone , Default ) ]
44
62
pub struct Pass ;
45
63
46
64
impl LintPass for Pass {
47
65
fn get_lints ( & self ) -> LintArray {
48
- lint_array ! ( SLOW_VECTOR_INITIALIZATION )
66
+ lint_array ! (
67
+ SLOW_VECTOR_INITIALIZATION ,
68
+ UNSAFE_VECTOR_INITIALIZATION ,
69
+ )
49
70
}
50
71
}
51
72
@@ -96,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
96
117
len_expr: len_arg,
97
118
} ;
98
119
99
- Pass :: search_slow_initialization( cx, vi, expr. id, expr . span ) ;
120
+ Pass :: search_slow_initialization( cx, vi, expr. id) ;
100
121
}
101
122
}
102
123
}
@@ -117,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
117
138
len_expr: len_arg,
118
139
} ;
119
140
120
- Pass :: search_slow_initialization( cx, vi, stmt. node. id( ) , stmt . span ) ;
141
+ Pass :: search_slow_initialization( cx, vi, stmt. node. id( ) ) ;
121
142
}
122
143
}
123
144
}
@@ -145,8 +166,7 @@ impl Pass {
145
166
fn search_slow_initialization < ' tcx > (
146
167
cx : & LateContext < ' _ , ' tcx > ,
147
168
vec_initialization : VecInitialization < ' tcx > ,
148
- parent_node : NodeId ,
149
- parent_span : Span
169
+ parent_node : NodeId
150
170
) {
151
171
let enclosing_body = get_enclosing_block ( cx, parent_node) ;
152
172
@@ -163,30 +183,54 @@ impl Pass {
163
183
164
184
v. visit_block ( enclosing_body. unwrap ( ) ) ;
165
185
166
- if let Some ( ref repeat_expr) = v. slow_expression {
167
- span_lint_and_then (
168
- cx,
169
- SLOW_VECTOR_INITIALIZATION ,
170
- parent_span,
171
- "detected slow zero-filling initialization" ,
172
- |db| {
173
- db. span_suggestion_with_applicability ( v. vec_ini . initialization_expr . span , "consider replacing with" , "vec![0; ..]" . to_string ( ) , Applicability :: Unspecified ) ;
174
-
175
- match repeat_expr {
176
- InitializationType :: Extend ( e) => {
177
- db. span_note ( e. span , "extended at" ) ;
178
- } ,
179
- InitializationType :: Resize ( e) => {
180
- db. span_note ( e. span , "resized at" ) ;
181
- } ,
182
- InitializationType :: UnsafeSetLen ( e) => {
183
- db. span_note ( e. span , "changed len at" ) ;
184
- } ,
185
- }
186
- }
187
- ) ;
186
+ if let Some ( ref initialization_expr) = v. slow_expression {
187
+ let alloc_span = v. vec_ini . initialization_expr . span ;
188
+ Pass :: lint_initialization ( cx, initialization_expr, alloc_span) ;
188
189
}
189
190
}
191
+
192
+ fn lint_initialization < ' tcx > ( cx : & LateContext < ' _ , ' tcx > , initialization : & InitializationType < ' tcx > , alloc_span : Span ) {
193
+ match initialization {
194
+ InitializationType :: UnsafeSetLen ( e) =>
195
+ Pass :: lint_unsafe_initialization ( cx, e, alloc_span) ,
196
+
197
+ InitializationType :: Extend ( e) |
198
+ InitializationType :: Resize ( e) =>
199
+ Pass :: lint_slow_initialization ( cx, e, alloc_span) ,
200
+ } ;
201
+ }
202
+
203
+ fn lint_slow_initialization < ' tcx > (
204
+ cx : & LateContext < ' _ , ' tcx > ,
205
+ slow_fill : & Expr ,
206
+ alloc_span : Span ,
207
+ ) {
208
+ span_lint_and_then (
209
+ cx,
210
+ SLOW_VECTOR_INITIALIZATION ,
211
+ slow_fill. span ,
212
+ "detected slow zero-filling initialization" ,
213
+ |db| {
214
+ db. span_suggestion_with_applicability ( alloc_span, "consider replacing with" , "vec![0; ..]" . to_string ( ) , Applicability :: Unspecified ) ;
215
+ }
216
+ ) ;
217
+ }
218
+
219
+ fn lint_unsafe_initialization < ' tcx > (
220
+ cx : & LateContext < ' _ , ' tcx > ,
221
+ slow_fill : & Expr ,
222
+ alloc_span : Span ,
223
+ ) {
224
+ span_lint_and_then (
225
+ cx,
226
+ UNSAFE_VECTOR_INITIALIZATION ,
227
+ slow_fill. span ,
228
+ "detected unsafe vector initialization" ,
229
+ |db| {
230
+ db. span_suggestion_with_applicability ( alloc_span, "consider replacing with" , "vec![0; ..]" . to_string ( ) , Applicability :: Unspecified ) ;
231
+ }
232
+ ) ;
233
+ }
190
234
}
191
235
192
236
/// SlowInitializationVisitor searches for slow zero filling vector initialization, for the given
0 commit comments