52
52
//! Otherwise the input capacity (and thus layout) in bytes may not be representable by the output
53
53
//! `Vec<U>`. In that case `alloc.shrink()` is used to update the allocation's layout.
54
54
//!
55
- //! Currently alignments of `T` and `U` must be the same. In principle smaller output alignments
56
- //! could be supported but that would require always calling `alloc.shrink` for those transformations .
55
+ //! Alignments of `T` must be the same or larger than `U`. Since alignments are always a power
56
+ //! of two _larger_ implies _is a multiple of_ .
57
57
//!
58
58
//! See `in_place_collectible()` for the current conditions.
59
59
//!
@@ -168,7 +168,7 @@ const fn in_place_collectible<DEST, SRC>(
168
168
step_merge : Option < NonZeroUsize > ,
169
169
step_expand : Option < NonZeroUsize > ,
170
170
) -> bool {
171
- if DEST :: IS_ZST || mem:: align_of :: < SRC > ( ) != mem:: align_of :: < DEST > ( ) {
171
+ if DEST :: IS_ZST || mem:: align_of :: < SRC > ( ) < mem:: align_of :: < DEST > ( ) {
172
172
return false ;
173
173
}
174
174
@@ -178,7 +178,7 @@ const fn in_place_collectible<DEST, SRC>(
178
178
// e.g.
179
179
// - 1 x [u8; 4] -> 4x u8, via flatten
180
180
// - 4 x u8 -> 1x [u8; 4], via array_chunks
181
- mem:: size_of :: < SRC > ( ) * step_merge. get ( ) = = mem:: size_of :: < DEST > ( ) * step_expand. get ( )
181
+ mem:: size_of :: < SRC > ( ) * step_merge. get ( ) > = mem:: size_of :: < DEST > ( ) * step_expand. get ( )
182
182
}
183
183
// Fall back to other from_iter impls if an overflow occurred in the step merge/expansion
184
184
// tracking.
@@ -255,12 +255,15 @@ where
255
255
let dst_guard = InPlaceDstBufDrop { ptr : dst_buf, len, cap : dst_cap } ;
256
256
src. forget_allocation_drop_remaining ( ) ;
257
257
258
- // Adjust the allocation size if the source had a capacity in bytes that wasn't a multiple
259
- // of the destination type size.
258
+ // Adjust the allocation if the alignment didn't match or the source had a capacity in bytes
259
+ // that wasn't a multiple of the destination type size.
260
260
// Since the discrepancy should generally be small this should only result in some
261
261
// bookkeeping updates and no memmove.
262
- if const { mem:: size_of :: < T > ( ) > mem:: size_of :: < I :: Src > ( ) }
263
- && src_cap * mem:: size_of :: < I :: Src > ( ) != dst_cap * mem:: size_of :: < T > ( )
262
+ if ( const {
263
+ let src_sz = mem:: size_of :: < I :: Src > ( ) ;
264
+ src_sz > 0 && mem:: size_of :: < T > ( ) % src_sz != 0
265
+ } && src_cap * mem:: size_of :: < I :: Src > ( ) != dst_cap * mem:: size_of :: < T > ( ) )
266
+ || const { mem:: align_of :: < T > ( ) != mem:: align_of :: < I :: Src > ( ) }
264
267
{
265
268
let alloc = Global ;
266
269
unsafe {
0 commit comments