@@ -96,14 +96,15 @@ impl<T, A: Alloc> RawVec<T, A> {
9696 NonNull :: < T > :: dangling ( ) . as_opaque ( )
9797 } else {
9898 let align = mem:: align_of :: < T > ( ) ;
99+ let layout = Layout :: from_size_align ( alloc_size, align) . unwrap ( ) ;
99100 let result = if zeroed {
100- a. alloc_zeroed ( Layout :: from_size_align ( alloc_size , align ) . unwrap ( ) )
101+ a. alloc_zeroed ( layout )
101102 } else {
102- a. alloc ( Layout :: from_size_align ( alloc_size , align ) . unwrap ( ) )
103+ a. alloc ( layout )
103104 } ;
104105 match result {
105106 Ok ( ptr) => ptr,
106- Err ( _) => oom ( ) ,
107+ Err ( _) => oom ( layout ) ,
107108 }
108109 } ;
109110
@@ -318,7 +319,7 @@ impl<T, A: Alloc> RawVec<T, A> {
318319 new_size) ;
319320 match ptr_res {
320321 Ok ( ptr) => ( new_cap, ptr. cast ( ) . into ( ) ) ,
321- Err ( _) => oom ( ) ,
322+ Err ( _) => oom ( Layout :: from_size_align_unchecked ( new_size , cur . align ( ) ) ) ,
322323 }
323324 }
324325 None => {
@@ -327,7 +328,7 @@ impl<T, A: Alloc> RawVec<T, A> {
327328 let new_cap = if elem_size > ( !0 ) / 8 { 1 } else { 4 } ;
328329 match self . a . alloc_array :: < T > ( new_cap) {
329330 Ok ( ptr) => ( new_cap, ptr. into ( ) ) ,
330- Err ( _) => oom ( ) ,
331+ Err ( _) => oom ( Layout :: array :: < T > ( new_cap ) . unwrap ( ) ) ,
331332 }
332333 }
333334 } ;
@@ -389,37 +390,7 @@ impl<T, A: Alloc> RawVec<T, A> {
389390 pub fn try_reserve_exact ( & mut self , used_cap : usize , needed_extra_cap : usize )
390391 -> Result < ( ) , CollectionAllocErr > {
391392
392- unsafe {
393- // NOTE: we don't early branch on ZSTs here because we want this
394- // to actually catch "asking for more than usize::MAX" in that case.
395- // If we make it past the first branch then we are guaranteed to
396- // panic.
397-
398- // Don't actually need any more capacity.
399- // Wrapping in case they gave a bad `used_cap`.
400- if self . cap ( ) . wrapping_sub ( used_cap) >= needed_extra_cap {
401- return Ok ( ( ) ) ;
402- }
403-
404- // Nothing we can really do about these checks :(
405- let new_cap = used_cap. checked_add ( needed_extra_cap) . ok_or ( CapacityOverflow ) ?;
406- let new_layout = Layout :: array :: < T > ( new_cap) . map_err ( |_| CapacityOverflow ) ?;
407-
408- alloc_guard ( new_layout. size ( ) ) ?;
409-
410- let res = match self . current_layout ( ) {
411- Some ( layout) => {
412- debug_assert ! ( new_layout. align( ) == layout. align( ) ) ;
413- self . a . realloc ( NonNull :: from ( self . ptr ) . as_opaque ( ) , layout, new_layout. size ( ) )
414- }
415- None => self . a . alloc ( new_layout) ,
416- } ;
417-
418- self . ptr = res?. cast ( ) . into ( ) ;
419- self . cap = new_cap;
420-
421- Ok ( ( ) )
422- }
393+ self . reserve_internal ( used_cap, needed_extra_cap, Fallible , Exact )
423394 }
424395
425396 /// Ensures that the buffer contains at least enough space to hold
@@ -443,9 +414,9 @@ impl<T, A: Alloc> RawVec<T, A> {
443414 ///
444415 /// Aborts on OOM
445416 pub fn reserve_exact ( & mut self , used_cap : usize , needed_extra_cap : usize ) {
446- match self . try_reserve_exact ( used_cap, needed_extra_cap) {
417+ match self . reserve_internal ( used_cap, needed_extra_cap, Infallible , Exact ) {
447418 Err ( CapacityOverflow ) => capacity_overflow ( ) ,
448- Err ( AllocErr ) => oom ( ) ,
419+ Err ( AllocErr ) => unreachable ! ( ) ,
449420 Ok ( ( ) ) => { /* yay */ }
450421 }
451422 }
@@ -467,37 +438,7 @@ impl<T, A: Alloc> RawVec<T, A> {
467438 /// The same as `reserve`, but returns on errors instead of panicking or aborting.
468439 pub fn try_reserve ( & mut self , used_cap : usize , needed_extra_cap : usize )
469440 -> Result < ( ) , CollectionAllocErr > {
470- unsafe {
471- // NOTE: we don't early branch on ZSTs here because we want this
472- // to actually catch "asking for more than usize::MAX" in that case.
473- // If we make it past the first branch then we are guaranteed to
474- // panic.
475-
476- // Don't actually need any more capacity.
477- // Wrapping in case they give a bad `used_cap`
478- if self . cap ( ) . wrapping_sub ( used_cap) >= needed_extra_cap {
479- return Ok ( ( ) ) ;
480- }
481-
482- let new_cap = self . amortized_new_size ( used_cap, needed_extra_cap) ?;
483- let new_layout = Layout :: array :: < T > ( new_cap) . map_err ( |_| CapacityOverflow ) ?;
484-
485- // FIXME: may crash and burn on over-reserve
486- alloc_guard ( new_layout. size ( ) ) ?;
487-
488- let res = match self . current_layout ( ) {
489- Some ( layout) => {
490- debug_assert ! ( new_layout. align( ) == layout. align( ) ) ;
491- self . a . realloc ( NonNull :: from ( self . ptr ) . as_opaque ( ) , layout, new_layout. size ( ) )
492- }
493- None => self . a . alloc ( new_layout) ,
494- } ;
495-
496- self . ptr = res?. cast ( ) . into ( ) ;
497- self . cap = new_cap;
498-
499- Ok ( ( ) )
500- }
441+ self . reserve_internal ( used_cap, needed_extra_cap, Fallible , Amortized )
501442 }
502443
503444 /// Ensures that the buffer contains at least enough space to hold
@@ -553,12 +494,12 @@ impl<T, A: Alloc> RawVec<T, A> {
553494 /// # }
554495 /// ```
555496 pub fn reserve ( & mut self , used_cap : usize , needed_extra_cap : usize ) {
556- match self . try_reserve ( used_cap, needed_extra_cap) {
497+ match self . reserve_internal ( used_cap, needed_extra_cap, Infallible , Amortized ) {
557498 Err ( CapacityOverflow ) => capacity_overflow ( ) ,
558- Err ( AllocErr ) => oom ( ) ,
499+ Err ( AllocErr ) => unreachable ! ( ) ,
559500 Ok ( ( ) ) => { /* yay */ }
560- }
561- }
501+ }
502+ }
562503 /// Attempts to ensure that the buffer contains at least enough space to hold
563504 /// `used_cap + needed_extra_cap` elements. If it doesn't already have
564505 /// enough capacity, will reallocate in place enough space plus comfortable slack
@@ -670,14 +611,81 @@ impl<T, A: Alloc> RawVec<T, A> {
670611 old_layout,
671612 new_size) {
672613 Ok ( p) => self . ptr = p. cast ( ) . into ( ) ,
673- Err ( _) => oom ( ) ,
614+ Err ( _) => oom ( Layout :: from_size_align_unchecked ( new_size , align ) ) ,
674615 }
675616 }
676617 self . cap = amount;
677618 }
678619 }
679620}
680621
622+ enum Fallibility {
623+ Fallible ,
624+ Infallible ,
625+ }
626+
627+ use self :: Fallibility :: * ;
628+
629+ enum ReserveStrategy {
630+ Exact ,
631+ Amortized ,
632+ }
633+
634+ use self :: ReserveStrategy :: * ;
635+
636+ impl < T , A : Alloc > RawVec < T , A > {
637+ fn reserve_internal (
638+ & mut self ,
639+ used_cap : usize ,
640+ needed_extra_cap : usize ,
641+ fallibility : Fallibility ,
642+ strategy : ReserveStrategy ,
643+ ) -> Result < ( ) , CollectionAllocErr > {
644+ unsafe {
645+ use alloc:: AllocErr ;
646+
647+ // NOTE: we don't early branch on ZSTs here because we want this
648+ // to actually catch "asking for more than usize::MAX" in that case.
649+ // If we make it past the first branch then we are guaranteed to
650+ // panic.
651+
652+ // Don't actually need any more capacity.
653+ // Wrapping in case they gave a bad `used_cap`.
654+ if self . cap ( ) . wrapping_sub ( used_cap) >= needed_extra_cap {
655+ return Ok ( ( ) ) ;
656+ }
657+
658+ // Nothing we can really do about these checks :(
659+ let new_cap = match strategy {
660+ Exact => used_cap. checked_add ( needed_extra_cap) . ok_or ( CapacityOverflow ) ?,
661+ Amortized => self . amortized_new_size ( used_cap, needed_extra_cap) ?,
662+ } ;
663+ let new_layout = Layout :: array :: < T > ( new_cap) . map_err ( |_| CapacityOverflow ) ?;
664+
665+ alloc_guard ( new_layout. size ( ) ) ?;
666+
667+ let res = match self . current_layout ( ) {
668+ Some ( layout) => {
669+ debug_assert ! ( new_layout. align( ) == layout. align( ) ) ;
670+ self . a . realloc ( NonNull :: from ( self . ptr ) . as_opaque ( ) , layout, new_layout. size ( ) )
671+ }
672+ None => self . a . alloc ( new_layout) ,
673+ } ;
674+
675+ match ( & res, fallibility) {
676+ ( Err ( AllocErr ) , Infallible ) => oom ( new_layout) ,
677+ _ => { }
678+ }
679+
680+ self . ptr = res?. cast ( ) . into ( ) ;
681+ self . cap = new_cap;
682+
683+ Ok ( ( ) )
684+ }
685+ }
686+
687+ }
688+
681689impl < T > RawVec < T , Global > {
682690 /// Converts the entire buffer into `Box<[T]>`.
683691 ///
0 commit comments