22
33use crate :: intrinsics:: transmute_unchecked;
44use crate :: iter:: { FusedIterator , TrustedLen , TrustedRandomAccessNoCoerce } ;
5- use crate :: mem:: MaybeUninit ;
5+ use crate :: mem:: { ManuallyDrop , MaybeUninit } ;
66use crate :: num:: NonZero ;
7- use crate :: ops:: { IndexRange , Range , Try } ;
7+ use crate :: ops:: { Deref as _ , DerefMut as _ , IndexRange , Range , Try } ;
88use crate :: { fmt, ptr} ;
99
1010mod iter_inner;
@@ -18,17 +18,17 @@ type InnerUnsized<T> = iter_inner::PolymorphicIter<[MaybeUninit<T>]>;
1818#[ rustc_diagnostic_item = "ArrayIntoIter" ]
1919#[ derive( Clone ) ]
2020pub struct IntoIter < T , const N : usize > {
21- inner : InnerSized < T , N > ,
21+ inner : ManuallyDrop < InnerSized < T , N > > ,
2222}
2323
2424impl < 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
@@ -320,11 +320,20 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
320320}
321321
322322#[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
323+ // Even though all the Drop logic could be completely handled by
324+ // PolymorphicIter, this impl still serves two purposes:
325+ // - Drop has been part of the public API, so we can't remove it
326+ // - the partial_drop function doesn't always get fully optimized away
327+ // for !Drop types and ends up as dead code in the final binary.
328+ // Branching on needs_drop higher in the call-tree allows it to be
329+ // removed by earlier optimization passes.
323330impl < T , const N : usize > Drop for IntoIter < T , N > {
324331 #[ inline]
325332 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.
333+ if crate :: mem:: needs_drop :: < T > ( ) {
334+ // SAFETY: This is the only place where we drop this field.
335+ unsafe { ManuallyDrop :: drop ( & mut self . inner ) }
336+ }
328337 }
329338}
330339
0 commit comments