Skip to content

Commit 051cf46

Browse files
committed
Guarantee vec.clear/truncate is O(1) for trivial types
1 parent 74d5c70 commit 051cf46

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

src/liballoc/vec.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -685,21 +685,25 @@ impl<T> Vec<T> {
685685
/// [`drain`]: #method.drain
686686
#[stable(feature = "rust1", since = "1.0.0")]
687687
pub fn truncate(&mut self, len: usize) {
688-
let current_len = self.len;
689-
unsafe {
690-
let mut ptr = self.as_mut_ptr().add(self.len);
691-
// Set the final length at the end, keeping in mind that
692-
// dropping an element might panic. Works around a missed
693-
// optimization, as seen in the following issue:
694-
// https://github.com/rust-lang/rust/issues/51802
695-
let mut local_len = SetLenOnDrop::new(&mut self.len);
688+
if mem::needs_drop::<T>() {
689+
let current_len = self.len;
690+
unsafe {
691+
let mut ptr = self.as_mut_ptr().add(self.len);
692+
// Set the final length at the end, keeping in mind that
693+
// dropping an element might panic. Works around a missed
694+
// optimization, as seen in the following issue:
695+
// https://github.com/rust-lang/rust/issues/51802
696+
let mut local_len = SetLenOnDrop::new(&mut self.len);
696697

697-
// drop any extra elements
698-
for _ in len..current_len {
699-
local_len.decrement_len(1);
700-
ptr = ptr.offset(-1);
701-
ptr::drop_in_place(ptr);
698+
// drop any extra elements
699+
for _ in len..current_len {
700+
local_len.decrement_len(1);
701+
ptr = ptr.offset(-1);
702+
ptr::drop_in_place(ptr);
703+
}
702704
}
705+
} else if len < self.len {
706+
self.len = len;
703707
}
704708
}
705709

0 commit comments

Comments
 (0)