2323#![ allow( unstable_name_collisions) ]
2424#![ allow( dead_code) ]
2525
26- use crate :: Bump ;
26+ use allocator_api2:: alloc:: { AllocError , Allocator } ;
27+ use bumpalo:: Bump ;
2728
29+ pub use core:: alloc:: Layout ;
2830use core:: cmp;
2931use core:: mem;
3032use core:: ptr:: { self , NonNull } ;
3133
32- use crate :: alloc:: { Alloc , Layout , UnstableLayoutMethods , handle_alloc_error} ;
33- use crate :: collections:: CollectionAllocErr ;
34- use crate :: collections:: CollectionAllocErr :: * ;
34+ use bumpalo:: collections:: CollectionAllocErr :: { self , AllocErr , CapacityOverflow } ;
35+
3536// use boxed::Box;
3637
3738/// A low-level utility for more ergonomically allocating, reallocating, and deallocating
@@ -103,8 +104,7 @@ impl<'a, T> RawVec<'a, T> {
103104 } else {
104105 let align = mem:: align_of :: < T > ( ) ;
105106 let layout = Layout :: from_size_align ( alloc_size, align) . unwrap ( ) ;
106- let result =
107- if zeroed { a. alloc_zeroed ( layout) } else { Alloc :: alloc ( & mut a, layout) } ;
107+ let result = if zeroed { a. allocate_zeroed ( layout) } else { a. allocate ( layout) } ;
108108 match result {
109109 Ok ( ptr) => ptr. cast ( ) ,
110110 Err ( _) => handle_alloc_error ( layout) ,
@@ -533,7 +533,7 @@ impl<'a, T> RawVec<'a, T> {
533533 let new_size = elem_size * amount;
534534 let align = mem:: align_of :: < T > ( ) ;
535535 let old_layout = Layout :: from_size_align_unchecked ( old_size, align) ;
536- match self . a . realloc ( self . ptr . cast ( ) , old_layout, new_size) {
536+ match realloc ( self . a , self . ptr . cast ( ) , old_layout, new_size) {
537537 Ok ( p) => self . ptr = p. cast ( ) ,
538538 Err ( _) => {
539539 handle_alloc_error ( Layout :: from_size_align_unchecked ( new_size, align) )
@@ -656,8 +656,6 @@ impl<'a, T> RawVec<'a, T> {
656656 strategy : ReserveStrategy ,
657657 ) -> Result < ( ) , CollectionAllocErr > {
658658 unsafe {
659- use crate :: AllocErr ;
660-
661659 // NOTE: we don't early branch on ZSTs here because we want this
662660 // to actually catch "asking for more than usize::MAX" in that case.
663661 // If we make it past the first branch then we are guaranteed to
@@ -675,16 +673,16 @@ impl<'a, T> RawVec<'a, T> {
675673 let res = match self . current_layout ( ) {
676674 Some ( layout) => {
677675 debug_assert ! ( new_layout. align( ) == layout. align( ) ) ;
678- self . a . realloc ( self . ptr . cast ( ) , layout, new_layout. size ( ) )
676+ realloc ( self . a , self . ptr . cast ( ) , layout, new_layout. size ( ) )
679677 }
680- None => Alloc :: alloc ( & mut self . a , new_layout) ,
678+ None => self . a . allocate ( new_layout) ,
681679 } ;
682680
683- if let ( Err ( AllocErr ) , Infallible ) = ( & res, fallibility) {
681+ if let ( Err ( AllocError ) , Infallible ) = ( & res, fallibility) {
684682 handle_alloc_error ( new_layout) ;
685683 }
686684
687- self . ptr = res?. cast ( ) ;
685+ self . ptr = res. map_err ( |_| AllocErr ) ?. cast ( ) ;
688686 self . cap = new_cap;
689687
690688 Ok ( ( ) )
@@ -698,7 +696,7 @@ impl<'a, T> RawVec<'a, T> {
698696 let elem_size = mem:: size_of :: < T > ( ) ;
699697 if elem_size != 0 {
700698 if let Some ( layout) = self . current_layout ( ) {
701- self . a . dealloc ( self . ptr . cast ( ) , layout) ;
699+ self . a . deallocate ( self . ptr . cast ( ) , layout) ;
702700 }
703701 }
704702 }
@@ -738,6 +736,93 @@ fn capacity_overflow() -> ! {
738736 panic ! ( "capacity overflow" )
739737}
740738
739+ // Copied from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/alloc.rs#L29-L31
740+ fn handle_alloc_error ( layout : Layout ) -> ! {
741+ panic ! ( "encountered allocation error: {:?}" , layout)
742+ }
743+
744+ // Copied from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/lib.rs#L482-L486
745+ /// Wrapper around `Layout::from_size_align` that adds debug assertions.
746+ #[ inline]
747+ fn layout_from_size_align ( size : usize , align : usize ) -> Result < Layout , AllocError > {
748+ Layout :: from_size_align ( size, align) . map_err ( |_| AllocError )
749+ }
750+
751+ // Code copied from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/lib.rs#L1917-L1936
752+ // Doc comment from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/alloc.rs#L322-L402
753+ //
754+ /// Returns a pointer suitable for holding data described by
755+ /// a new layout with `layout`’s alignment and a size given
756+ /// by `new_size`. To
757+ /// accomplish this, this may extend or shrink the allocation
758+ /// referenced by `ptr` to fit the new layout.
759+ ///
760+ /// If this returns `Ok`, then ownership of the memory block
761+ /// referenced by `ptr` has been transferred to this
762+ /// allocator. The memory may or may not have been freed, and
763+ /// should be considered unusable (unless of course it was
764+ /// transferred back to the caller again via the return value of
765+ /// this method).
766+ ///
767+ /// If this method returns `Err`, then ownership of the memory
768+ /// block has not been transferred to this allocator, and the
769+ /// contents of the memory block are unaltered.
770+ ///
771+ /// # Safety
772+ ///
773+ /// This function is unsafe because undefined behavior can result
774+ /// if the caller does not ensure all of the following:
775+ ///
776+ /// * `ptr` must be currently allocated via this allocator,
777+ ///
778+ /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
779+ /// argument need not fit it.)
780+ ///
781+ /// * `new_size` must be greater than zero.
782+ ///
783+ /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
784+ /// must not overflow (i.e. the rounded value must be less than `usize::MAX`).
785+ ///
786+ /// (Extension subtraits might provide more specific bounds on
787+ /// behavior, e.g. guarantee a sentinel address or a null pointer
788+ /// in response to a zero-size allocation request.)
789+ ///
790+ /// # Errors
791+ ///
792+ /// Returns `Err` only if the new layout
793+ /// does not meet the allocator's size
794+ /// and alignment constraints of the allocator, or if reallocation
795+ /// otherwise fails.
796+ ///
797+ /// Implementations are encouraged to return `Err` on memory
798+ /// exhaustion rather than panicking or aborting, but this is not
799+ /// a strict requirement. (Specifically: it is *legal* to
800+ /// implement this trait atop an underlying native allocation
801+ /// library that aborts on memory exhaustion.)
802+ ///
803+ /// Clients wishing to abort computation in response to a
804+ /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
805+ /// rather than directly invoking `panic!` or similar.
806+ unsafe fn realloc (
807+ bump : & Bump ,
808+ ptr : NonNull < u8 > ,
809+ layout : Layout ,
810+ new_size : usize ,
811+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
812+ let old_size = layout. size ( ) ;
813+
814+ if old_size == 0 {
815+ return bump. allocate ( layout) ;
816+ }
817+
818+ let new_layout = layout_from_size_align ( new_size, layout. align ( ) ) ?;
819+ if new_size <= old_size {
820+ bump. shrink ( ptr, layout, new_layout)
821+ } else {
822+ bump. grow ( ptr, layout, new_layout)
823+ }
824+ }
825+
741826#[ cfg( test) ]
742827mod tests {
743828 use super :: * ;
0 commit comments