7272//! This is handled by the [`InPlaceDrop`] guard for sink items (`U`) and by
7373//! [`vec::IntoIter::forget_allocation_drop_remaining()`] for remaining source items (`T`).
7474//!
75- //! If dropping any remaining source item (`T`) panics then [`InPlaceDstBufDrop `] will handle dropping
75+ //! If dropping any remaining source item (`T`) panics then [`InPlaceDstDataSrcBufDrop `] will handle dropping
7676//! the already collected sink items (`U`) and freeing the allocation.
7777//!
7878//! [`vec::IntoIter::forget_allocation_drop_remaining()`]: super::IntoIter::forget_allocation_drop_remaining()
@@ -158,17 +158,20 @@ use crate::alloc::{handle_alloc_error, Global};
158158use core:: alloc:: Allocator ;
159159use core:: alloc:: Layout ;
160160use core:: iter:: { InPlaceIterable , SourceIter , TrustedRandomAccessNoCoerce } ;
161+ use core:: marker:: PhantomData ;
161162use core:: mem:: { self , ManuallyDrop , SizedTypeProperties } ;
162163use core:: num:: NonZeroUsize ;
163164use core:: ptr:: { self , NonNull } ;
164165
165- use super :: { InPlaceDrop , InPlaceDstBufDrop , SpecFromIter , SpecFromIterNested , Vec } ;
166+ use super :: { InPlaceDrop , InPlaceDstDataSrcBufDrop , SpecFromIter , SpecFromIterNested , Vec } ;
166167
167168const fn in_place_collectible < DEST , SRC > (
168169 step_merge : Option < NonZeroUsize > ,
169170 step_expand : Option < NonZeroUsize > ,
170171) -> bool {
171- if const { SRC :: IS_ZST || DEST :: IS_ZST || mem:: align_of :: < SRC > ( ) < mem:: align_of :: < DEST > ( ) } {
172+ // Require matching alignments because an alignment-changing realloc is inefficient on many
173+ // system allocators and better implementations would require the unstable Allocator trait.
174+ if const { SRC :: IS_ZST || DEST :: IS_ZST || mem:: align_of :: < SRC > ( ) != mem:: align_of :: < DEST > ( ) } {
172175 return false ;
173176 }
174177
@@ -188,7 +191,8 @@ const fn in_place_collectible<DEST, SRC>(
188191
189192const fn needs_realloc < SRC , DEST > ( src_cap : usize , dst_cap : usize ) -> bool {
190193 if const { mem:: align_of :: < SRC > ( ) != mem:: align_of :: < DEST > ( ) } {
191- return src_cap > 0 ;
194+ // FIXME: use unreachable! once that works in const
195+ panic ! ( "in_place_collectible() prevents this" ) ;
192196 }
193197
194198 // If src type size is an integer multiple of the destination type size then
@@ -262,7 +266,7 @@ where
262266 ) ;
263267 }
264268
265- // The ownership of the allocation and the new `T` values is temporarily moved into `dst_guard`.
269+ // The ownership of the source allocation and the new `T` values is temporarily moved into `dst_guard`.
266270 // This is safe because
267271 // * `forget_allocation_drop_remaining` immediately forgets the allocation
268272 // before any panic can occur in order to avoid any double free, and then proceeds to drop
@@ -273,11 +277,12 @@ where
273277 // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce
274278 // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the
275279 // module documentation why this is ok anyway.
276- let dst_guard = InPlaceDstBufDrop { ptr : dst_buf, len, cap : dst_cap } ;
280+ let dst_guard =
281+ InPlaceDstDataSrcBufDrop { ptr : dst_buf, len, src_cap, src : PhantomData :: < I :: Src > } ;
277282 src. forget_allocation_drop_remaining ( ) ;
278283
279- // Adjust the allocation if the alignment didn't match or the source had a capacity in bytes
280- // that wasn't a multiple of the destination type size.
284+ // Adjust the allocation if the source had a capacity in bytes that wasn't a multiple
285+ // of the destination type size.
281286 // Since the discrepancy should generally be small this should only result in some
282287 // bookkeeping updates and no memmove.
283288 if needs_realloc :: < I :: Src , T > ( src_cap, dst_cap) {
@@ -290,7 +295,7 @@ where
290295 let src_size = mem:: size_of :: < I :: Src > ( ) . unchecked_mul ( src_cap) ;
291296 let old_layout = Layout :: from_size_align_unchecked ( src_size, src_align) ;
292297
293- // The must be equal or smaller for in-place iteration to be possible
298+ // The allocation must be equal or smaller for in-place iteration to be possible
294299 // therefore the new layout must be ≤ the old one and therefore valid.
295300 let dst_align = mem:: align_of :: < T > ( ) ;
296301 let dst_size = mem:: size_of :: < T > ( ) . unchecked_mul ( dst_cap) ;
0 commit comments