diff options
| author | Simon Sapin <simon.sapin@exyr.org> | 2019-10-25 18:11:20 +0200 |
|---|---|---|
| committer | Simon Sapin <simon.sapin@exyr.org> | 2019-11-18 15:56:26 +0100 |
| commit | 74b571402f980f70a4d87ec3c778af568e4fa329 (patch) | |
| tree | abfad347e5f2a16d428988e4bec341880fbb2d22 | |
| parent | a0d40f8bdfcc3c28355467973f97fd4c45ac5876 (diff) | |
| download | rust-74b571402f980f70a4d87ec3c778af568e4fa329.tar.gz rust-74b571402f980f70a4d87ec3c778af568e4fa329.zip | |
Use `drop_in_place` in `array::IntoIter::drop`
This skips the loop when the element type is known not to have drop glue, even in debug mode.
| -rw-r--r-- | src/libcore/array/iter.rs | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/libcore/array/iter.rs b/src/libcore/array/iter.rs index 307e9b90ee2..aab9463e3aa 100644 --- a/src/libcore/array/iter.rs +++ b/src/libcore/array/iter.rs @@ -92,6 +92,18 @@ where mem::transmute::<&[MaybeUninit<T>], &[T]>(slice) } } + + /// Returns a mutable slice of all elements that have not been yielded yet. + fn as_mut_slice(&mut self) -> &mut [T] { + // This transmute is safe, same as in `as_slice` above. + let slice = &mut self.data[self.alive.clone()]; + // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains + // the size and alignment of `T`. Furthermore, we know that all + // elements within `alive` are properly initialized. + unsafe { + mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice) + } + } } @@ -184,10 +196,12 @@ where [T; N]: LengthAtMost32, { fn drop(&mut self) { - // We simply drop each element via `for_each`. This should not incur - // any significant runtime overhead and avoids adding another `unsafe` - // block. - self.by_ref().for_each(drop); + // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice + // of elements that have not been moved out yet and that remain + // to be dropped. + unsafe { + ptr::drop_in_place(self.as_mut_slice()) + } } } |
