@@ -668,8 +668,7 @@ impl<A: Allocator> RawVecInner<A> {
668
668
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
669
669
/// initially construct `self`
670
670
/// - `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
673
672
unsafe fn grow_amortized (
674
673
& mut self ,
675
674
len : usize ,
@@ -693,16 +692,12 @@ impl<A: Allocator> RawVecInner<A> {
693
692
let cap = cmp:: max ( self . cap . as_inner ( ) * 2 , required_cap) ;
694
693
let cap = cmp:: max ( min_non_zero_cap ( elem_layout. size ( ) ) , cap) ;
695
694
696
- let new_layout = layout_array ( cap, elem_layout) ?;
697
-
698
695
// 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) ? } ;
704
699
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`
706
701
unsafe { self . set_ptr_and_cap ( ptr, cap) } ;
707
702
Ok ( ( ) )
708
703
}
@@ -711,8 +706,7 @@ impl<A: Allocator> RawVecInner<A> {
711
706
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
712
707
/// initially construct `self`
713
708
/// - `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
716
710
unsafe fn grow_exact (
717
711
& mut self ,
718
712
len : usize ,
@@ -726,21 +720,44 @@ impl<A: Allocator> RawVecInner<A> {
726
720
}
727
721
728
722
let cap = len. checked_add ( additional) . ok_or ( CapacityOverflow ) ?;
729
- let new_layout = layout_array ( cap, elem_layout) ?;
730
723
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) } ;
741
729
Ok ( ( ) )
742
730
}
743
731
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
+
744
761
/// # Safety
745
762
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
746
763
/// initially construct `self`
@@ -820,38 +837,6 @@ impl<A: Allocator> RawVecInner<A> {
820
837
}
821
838
}
822
839
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
-
855
840
// Central function for reserve error handling.
856
841
#[ cfg( not( no_global_oom_handling) ) ]
857
842
#[ cold]
0 commit comments