@@ -668,8 +668,7 @@ impl<A: Allocator> RawVecInner<A> {
668668 /// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
669669 /// initially construct `self`
670670 /// - `elem_layout`'s size must be a multiple of its alignment
671- /// - The sum of `len` and `additional` must be greater than or equal to
672- /// `self.capacity(elem_layout.size())`
671+ /// - The sum of `len` and `additional` must be greater than the current capacity
673672 unsafe fn grow_amortized (
674673 & mut self ,
675674 len : usize ,
@@ -693,16 +692,12 @@ impl<A: Allocator> RawVecInner<A> {
693692 let cap = cmp:: max ( self . cap . as_inner ( ) * 2 , required_cap) ;
694693 let cap = cmp:: max ( min_non_zero_cap ( elem_layout. size ( ) ) , cap) ;
695694
696- let new_layout = layout_array ( cap, elem_layout) ?;
697-
698695 // SAFETY:
699- // - For the `current_memory` call: Precondition passed to caller
700- // - For the `finish_grow` call: Precondition passed to caller
701- // + `current_memory` does the right thing
702- let ptr =
703- unsafe { finish_grow ( new_layout, self . current_memory ( elem_layout) , & mut self . alloc ) ? } ;
696+ // - cap >= len + additional
697+ // - other preconditions passed to caller
698+ let ptr = unsafe { self . finish_grow ( cap, elem_layout) ? } ;
704699
705- // SAFETY: layout_array would have resulted in a capacity overflow if we tried to allocate more than ` isize::MAX` items
700+ // SAFETY: `finish_grow` would have failed if `cap > isize::MAX`
706701 unsafe { self . set_ptr_and_cap ( ptr, cap) } ;
707702 Ok ( ( ) )
708703 }
@@ -711,8 +706,7 @@ impl<A: Allocator> RawVecInner<A> {
711706 /// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
712707 /// initially construct `self`
713708 /// - `elem_layout`'s size must be a multiple of its alignment
714- /// - The sum of `len` and `additional` must be greater than or equal to
715- /// `self.capacity(elem_layout.size())`
709+ /// - The sum of `len` and `additional` must be greater than the current capacity
716710 unsafe fn grow_exact (
717711 & mut self ,
718712 len : usize ,
@@ -726,21 +720,44 @@ impl<A: Allocator> RawVecInner<A> {
726720 }
727721
728722 let cap = len. checked_add ( additional) . ok_or ( CapacityOverflow ) ?;
729- let new_layout = layout_array ( cap, elem_layout) ?;
730723
731- // SAFETY:
732- // - For the `current_memory` call: Precondition passed to caller
733- // - For the `finish_grow` call: Precondition passed to caller
734- // + `current_memory` does the right thing
735- let ptr =
736- unsafe { finish_grow ( new_layout, self . current_memory ( elem_layout) , & mut self . alloc ) ? } ;
737- // SAFETY: layout_array would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items
738- unsafe {
739- self . set_ptr_and_cap ( ptr, cap) ;
740- }
724+ // SAFETY: preconditions passed to caller
725+ let ptr = unsafe { self . finish_grow ( cap, elem_layout) ? } ;
726+
727+ // SAFETY: `finish_grow` would have failed if `cap > isize::MAX`
728+ unsafe { self . set_ptr_and_cap ( ptr, cap) } ;
741729 Ok ( ( ) )
742730 }
743731
732+ /// # Safety
733+ /// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
734+ /// initially construct `self`
735+ /// - `elem_layout`'s size must be a multiple of its alignment
736+ /// - `cap` must be greater than the current capacity
737+ // not marked inline(never) since we want optimizers to be able to observe the specifics of this
738+ // function, see tests/codegen-llvm/vec-reserve-extend.rs.
739+ #[ cold]
740+ unsafe fn finish_grow (
741+ & self ,
742+ cap : usize ,
743+ elem_layout : Layout ,
744+ ) -> Result < NonNull < [ u8 ] > , TryReserveError > {
745+ let new_layout = layout_array ( cap, elem_layout) ?;
746+
747+ let memory = if let Some ( ( ptr, old_layout) ) = unsafe { self . current_memory ( elem_layout) } {
748+ debug_assert_eq ! ( old_layout. align( ) , new_layout. align( ) ) ;
749+ unsafe {
750+ // The allocator checks for alignment equality
751+ hint:: assert_unchecked ( old_layout. align ( ) == new_layout. align ( ) ) ;
752+ self . alloc . grow ( ptr, old_layout, new_layout)
753+ }
754+ } else {
755+ self . alloc . allocate ( new_layout)
756+ } ;
757+
758+ memory. map_err ( |_| AllocError { layout : new_layout, non_exhaustive : ( ) } . into ( ) )
759+ }
760+
744761 /// # Safety
745762 /// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
746763 /// initially construct `self`
@@ -820,38 +837,6 @@ impl<A: Allocator> RawVecInner<A> {
820837 }
821838}
822839
823- /// # Safety
824- /// If `current_memory` matches `Some((ptr, old_layout))`:
825- /// - `ptr` must denote a block of memory *currently allocated* via `alloc`
826- /// - `old_layout` must *fit* that block of memory
827- /// - `new_layout` must have the same alignment as `old_layout`
828- /// - `new_layout.size()` must be greater than or equal to `old_layout.size()`
829- /// If `current_memory` is `None`, this function is safe.
830- // not marked inline(never) since we want optimizers to be able to observe the specifics of this
831- // function, see tests/codegen-llvm/vec-reserve-extend.rs.
832- #[ cold]
833- unsafe fn finish_grow < A > (
834- new_layout : Layout ,
835- current_memory : Option < ( NonNull < u8 > , Layout ) > ,
836- alloc : & mut A ,
837- ) -> Result < NonNull < [ u8 ] > , TryReserveError >
838- where
839- A : Allocator ,
840- {
841- let memory = if let Some ( ( ptr, old_layout) ) = current_memory {
842- debug_assert_eq ! ( old_layout. align( ) , new_layout. align( ) ) ;
843- unsafe {
844- // The allocator checks for alignment equality
845- hint:: assert_unchecked ( old_layout. align ( ) == new_layout. align ( ) ) ;
846- alloc. grow ( ptr, old_layout, new_layout)
847- }
848- } else {
849- alloc. allocate ( new_layout)
850- } ;
851-
852- memory. map_err ( |_| AllocError { layout : new_layout, non_exhaustive : ( ) } . into ( ) )
853- }
854-
855840// Central function for reserve error handling.
856841#[ cfg( not( no_global_oom_handling) ) ]
857842#[ cold]
0 commit comments