From b28a95391b85e17b1d2f7edc1115291d8a86bcd2 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 18 Jan 2024 22:47:20 +0100 Subject: [PATCH 1/2] update internal ASCII art comment for vec specializations --- library/alloc/src/vec/spec_from_iter.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index e976552cf2b92..33dd4139bc08b 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -13,13 +13,13 @@ use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; /// +-+-----------+ /// | /// v -/// +-+-------------------------------+ +---------------------+ -/// |SpecFromIter +---->+SpecFromIterNested | -/// |where I: | | |where I: | -/// | Iterator (default)----------+ | | Iterator (default) | -/// | vec::IntoIter | | | TrustedLen | -/// | SourceIterMarker---fallback-+ | +---------------------+ -/// +---------------------------------+ +/// +-+---------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)------------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | InPlaceCollect--(fallback to)-+ | +---------------------+ +/// +-----------------------------------+ /// ``` pub(super) trait SpecFromIter { fn from_iter(iter: I) -> Self; From 85d17879623116be76a68c2170c4cb6ff58f4ceb Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 18 Jan 2024 22:50:14 +0100 Subject: [PATCH 2/2] remove alignment-changing in-place collect Currently stable users can't benefit from this because GlobaAlloc doesn't support alignment-changing realloc and neither do most posix allocators. So in practice it always results in an extra memcpy. --- library/alloc/src/vec/in_place_collect.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index ec5f32539f2c2..5a783e6675215 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -168,7 +168,9 @@ const fn in_place_collectible( step_merge: Option, step_expand: Option, ) -> bool { - if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() < mem::align_of::() } { + // Require matching alignments because an alignment-changing realloc is inefficient on many + // system allocators and better implementations would require the unstable Allocator trait. + if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() != mem::align_of::() } { return false; } @@ -188,7 +190,8 @@ const fn in_place_collectible( const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { if const { mem::align_of::() != mem::align_of::() } { - return src_cap > 0; + // FIXME: use unreachable! once that works in const + panic!("in_place_collectible() prevents this"); } // If src type size is an integer multiple of the destination type size then @@ -276,8 +279,8 @@ where let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap: dst_cap }; src.forget_allocation_drop_remaining(); - // Adjust the allocation if the alignment didn't match or the source had a capacity in bytes - // that wasn't a multiple of the destination type size. + // Adjust the allocation if the source had a capacity in bytes that wasn't a multiple + // of the destination type size. // Since the discrepancy should generally be small this should only result in some // bookkeeping updates and no memmove. if needs_realloc::(src_cap, dst_cap) { @@ -290,7 +293,7 @@ where let src_size = mem::size_of::().unchecked_mul(src_cap); let old_layout = Layout::from_size_align_unchecked(src_size, src_align); - // The must be equal or smaller for in-place iteration to be possible + // The allocation must be equal or smaller for in-place iteration to be possible // therefore the new layout must be ≤ the old one and therefore valid. let dst_align = mem::align_of::(); let dst_size = mem::size_of::().unchecked_mul(dst_cap);