Skip to content
/ rust Public
forked from rust-lang/rust

Commit add2722

Browse files
committed
Auto merge of rust-lang#11310 - y21:slow_vector_initialization_doc, r=xFrednet,djc
[`slow_vector_initialization`]: clarify why `Vec::new()` + resize is worse rust-lang#11198 extended this lint to also warn on `Vec::new()` + `resize(0, len)`, but did not update the lint documentation, so it left some confused (rust-lang/rust-clippy#10938 (comment)). This PR should make it a bit more clear. (cc `@djc` `@vi` what do you think about this?) <details> <summary>More details</summary> Godbolt for `Vec::new()` + `.resize(x, 0)`: https://godbolt.org/z/e7q9xc9rG The resize call first does a normal allocation (`__rust_alloc`): ```asm alloc::raw_vec::finish_grow: ... cmp qword ptr [rcx + 8], 0 je .LBB1_7 ; if capacity == 0 -> LBB1_7 .LBB1_7: ... call qword ptr [rip + __rust_alloc@GOTPCREL] ``` *Then* a memset for zero initialization: ```asm example::f: ... xor esi, esi ; 0 call qword ptr [rip + memset@GOTPCREL] ``` ------------ Godbolt for `vec![0; len]`: https://godbolt.org/z/M3vr53vWY Important bit: ```asm example::f: ... call qword ptr [rip + __rust_alloc_zeroed@GOTPCREL] ``` </details> changelog: [`slow_vector_initialization`]: clarify why `Vec::new()` + resize is worse than `vec![0; len]`
2 parents 7c595b4 + dd25cc3 commit add2722

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

clippy_lints/src/slow_vector_initialization.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,35 @@ declare_clippy_lint! {
2020
/// These structures are non-idiomatic and less efficient than simply using
2121
/// `vec![0; len]`.
2222
///
23+
/// Specifically, for `vec![0; len]`, the compiler can use a specialized type of allocation
24+
/// that also zero-initializes the allocated memory in the same call
25+
/// (see: [alloc_zeroed](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#method.alloc_zeroed)).
26+
///
27+
/// Writing `Vec::new()` followed by `vec.resize(len, 0)` is suboptimal because,
28+
/// while it does do the same number of allocations,
29+
/// it involves two operations for allocating and initializing.
30+
/// The `resize` call first allocates memory (since `Vec::new()` did not), and only *then* zero-initializes it.
31+
///
2332
/// ### Example
2433
/// ```rust
2534
/// # use core::iter::repeat;
2635
/// # let len = 4;
27-
/// let mut vec1 = Vec::with_capacity(len);
36+
/// let mut vec1 = Vec::new();
2837
/// vec1.resize(len, 0);
2938
///
30-
/// let mut vec1 = Vec::with_capacity(len);
31-
/// vec1.resize(vec1.capacity(), 0);
32-
///
3339
/// let mut vec2 = Vec::with_capacity(len);
34-
/// vec2.extend(repeat(0).take(len));
40+
/// vec2.resize(len, 0);
41+
///
42+
/// let mut vec3 = Vec::with_capacity(len);
43+
/// vec3.extend(repeat(0).take(len));
3544
/// ```
3645
///
3746
/// Use instead:
3847
/// ```rust
3948
/// # let len = 4;
4049
/// let mut vec1 = vec![0; len];
4150
/// let mut vec2 = vec![0; len];
51+
/// let mut vec3 = vec![0; len];
4252
/// ```
4353
#[clippy::version = "1.32.0"]
4454
pub SLOW_VECTOR_INITIALIZATION,

0 commit comments

Comments
 (0)