Skip to content

Commit 9b4bc3b

Browse files
committed
Add unsafe set_len initialization
1 parent e0ccc9d commit 9b4bc3b

File tree

3 files changed

+92
-43
lines changed

3 files changed

+92
-43
lines changed

clippy_lints/src/slow_vector_initialization.rs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ enum InitializationType<'tcx> {
7171

7272
/// Resize is a slow initialization with the form `vec.resize(.., 0)`
7373
Resize(&'tcx Expr),
74+
75+
/// UnsafeSetLen is a slow initialization with the form `vec.set_len(..)`
76+
UnsafeSetLen(&'tcx Expr),
7477
}
7578

7679
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
@@ -93,7 +96,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
9396
len_expr: len_arg,
9497
};
9598

96-
Pass::search_slow_zero_filling(cx, vi, expr.id, expr.span);
99+
Pass::search_slow_initialization(cx, vi, expr.id, expr.span);
97100
}
98101
}
99102
}
@@ -114,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
114117
len_expr: len_arg,
115118
};
116119

117-
Pass::search_slow_zero_filling(cx, vi, stmt.node.id(), stmt.span);
120+
Pass::search_slow_initialization(cx, vi, stmt.node.id(), stmt.span);
118121
}
119122
}
120123
}
@@ -138,8 +141,8 @@ impl Pass {
138141
None
139142
}
140143

141-
/// Search for slow zero filling vector initialization for the given vector
142-
fn search_slow_zero_filling<'tcx>(
144+
/// Search a slow initialization for the given vector
145+
fn search_slow_initialization<'tcx>(
143146
cx: &LateContext<'_, 'tcx>,
144147
vec_initialization: VecInitialization<'tcx>,
145148
parent_node: NodeId,
@@ -171,11 +174,14 @@ impl Pass {
171174

172175
match repeat_expr {
173176
InitializationType::Extend(e) => {
174-
db.span_note(e.span, "extended here with .. 0");
177+
db.span_note(e.span, "extended at");
175178
},
176179
InitializationType::Resize(e) => {
177-
db.span_note(e.span, "resize here with .. 0");
178-
}
180+
db.span_note(e.span, "resized at");
181+
},
182+
InitializationType::UnsafeSetLen(e) => {
183+
db.span_note(e.span, "changed len at");
184+
},
179185
}
180186
}
181187
);
@@ -239,6 +245,25 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> {
239245
}
240246
}
241247

248+
/// Checks if the given expression is using `set_len` to initialize the vector
249+
fn search_unsafe_set_len(&mut self, expr: &'tcx Expr) {
250+
if_chain! {
251+
if self.initialization_found;
252+
if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
253+
if let ExprKind::Path(ref qpath_subj) = args[0].node;
254+
if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]);
255+
if path.ident.name == "set_len";
256+
if let Some(ref len_arg) = args.get(1);
257+
258+
// Check that len expression is equals to `with_capacity` expression
259+
if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr);
260+
261+
then {
262+
self.slow_expression = Some(InitializationType::UnsafeSetLen(expr));
263+
}
264+
}
265+
}
266+
242267
/// Returns `true` if give expression is `repeat(0).take(...)`
243268
fn is_repeat_take(&self, expr: &Expr) -> bool {
244269
if_chain! {
@@ -294,6 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SlowInitializationVisitor<'a, 'tcx> {
294319

295320
self.search_slow_extend_filling(expr);
296321
self.search_slow_resize_filling(expr);
322+
self.search_unsafe_set_len(expr);
297323

298324
walk_expr(self, expr);
299325
}

tests/ui/slow_vector_initialization.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ fn main() {
1313
resize_vector();
1414
extend_vector();
1515
mixed_extend_resize_vector();
16+
unsafe_vector();
1617
}
1718

1819
fn extend_vector() {
@@ -61,3 +62,11 @@ fn resize_vector() {
6162
vec1 = Vec::with_capacity(10);
6263
vec1.resize(10, 0);
6364
}
65+
66+
fn unsafe_vector() {
67+
let mut unsafe_vec: Vec<u8> = Vec::with_capacity(200);
68+
69+
unsafe {
70+
unsafe_vec.set_len(200);
71+
}
72+
}
Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,115 @@
11
error: detected slow zero-filling initialization
2-
--> $DIR/slow_vector_initialization.rs:21:5
2+
--> $DIR/slow_vector_initialization.rs:22:5
33
|
4-
21 | let mut vec1 = Vec::with_capacity(len);
4+
22 | let mut vec1 = Vec::with_capacity(len);
55
| ^^^^^^^^^^^^^^^-----------------------^
66
| |
77
| help: consider replacing with: `vec![0; ..]`
88
|
99
= note: `-D clippy::slow-vector-initialization` implied by `-D warnings`
10-
note: extended here with .. 0
11-
--> $DIR/slow_vector_initialization.rs:22:5
10+
note: extended at
11+
--> $DIR/slow_vector_initialization.rs:23:5
1212
|
13-
22 | vec1.extend(repeat(0).take(len));
13+
23 | vec1.extend(repeat(0).take(len));
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1515

1616
error: detected slow zero-filling initialization
17-
--> $DIR/slow_vector_initialization.rs:25:5
17+
--> $DIR/slow_vector_initialization.rs:26:5
1818
|
19-
25 | let mut vec2 = Vec::with_capacity(len - 10);
19+
26 | let mut vec2 = Vec::with_capacity(len - 10);
2020
| ^^^^^^^^^^^^^^^----------------------------^
2121
| |
2222
| help: consider replacing with: `vec![0; ..]`
2323
|
24-
note: extended here with .. 0
25-
--> $DIR/slow_vector_initialization.rs:26:5
24+
note: extended at
25+
--> $DIR/slow_vector_initialization.rs:27:5
2626
|
27-
26 | vec2.extend(repeat(0).take(len - 10));
27+
27 | vec2.extend(repeat(0).take(len - 10));
2828
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2929

3030
error: detected slow zero-filling initialization
31-
--> $DIR/slow_vector_initialization.rs:38:5
31+
--> $DIR/slow_vector_initialization.rs:39:5
3232
|
33-
38 | let mut resized_vec = Vec::with_capacity(30);
33+
39 | let mut resized_vec = Vec::with_capacity(30);
3434
| ^^^^^^^^^^^^^^^^^^^^^^----------------------^
3535
| |
3636
| help: consider replacing with: `vec![0; ..]`
3737
|
38-
note: resize here with .. 0
39-
--> $DIR/slow_vector_initialization.rs:41:5
38+
note: resized at
39+
--> $DIR/slow_vector_initialization.rs:42:5
4040
|
41-
41 | resized_vec.resize(30, 0);
41+
42 | resized_vec.resize(30, 0);
4242
| ^^^^^^^^^^^^^^^^^^^^^^^^^
4343

4444
error: detected slow zero-filling initialization
45-
--> $DIR/slow_vector_initialization.rs:39:5
45+
--> $DIR/slow_vector_initialization.rs:40:5
4646
|
47-
39 | let mut extend_vec = Vec::with_capacity(30);
47+
40 | let mut extend_vec = Vec::with_capacity(30);
4848
| ^^^^^^^^^^^^^^^^^^^^^----------------------^
4949
| |
5050
| help: consider replacing with: `vec![0; ..]`
5151
|
52-
note: extended here with .. 0
53-
--> $DIR/slow_vector_initialization.rs:43:5
52+
note: extended at
53+
--> $DIR/slow_vector_initialization.rs:44:5
5454
|
55-
43 | extend_vec.extend(repeat(0).take(30));
55+
44 | extend_vec.extend(repeat(0).take(30));
5656
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5757

5858
error: detected slow zero-filling initialization
59-
--> $DIR/slow_vector_initialization.rs:49:5
59+
--> $DIR/slow_vector_initialization.rs:50:5
6060
|
61-
49 | let mut vec1 = Vec::with_capacity(len);
61+
50 | let mut vec1 = Vec::with_capacity(len);
6262
| ^^^^^^^^^^^^^^^-----------------------^
6363
| |
6464
| help: consider replacing with: `vec![0; ..]`
6565
|
66-
note: resize here with .. 0
67-
--> $DIR/slow_vector_initialization.rs:50:5
66+
note: resized at
67+
--> $DIR/slow_vector_initialization.rs:51:5
6868
|
69-
50 | vec1.resize(len, 0);
69+
51 | vec1.resize(len, 0);
7070
| ^^^^^^^^^^^^^^^^^^^
7171

7272
error: detected slow zero-filling initialization
73-
--> $DIR/slow_vector_initialization.rs:57:5
73+
--> $DIR/slow_vector_initialization.rs:58:5
7474
|
75-
57 | let mut vec3 = Vec::with_capacity(len - 10);
75+
58 | let mut vec3 = Vec::with_capacity(len - 10);
7676
| ^^^^^^^^^^^^^^^----------------------------^
7777
| |
7878
| help: consider replacing with: `vec![0; ..]`
7979
|
80-
note: resize here with .. 0
81-
--> $DIR/slow_vector_initialization.rs:58:5
80+
note: resized at
81+
--> $DIR/slow_vector_initialization.rs:59:5
8282
|
83-
58 | vec3.resize(len - 10, 0);
83+
59 | vec3.resize(len - 10, 0);
8484
| ^^^^^^^^^^^^^^^^^^^^^^^^
8585

8686
error: detected slow zero-filling initialization
87-
--> $DIR/slow_vector_initialization.rs:61:5
87+
--> $DIR/slow_vector_initialization.rs:62:5
8888
|
89-
61 | vec1 = Vec::with_capacity(10);
89+
62 | vec1 = Vec::with_capacity(10);
9090
| ^^^^^^^----------------------
9191
| |
9292
| help: consider replacing with: `vec![0; ..]`
9393
|
94-
note: resize here with .. 0
95-
--> $DIR/slow_vector_initialization.rs:62:5
94+
note: resized at
95+
--> $DIR/slow_vector_initialization.rs:63:5
9696
|
97-
62 | vec1.resize(10, 0);
97+
63 | vec1.resize(10, 0);
9898
| ^^^^^^^^^^^^^^^^^^
9999

100-
error: aborting due to 7 previous errors
100+
error: detected slow zero-filling initialization
101+
--> $DIR/slow_vector_initialization.rs:67:5
102+
|
103+
67 | let mut unsafe_vec: Vec<u8> = Vec::with_capacity(200);
104+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^
105+
| |
106+
| help: consider replacing with: `vec![0; ..]`
107+
|
108+
note: changed len at
109+
--> $DIR/slow_vector_initialization.rs:70:9
110+
|
111+
70 | unsafe_vec.set_len(200);
112+
| ^^^^^^^^^^^^^^^^^^^^^^^
113+
114+
error: aborting due to 8 previous errors
101115

0 commit comments

Comments
 (0)