Skip to content

Commit 27bddcb

Browse files
committed
Speed up Vec::clear().
Currently it just calls `truncate(0)`. `truncate()` is (a) not marked as `#[inline]`, and (b) more general than needed for `clear()`. This commit changes `clear()` to do the work itself. This modest change was first proposed in #74172, where the reviewer rejected it because there was insufficient evidence that `Vec::clear()`'s performance mattered enough to justify the change. Recent changes within rustc have made `Vec::clear()` hot within `macro_parser.rs`, so the change is now clearly worthwhile. Note that this will also benefit `String::clear()`, because it just calls `Vec::clear()`.
1 parent 6a9080b commit 27bddcb

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

library/alloc/src/vec/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1881,7 +1881,18 @@ impl<T, A: Allocator> Vec<T, A> {
18811881
#[inline]
18821882
#[stable(feature = "rust1", since = "1.0.0")]
18831883
pub fn clear(&mut self) {
1884-
self.truncate(0)
1884+
let elems: *mut [T] = self.as_mut_slice();
1885+
1886+
// SAFETY:
1887+
// - `elems` comes directly from `as_mut_slice` and is therefore valid.
1888+
// - Setting `self.len` before calling `drop_in_place` means that,
1889+
// if an element's `Drop` impl panics, the vector's `Drop` impl will
1890+
// do nothing (leaking the rest of the elements) instead of dropping
1891+
// some twice.
1892+
unsafe {
1893+
self.len = 0;
1894+
ptr::drop_in_place(elems);
1895+
}
18851896
}
18861897

18871898
/// Returns the number of elements in the vector, also referred to

0 commit comments

Comments
 (0)