diff options
| author | Kornel <kornel@geekhood.net> | 2019-09-11 11:46:53 +0100 |
|---|---|---|
| committer | Kornel <kornel@geekhood.net> | 2019-09-11 20:14:23 +0100 |
| commit | 223600ac2c23715f350ceae7f315f5056aae6fc0 (patch) | |
| tree | 6f4a2f644a3efb0763bd8f8acce8f1938bd10f6b /src/liballoc | |
| parent | 74d5c70b174f06843049af2d764ff57ddc81c81c (diff) | |
Guarantee vec.clear/truncate is O(1) for trivial types
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/vec.rs | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d5dc2d4b868..c513658c842 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -685,21 +685,25 @@ impl<T> Vec<T> { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { - let current_len = self.len; - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len); - // Set the final length at the end, keeping in mind that - // dropping an element might panic. Works around a missed - // optimization, as seen in the following issue: - // https://github.com/rust-lang/rust/issues/51802 - let mut local_len = SetLenOnDrop::new(&mut self.len); + if mem::needs_drop::<T>() { + let current_len = self.len; + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len); + // Set the final length at the end, keeping in mind that + // dropping an element might panic. Works around a missed + // optimization, as seen in the following issue: + // https://github.com/rust-lang/rust/issues/51802 + let mut local_len = SetLenOnDrop::new(&mut self.len); - // drop any extra elements - for _ in len..current_len { - local_len.decrement_len(1); - ptr = ptr.offset(-1); - ptr::drop_in_place(ptr); + // drop any extra elements + for _ in len..current_len { + local_len.decrement_len(1); + ptr = ptr.offset(-1); + ptr::drop_in_place(ptr); + } } + } else if len <= self.len { + self.len = len; } } |
