]> git.lizzy.rs Git - rust.git/blob - src/liballoc/raw_vec.rs
Rollup merge of #61453 - lzutao:nouse-featuregate-integer_atomics, r=sfackler
[rust.git] / src / liballoc / raw_vec.rs
1 #![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "0")]
2 #![doc(hidden)]
3
4 use core::cmp;
5 use core::mem;
6 use core::ops::Drop;
7 use core::ptr::{self, NonNull, Unique};
8 use core::slice;
9
10 use crate::alloc::{Alloc, Layout, Global, handle_alloc_error};
11 use crate::collections::CollectionAllocErr::{self, *};
12 use crate::boxed::Box;
13
14 /// A low-level utility for more ergonomically allocating, reallocating, and deallocating
15 /// a buffer of memory on the heap without having to worry about all the corner cases
16 /// involved. This type is excellent for building your own data structures like Vec and VecDeque.
17 /// In particular:
18 ///
19 /// * Produces Unique::empty() on zero-sized types
20 /// * Produces Unique::empty() on zero-length allocations
21 /// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics)
22 /// * Guards against 32-bit systems allocating more than isize::MAX bytes
23 /// * Guards against overflowing your length
24 /// * Aborts on OOM or calls handle_alloc_error as applicable
25 /// * Avoids freeing Unique::empty()
26 /// * Contains a ptr::Unique and thus endows the user with all related benefits
27 ///
28 /// This type does not in anyway inspect the memory that it manages. When dropped it *will*
29 /// free its memory, but it *won't* try to Drop its contents. It is up to the user of RawVec
30 /// to handle the actual things *stored* inside of a RawVec.
31 ///
32 /// Note that a RawVec always forces its capacity to be usize::MAX for zero-sized types.
33 /// This enables you to use capacity growing logic catch the overflows in your length
34 /// that might occur with zero-sized types.
35 ///
36 /// However this means that you need to be careful when round-tripping this type
37 /// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`,
38 /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity
39 /// field. This allows zero-sized types to not be special-cased by consumers of
40 /// this type.
41 #[allow(missing_debug_implementations)]
42 pub struct RawVec<T, A: Alloc = Global> {
43     ptr: Unique<T>,
44     cap: usize,
45     a: A,
46 }
47
48 impl<T, A: Alloc> RawVec<T, A> {
49     /// Like `new` but parameterized over the choice of allocator for
50     /// the returned RawVec.
51     pub const fn new_in(a: A) -> Self {
52         // !0 is usize::MAX. This branch should be stripped at compile time.
53         // FIXME(mark-i-m): use this line when `if`s are allowed in `const`
54         //let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
55
56         // Unique::empty() doubles as "unallocated" and "zero-sized allocation"
57         RawVec {
58             ptr: Unique::empty(),
59             // FIXME(mark-i-m): use `cap` when ifs are allowed in const
60             cap: [0, !0][(mem::size_of::<T>() == 0) as usize],
61             a,
62         }
63     }
64
65     /// Like `with_capacity` but parameterized over the choice of
66     /// allocator for the returned RawVec.
67     #[inline]
68     pub fn with_capacity_in(cap: usize, a: A) -> Self {
69         RawVec::allocate_in(cap, false, a)
70     }
71
72     /// Like `with_capacity_zeroed` but parameterized over the choice
73     /// of allocator for the returned RawVec.
74     #[inline]
75     pub fn with_capacity_zeroed_in(cap: usize, a: A) -> Self {
76         RawVec::allocate_in(cap, true, a)
77     }
78
79     fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self {
80         unsafe {
81             let elem_size = mem::size_of::<T>();
82
83             let alloc_size = cap.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
84             alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
85
86             // handles ZSTs and `cap = 0` alike
87             let ptr = if alloc_size == 0 {
88                 NonNull::<T>::dangling()
89             } else {
90                 let align = mem::align_of::<T>();
91                 let layout = Layout::from_size_align(alloc_size, align).unwrap();
92                 let result = if zeroed {
93                     a.alloc_zeroed(layout)
94                 } else {
95                     a.alloc(layout)
96                 };
97                 match result {
98                     Ok(ptr) => ptr.cast(),
99                     Err(_) => handle_alloc_error(layout),
100                 }
101             };
102
103             RawVec {
104                 ptr: ptr.into(),
105                 cap,
106                 a,
107             }
108         }
109     }
110 }
111
112 impl<T> RawVec<T, Global> {
113     /// Creates the biggest possible RawVec (on the system heap)
114     /// without allocating. If T has positive size, then this makes a
115     /// RawVec with capacity 0. If T has 0 size, then it makes a
116     /// RawVec with capacity `usize::MAX`. Useful for implementing
117     /// delayed allocation.
118     pub const fn new() -> Self {
119         Self::new_in(Global)
120     }
121
122     /// Creates a RawVec (on the system heap) with exactly the
123     /// capacity and alignment requirements for a `[T; cap]`. This is
124     /// equivalent to calling RawVec::new when `cap` is 0 or T is
125     /// zero-sized. Note that if `T` is zero-sized this means you will
126     /// *not* get a RawVec with the requested capacity!
127     ///
128     /// # Panics
129     ///
130     /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
131     /// * Panics on 32-bit platforms if the requested capacity exceeds
132     ///   `isize::MAX` bytes.
133     ///
134     /// # Aborts
135     ///
136     /// Aborts on OOM
137     #[inline]
138     pub fn with_capacity(cap: usize) -> Self {
139         RawVec::allocate_in(cap, false, Global)
140     }
141
142     /// Like `with_capacity` but guarantees the buffer is zeroed.
143     #[inline]
144     pub fn with_capacity_zeroed(cap: usize) -> Self {
145         RawVec::allocate_in(cap, true, Global)
146     }
147 }
148
149 impl<T, A: Alloc> RawVec<T, A> {
150     /// Reconstitutes a RawVec from a pointer, capacity, and allocator.
151     ///
152     /// # Undefined Behavior
153     ///
154     /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The
155     /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
156     /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed.
157     pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self {
158         RawVec {
159             ptr: Unique::new_unchecked(ptr),
160             cap,
161             a,
162         }
163     }
164 }
165
166 impl<T> RawVec<T, Global> {
167     /// Reconstitutes a RawVec from a pointer, capacity.
168     ///
169     /// # Undefined Behavior
170     ///
171     /// The ptr must be allocated (on the system heap), and with the given capacity. The
172     /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
173     /// If the ptr and capacity come from a RawVec, then this is guaranteed.
174     pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self {
175         RawVec {
176             ptr: Unique::new_unchecked(ptr),
177             cap,
178             a: Global,
179         }
180     }
181
182     /// Converts a `Box<[T]>` into a `RawVec<T>`.
183     pub fn from_box(mut slice: Box<[T]>) -> Self {
184         unsafe {
185             let result = RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len());
186             mem::forget(slice);
187             result
188         }
189     }
190 }
191
192 impl<T, A: Alloc> RawVec<T, A> {
193     /// Gets a raw pointer to the start of the allocation. Note that this is
194     /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must
195     /// be careful.
196     pub fn ptr(&self) -> *mut T {
197         self.ptr.as_ptr()
198     }
199
200     /// Gets the capacity of the allocation.
201     ///
202     /// This will always be `usize::MAX` if `T` is zero-sized.
203     #[inline(always)]
204     pub fn cap(&self) -> usize {
205         if mem::size_of::<T>() == 0 {
206             !0
207         } else {
208             self.cap
209         }
210     }
211
212     /// Returns a shared reference to the allocator backing this RawVec.
213     pub fn alloc(&self) -> &A {
214         &self.a
215     }
216
217     /// Returns a mutable reference to the allocator backing this RawVec.
218     pub fn alloc_mut(&mut self) -> &mut A {
219         &mut self.a
220     }
221
222     fn current_layout(&self) -> Option<Layout> {
223         if self.cap == 0 {
224             None
225         } else {
226             // We have an allocated chunk of memory, so we can bypass runtime
227             // checks to get our current layout.
228             unsafe {
229                 let align = mem::align_of::<T>();
230                 let size = mem::size_of::<T>() * self.cap;
231                 Some(Layout::from_size_align_unchecked(size, align))
232             }
233         }
234     }
235
236     /// Doubles the size of the type's backing allocation. This is common enough
237     /// to want to do that it's easiest to just have a dedicated method. Slightly
238     /// more efficient logic can be provided for this than the general case.
239     ///
240     /// This function is ideal for when pushing elements one-at-a-time because
241     /// you don't need to incur the costs of the more general computations
242     /// reserve needs to do to guard against overflow. You do however need to
243     /// manually check if your `len == cap`.
244     ///
245     /// # Panics
246     ///
247     /// * Panics if T is zero-sized on the assumption that you managed to exhaust
248     ///   all `usize::MAX` slots in your imaginary buffer.
249     /// * Panics on 32-bit platforms if the requested capacity exceeds
250     ///   `isize::MAX` bytes.
251     ///
252     /// # Aborts
253     ///
254     /// Aborts on OOM
255     ///
256     /// # Examples
257     ///
258     /// ```
259     /// # #![feature(raw_vec_internals)]
260     /// # extern crate alloc;
261     /// # use std::ptr;
262     /// # use alloc::raw_vec::RawVec;
263     /// struct MyVec<T> {
264     ///     buf: RawVec<T>,
265     ///     len: usize,
266     /// }
267     ///
268     /// impl<T> MyVec<T> {
269     ///     pub fn push(&mut self, elem: T) {
270     ///         if self.len == self.buf.cap() { self.buf.double(); }
271     ///         // double would have aborted or panicked if the len exceeded
272     ///         // `isize::MAX` so this is safe to do unchecked now.
273     ///         unsafe {
274     ///             ptr::write(self.buf.ptr().add(self.len), elem);
275     ///         }
276     ///         self.len += 1;
277     ///     }
278     /// }
279     /// # fn main() {
280     /// #   let mut vec = MyVec { buf: RawVec::new(), len: 0 };
281     /// #   vec.push(1);
282     /// # }
283     /// ```
284     #[inline(never)]
285     #[cold]
286     pub fn double(&mut self) {
287         unsafe {
288             let elem_size = mem::size_of::<T>();
289
290             // since we set the capacity to usize::MAX when elem_size is
291             // 0, getting to here necessarily means the RawVec is overfull.
292             assert!(elem_size != 0, "capacity overflow");
293
294             let (new_cap, uniq) = match self.current_layout() {
295                 Some(cur) => {
296                     // Since we guarantee that we never allocate more than
297                     // isize::MAX bytes, `elem_size * self.cap <= isize::MAX` as
298                     // a precondition, so this can't overflow. Additionally the
299                     // alignment will never be too large as to "not be
300                     // satisfiable", so `Layout::from_size_align` will always
301                     // return `Some`.
302                     //
303                     // tl;dr; we bypass runtime checks due to dynamic assertions
304                     // in this module, allowing us to use
305                     // `from_size_align_unchecked`.
306                     let new_cap = 2 * self.cap;
307                     let new_size = new_cap * elem_size;
308                     alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
309                     let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(),
310                                                  cur,
311                                                  new_size);
312                     match ptr_res {
313                         Ok(ptr) => (new_cap, ptr.cast().into()),
314                         Err(_) => handle_alloc_error(
315                             Layout::from_size_align_unchecked(new_size, cur.align())
316                         ),
317                     }
318                 }
319                 None => {
320                     // skip to 4 because tiny Vec's are dumb; but not if that
321                     // would cause overflow
322                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
323                     match self.a.alloc_array::<T>(new_cap) {
324                         Ok(ptr) => (new_cap, ptr.into()),
325                         Err(_) => handle_alloc_error(Layout::array::<T>(new_cap).unwrap()),
326                     }
327                 }
328             };
329             self.ptr = uniq;
330             self.cap = new_cap;
331         }
332     }
333
334     /// Attempts to double the size of the type's backing allocation in place. This is common
335     /// enough to want to do that it's easiest to just have a dedicated method. Slightly
336     /// more efficient logic can be provided for this than the general case.
337     ///
338     /// Returns `true` if the reallocation attempt has succeeded.
339     ///
340     /// # Panics
341     ///
342     /// * Panics if T is zero-sized on the assumption that you managed to exhaust
343     ///   all `usize::MAX` slots in your imaginary buffer.
344     /// * Panics on 32-bit platforms if the requested capacity exceeds
345     ///   `isize::MAX` bytes.
346     #[inline(never)]
347     #[cold]
348     pub fn double_in_place(&mut self) -> bool {
349         unsafe {
350             let elem_size = mem::size_of::<T>();
351             let old_layout = match self.current_layout() {
352                 Some(layout) => layout,
353                 None => return false, // nothing to double
354             };
355
356             // since we set the capacity to usize::MAX when elem_size is
357             // 0, getting to here necessarily means the RawVec is overfull.
358             assert!(elem_size != 0, "capacity overflow");
359
360             // Since we guarantee that we never allocate more than isize::MAX
361             // bytes, `elem_size * self.cap <= isize::MAX` as a precondition, so
362             // this can't overflow.
363             //
364             // Similarly like with `double` above we can go straight to
365             // `Layout::from_size_align_unchecked` as we know this won't
366             // overflow and the alignment is sufficiently small.
367             let new_cap = 2 * self.cap;
368             let new_size = new_cap * elem_size;
369             alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
370             match self.a.grow_in_place(NonNull::from(self.ptr).cast(), old_layout, new_size) {
371                 Ok(_) => {
372                     // We can't directly divide `size`.
373                     self.cap = new_cap;
374                     true
375                 }
376                 Err(_) => {
377                     false
378                 }
379             }
380         }
381     }
382
383     /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
384     pub fn try_reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize)
385            -> Result<(), CollectionAllocErr> {
386
387         self.reserve_internal(used_cap, needed_extra_cap, Fallible, Exact)
388     }
389
390     /// Ensures that the buffer contains at least enough space to hold
391     /// `used_cap + needed_extra_cap` elements. If it doesn't already,
392     /// will reallocate the minimum possible amount of memory necessary.
393     /// Generally this will be exactly the amount of memory necessary,
394     /// but in principle the allocator is free to give back more than
395     /// we asked for.
396     ///
397     /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
398     /// the requested space. This is not really unsafe, but the unsafe
399     /// code *you* write that relies on the behavior of this function may break.
400     ///
401     /// # Panics
402     ///
403     /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
404     /// * Panics on 32-bit platforms if the requested capacity exceeds
405     ///   `isize::MAX` bytes.
406     ///
407     /// # Aborts
408     ///
409     /// Aborts on OOM
410     pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
411         match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Exact) {
412             Err(CapacityOverflow) => capacity_overflow(),
413             Err(AllocErr) => unreachable!(),
414             Ok(()) => { /* yay */ }
415          }
416      }
417
418     /// Calculates the buffer's new size given that it'll hold `used_cap +
419     /// needed_extra_cap` elements. This logic is used in amortized reserve methods.
420     /// Returns `(new_capacity, new_alloc_size)`.
421     fn amortized_new_size(&self, used_cap: usize, needed_extra_cap: usize)
422         -> Result<usize, CollectionAllocErr> {
423
424         // Nothing we can really do about these checks :(
425         let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?;
426         // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
427         let double_cap = self.cap * 2;
428         // `double_cap` guarantees exponential growth.
429         Ok(cmp::max(double_cap, required_cap))
430     }
431
432     /// The same as `reserve`, but returns on errors instead of panicking or aborting.
433     pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize)
434         -> Result<(), CollectionAllocErr> {
435         self.reserve_internal(used_cap, needed_extra_cap, Fallible, Amortized)
436     }
437
438     /// Ensures that the buffer contains at least enough space to hold
439     /// `used_cap + needed_extra_cap` elements. If it doesn't already have
440     /// enough capacity, will reallocate enough space plus comfortable slack
441     /// space to get amortized `O(1)` behavior. Will limit this behavior
442     /// if it would needlessly cause itself to panic.
443     ///
444     /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
445     /// the requested space. This is not really unsafe, but the unsafe
446     /// code *you* write that relies on the behavior of this function may break.
447     ///
448     /// This is ideal for implementing a bulk-push operation like `extend`.
449     ///
450     /// # Panics
451     ///
452     /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
453     /// * Panics on 32-bit platforms if the requested capacity exceeds
454     ///   `isize::MAX` bytes.
455     ///
456     /// # Aborts
457     ///
458     /// Aborts on OOM
459     ///
460     /// # Examples
461     ///
462     /// ```
463     /// # #![feature(raw_vec_internals)]
464     /// # extern crate alloc;
465     /// # use std::ptr;
466     /// # use alloc::raw_vec::RawVec;
467     /// struct MyVec<T> {
468     ///     buf: RawVec<T>,
469     ///     len: usize,
470     /// }
471     ///
472     /// impl<T: Clone> MyVec<T> {
473     ///     pub fn push_all(&mut self, elems: &[T]) {
474     ///         self.buf.reserve(self.len, elems.len());
475     ///         // reserve would have aborted or panicked if the len exceeded
476     ///         // `isize::MAX` so this is safe to do unchecked now.
477     ///         for x in elems {
478     ///             unsafe {
479     ///                 ptr::write(self.buf.ptr().add(self.len), x.clone());
480     ///             }
481     ///             self.len += 1;
482     ///         }
483     ///     }
484     /// }
485     /// # fn main() {
486     /// #   let mut vector = MyVec { buf: RawVec::new(), len: 0 };
487     /// #   vector.push_all(&[1, 3, 5, 7, 9]);
488     /// # }
489     /// ```
490     pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
491         match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Amortized) {
492             Err(CapacityOverflow) => capacity_overflow(),
493             Err(AllocErr) => unreachable!(),
494             Ok(()) => { /* yay */ }
495         }
496     }
497     /// Attempts to ensure that the buffer contains at least enough space to hold
498     /// `used_cap + needed_extra_cap` elements. If it doesn't already have
499     /// enough capacity, will reallocate in place enough space plus comfortable slack
500     /// space to get amortized `O(1)` behavior. Will limit this behaviour
501     /// if it would needlessly cause itself to panic.
502     ///
503     /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
504     /// the requested space. This is not really unsafe, but the unsafe
505     /// code *you* write that relies on the behavior of this function may break.
506     ///
507     /// Returns `true` if the reallocation attempt has succeeded.
508     ///
509     /// # Panics
510     ///
511     /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
512     /// * Panics on 32-bit platforms if the requested capacity exceeds
513     ///   `isize::MAX` bytes.
514     pub fn reserve_in_place(&mut self, used_cap: usize, needed_extra_cap: usize) -> bool {
515         unsafe {
516             // NOTE: we don't early branch on ZSTs here because we want this
517             // to actually catch "asking for more than usize::MAX" in that case.
518             // If we make it past the first branch then we are guaranteed to
519             // panic.
520
521             // Don't actually need any more capacity. If the current `cap` is 0, we can't
522             // reallocate in place.
523             // Wrapping in case they give a bad `used_cap`
524             let old_layout = match self.current_layout() {
525                 Some(layout) => layout,
526                 None => return false,
527             };
528             if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
529                 return false;
530             }
531
532             let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)
533                 .unwrap_or_else(|_| capacity_overflow());
534
535             // Here, `cap < used_cap + needed_extra_cap <= new_cap`
536             // (regardless of whether `self.cap - used_cap` wrapped).
537             // Therefore we can safely call grow_in_place.
538
539             let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
540             // FIXME: may crash and burn on over-reserve
541             alloc_guard(new_layout.size()).unwrap_or_else(|_| capacity_overflow());
542             match self.a.grow_in_place(
543                 NonNull::from(self.ptr).cast(), old_layout, new_layout.size(),
544             ) {
545                 Ok(_) => {
546                     self.cap = new_cap;
547                     true
548                 }
549                 Err(_) => {
550                     false
551                 }
552             }
553         }
554     }
555
556     /// Shrinks the allocation down to the specified amount. If the given amount
557     /// is 0, actually completely deallocates.
558     ///
559     /// # Panics
560     ///
561     /// Panics if the given amount is *larger* than the current capacity.
562     ///
563     /// # Aborts
564     ///
565     /// Aborts on OOM.
566     pub fn shrink_to_fit(&mut self, amount: usize) {
567         let elem_size = mem::size_of::<T>();
568
569         // Set the `cap` because they might be about to promote to a `Box<[T]>`
570         if elem_size == 0 {
571             self.cap = amount;
572             return;
573         }
574
575         // This check is my waterloo; it's the only thing Vec wouldn't have to do.
576         assert!(self.cap >= amount, "Tried to shrink to a larger capacity");
577
578         if amount == 0 {
579             // We want to create a new zero-length vector within the
580             // same allocator.  We use ptr::write to avoid an
581             // erroneous attempt to drop the contents, and we use
582             // ptr::read to sidestep condition against destructuring
583             // types that implement Drop.
584
585             unsafe {
586                 let a = ptr::read(&self.a as *const A);
587                 self.dealloc_buffer();
588                 ptr::write(self, RawVec::new_in(a));
589             }
590         } else if self.cap != amount {
591             unsafe {
592                 // We know here that our `amount` is greater than zero. This
593                 // implies, via the assert above, that capacity is also greater
594                 // than zero, which means that we've got a current layout that
595                 // "fits"
596                 //
597                 // We also know that `self.cap` is greater than `amount`, and
598                 // consequently we don't need runtime checks for creating either
599                 // layout
600                 let old_size = elem_size * self.cap;
601                 let new_size = elem_size * amount;
602                 let align = mem::align_of::<T>();
603                 let old_layout = Layout::from_size_align_unchecked(old_size, align);
604                 match self.a.realloc(NonNull::from(self.ptr).cast(),
605                                      old_layout,
606                                      new_size) {
607                     Ok(p) => self.ptr = p.cast().into(),
608                     Err(_) => handle_alloc_error(
609                         Layout::from_size_align_unchecked(new_size, align)
610                     ),
611                 }
612             }
613             self.cap = amount;
614         }
615     }
616 }
617
618 enum Fallibility {
619     Fallible,
620     Infallible,
621 }
622
623 use Fallibility::*;
624
625 enum ReserveStrategy {
626     Exact,
627     Amortized,
628 }
629
630 use ReserveStrategy::*;
631
632 impl<T, A: Alloc> RawVec<T, A> {
633     fn reserve_internal(
634         &mut self,
635         used_cap: usize,
636         needed_extra_cap: usize,
637         fallibility: Fallibility,
638         strategy: ReserveStrategy,
639     ) -> Result<(), CollectionAllocErr> {
640         unsafe {
641             use crate::alloc::AllocErr;
642
643             // NOTE: we don't early branch on ZSTs here because we want this
644             // to actually catch "asking for more than usize::MAX" in that case.
645             // If we make it past the first branch then we are guaranteed to
646             // panic.
647
648             // Don't actually need any more capacity.
649             // Wrapping in case they gave a bad `used_cap`.
650             if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
651                 return Ok(());
652             }
653
654             // Nothing we can really do about these checks :(
655             let new_cap = match strategy {
656                 Exact => used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?,
657                 Amortized => self.amortized_new_size(used_cap, needed_extra_cap)?,
658             };
659             let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
660
661             alloc_guard(new_layout.size())?;
662
663             let res = match self.current_layout() {
664                 Some(layout) => {
665                     debug_assert!(new_layout.align() == layout.align());
666                     self.a.realloc(NonNull::from(self.ptr).cast(), layout, new_layout.size())
667                 }
668                 None => self.a.alloc(new_layout),
669             };
670
671             match (&res, fallibility) {
672                 (Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
673                 _ => {}
674             }
675
676             self.ptr = res?.cast().into();
677             self.cap = new_cap;
678
679             Ok(())
680         }
681     }
682
683 }
684
685 impl<T> RawVec<T, Global> {
686     /// Converts the entire buffer into `Box<[T]>`.
687     ///
688     /// Note that this will correctly reconstitute any `cap` changes
689     /// that may have been performed. (see description of type for details)
690     ///
691     /// # Undefined Behavior
692     ///
693     /// All elements of `RawVec<T, Global>` must be initialized. Notice that
694     /// the rules around uninitialized boxed values are not finalized yet,
695     /// but until they are, it is advisable to avoid them.
696     pub unsafe fn into_box(self) -> Box<[T]> {
697         // NOTE: not calling `cap()` here, actually using the real `cap` field!
698         let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);
699         let output: Box<[T]> = Box::from_raw(slice);
700         mem::forget(self);
701         output
702     }
703 }
704
705 impl<T, A: Alloc> RawVec<T, A> {
706     /// Frees the memory owned by the RawVec *without* trying to Drop its contents.
707     pub unsafe fn dealloc_buffer(&mut self) {
708         let elem_size = mem::size_of::<T>();
709         if elem_size != 0 {
710             if let Some(layout) = self.current_layout() {
711                 self.a.dealloc(NonNull::from(self.ptr).cast(), layout);
712             }
713         }
714     }
715 }
716
717 unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
718     /// Frees the memory owned by the RawVec *without* trying to Drop its contents.
719     fn drop(&mut self) {
720         unsafe { self.dealloc_buffer(); }
721     }
722 }
723
724
725
726 // We need to guarantee the following:
727 // * We don't ever allocate `> isize::MAX` byte-size objects
728 // * We don't overflow `usize::MAX` and actually allocate too little
729 //
730 // On 64-bit we just need to check for overflow since trying to allocate
731 // `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
732 // an extra guard for this in case we're running on a platform which can use
733 // all 4GB in user-space. e.g., PAE or x32
734
735 #[inline]
736 fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
737     if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize {
738         Err(CapacityOverflow)
739     } else {
740         Ok(())
741     }
742 }
743
744 // One central function responsible for reporting capacity overflows. This'll
745 // ensure that the code generation related to these panics is minimal as there's
746 // only one location which panics rather than a bunch throughout the module.
747 fn capacity_overflow() -> ! {
748     panic!("capacity overflow")
749 }
750
751 #[cfg(test)]
752 mod tests {
753     use super::*;
754
755     #[test]
756     fn allocator_param() {
757         use crate::alloc::AllocErr;
758
759         // Writing a test of integration between third-party
760         // allocators and RawVec is a little tricky because the RawVec
761         // API does not expose fallible allocation methods, so we
762         // cannot check what happens when allocator is exhausted
763         // (beyond detecting a panic).
764         //
765         // Instead, this just checks that the RawVec methods do at
766         // least go through the Allocator API when it reserves
767         // storage.
768
769         // A dumb allocator that consumes a fixed amount of fuel
770         // before allocation attempts start failing.
771         struct BoundedAlloc { fuel: usize }
772         unsafe impl Alloc for BoundedAlloc {
773             unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
774                 let size = layout.size();
775                 if size > self.fuel {
776                     return Err(AllocErr);
777                 }
778                 match Global.alloc(layout) {
779                     ok @ Ok(_) => { self.fuel -= size; ok }
780                     err @ Err(_) => err,
781                 }
782             }
783             unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
784                 Global.dealloc(ptr, layout)
785             }
786         }
787
788         let a = BoundedAlloc { fuel: 500 };
789         let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
790         assert_eq!(v.a.fuel, 450);
791         v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
792         assert_eq!(v.a.fuel, 250);
793     }
794
795     #[test]
796     fn reserve_does_not_overallocate() {
797         {
798             let mut v: RawVec<u32> = RawVec::new();
799             // First `reserve` allocates like `reserve_exact`
800             v.reserve(0, 9);
801             assert_eq!(9, v.cap());
802         }
803
804         {
805             let mut v: RawVec<u32> = RawVec::new();
806             v.reserve(0, 7);
807             assert_eq!(7, v.cap());
808             // 97 if more than double of 7, so `reserve` should work
809             // like `reserve_exact`.
810             v.reserve(7, 90);
811             assert_eq!(97, v.cap());
812         }
813
814         {
815             let mut v: RawVec<u32> = RawVec::new();
816             v.reserve(0, 12);
817             assert_eq!(12, v.cap());
818             v.reserve(12, 3);
819             // 3 is less than half of 12, so `reserve` must grow
820             // exponentially. At the time of writing this test grow
821             // factor is 2, so new capacity is 24, however, grow factor
822             // of 1.5 is OK too. Hence `>= 18` in assert.
823             assert!(v.cap() >= 12 + 12 / 2);
824         }
825     }
826
827
828 }