Skip to content

Commit 61c5b78

Browse files
Auto merge of #147353 - the8472:nondrop-array-iter, r=<try>
only call polymorphic array iter drop machinery when the type requires it
2 parents e2c96cc + 8e79e6d commit 61c5b78

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

library/core/src/array/iter.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
33
use crate::intrinsics::transmute_unchecked;
44
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce};
5-
use crate::mem::MaybeUninit;
5+
use crate::mem::{ManuallyDrop, MaybeUninit};
66
use crate::num::NonZero;
7-
use crate::ops::{IndexRange, Range, Try};
7+
use crate::ops::{Deref as _, DerefMut as _, IndexRange, Range, Try};
88
use crate::{fmt, ptr};
99

1010
mod iter_inner;
@@ -18,17 +18,17 @@ type InnerUnsized<T> = iter_inner::PolymorphicIter<[MaybeUninit<T>]>;
1818
#[rustc_diagnostic_item = "ArrayIntoIter"]
1919
#[derive(Clone)]
2020
pub struct IntoIter<T, const N: usize> {
21-
inner: InnerSized<T, N>,
21+
inner: ManuallyDrop<InnerSized<T, N>>,
2222
}
2323

2424
impl<T, const N: usize> IntoIter<T, N> {
2525
#[inline]
2626
fn unsize(&self) -> &InnerUnsized<T> {
27-
&self.inner
27+
self.inner.deref()
2828
}
2929
#[inline]
3030
fn unsize_mut(&mut self) -> &mut InnerUnsized<T> {
31-
&mut self.inner
31+
self.inner.deref_mut()
3232
}
3333
}
3434

@@ -69,7 +69,7 @@ impl<T, const N: usize> IntoIterator for [T; N] {
6969
// SAFETY: The original array was entirely initialized and the the alive
7070
// range we're passing here represents that fact.
7171
let inner = unsafe { InnerSized::new_unchecked(IndexRange::zero_to(N), data) };
72-
IntoIter { inner }
72+
IntoIter { inner: ManuallyDrop::new(inner) }
7373
}
7474
}
7575

@@ -146,7 +146,7 @@ impl<T, const N: usize> IntoIter<T, N> {
146146
let alive = unsafe { IndexRange::new_unchecked(initialized.start, initialized.end) };
147147
// SAFETY: one of our safety condition is that these items are initialized.
148148
let inner = unsafe { InnerSized::new_unchecked(alive, buffer) };
149-
IntoIter { inner }
149+
IntoIter { inner: ManuallyDrop::new(inner) }
150150
}
151151

152152
/// Creates an iterator over `T` which returns no elements.
@@ -205,7 +205,7 @@ impl<T, const N: usize> IntoIter<T, N> {
205205
#[inline]
206206
pub const fn empty() -> Self {
207207
let inner = InnerSized::empty();
208-
IntoIter { inner }
208+
IntoIter { inner: ManuallyDrop::new(inner) }
209209
}
210210

211211
/// Returns an immutable slice of all elements that have not been yielded
@@ -323,8 +323,15 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
323323
impl<T, const N: usize> Drop for IntoIter<T, N> {
324324
#[inline]
325325
fn drop(&mut self) {
326-
// `inner` now handles this, but it'd technically be a breaking change
327-
// to remove this `impl`, even though it's useless.
326+
let drop: Option<unsafe fn(&mut _)> =
327+
const { if crate::mem::needs_drop::<T>() { Some(ManuallyDrop::drop) } else { None } };
328+
329+
if let Some(drop) = drop {
330+
// SAFETY: This is the only place where we drop this field.
331+
unsafe {
332+
drop(&mut self.inner);
333+
}
334+
}
328335
}
329336
}
330337

0 commit comments

Comments
 (0)