diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-09-14 16:42:28 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-14 16:42:28 +0200 |
| commit | c6c2acdb47d320658d22b0ac0f8a357fdc071b1f (patch) | |
| tree | 001224f37a46a755ced70fb8f9ea9e85fba29d8d /src/liballoc | |
| parent | af33a1d902c7dec7824740e971953b21996d4429 (diff) | |
| parent | 223600ac2c23715f350ceae7f315f5056aae6fc0 (diff) | |
| download | rust-c6c2acdb47d320658d22b0ac0f8a357fdc071b1f.tar.gz rust-c6c2acdb47d320658d22b0ac0f8a357fdc071b1f.zip | |
Rollup merge of #64375 - kornelski:vecdrop, r=rkruppe
Fast path for vec.clear/truncate For trivial types like `u8`, `vec.truncate()`/`vec.clear()` relies on the optimizer to remove the loop. This means more work in debug builds, and more work for the optimizer. Avoiding this busywork is exactly what `mem::needs_drop::<T>()` is for.
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; } } |
