1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 
11 #![allow(unstable_name_collisions)]
12 #![allow(dead_code)]
13 #![allow(deprecated)]
14 
15 //! Memory allocation APIs
16 
17 use core::cmp;
18 use core::fmt;
19 use core::mem;
20 use core::ptr::{self, NonNull};
21 use core::usize;
22 
23 pub use core::alloc::{Layout, LayoutErr};
24 
new_layout_err() -> LayoutErr25 fn new_layout_err() -> LayoutErr {
26     Layout::from_size_align(1, 3).unwrap_err()
27 }
28 
handle_alloc_error(layout: Layout) -> !29 pub fn handle_alloc_error(layout: Layout) -> ! {
30     panic!("encountered allocation error: {:?}", layout)
31 }
32 
33 pub trait UnstableLayoutMethods {
padding_needed_for(&self, align: usize) -> usize34     fn padding_needed_for(&self, align: usize) -> usize;
repeat(&self, n: usize) -> Result<(Layout, usize), LayoutErr>35     fn repeat(&self, n: usize) -> Result<(Layout, usize), LayoutErr>;
array<T>(n: usize) -> Result<Layout, LayoutErr>36     fn array<T>(n: usize) -> Result<Layout, LayoutErr>;
37 }
38 
39 impl UnstableLayoutMethods for Layout {
padding_needed_for(&self, align: usize) -> usize40     fn padding_needed_for(&self, align: usize) -> usize {
41         let len = self.size();
42 
43         // Rounded up value is:
44         //   len_rounded_up = (len + align - 1) & !(align - 1);
45         // and then we return the padding difference: `len_rounded_up - len`.
46         //
47         // We use modular arithmetic throughout:
48         //
49         // 1. align is guaranteed to be > 0, so align - 1 is always
50         //    valid.
51         //
52         // 2. `len + align - 1` can overflow by at most `align - 1`,
53         //    so the &-mask with `!(align - 1)` will ensure that in the
54         //    case of overflow, `len_rounded_up` will itself be 0.
55         //    Thus the returned padding, when added to `len`, yields 0,
56         //    which trivially satisfies the alignment `align`.
57         //
58         // (Of course, attempts to allocate blocks of memory whose
59         // size and padding overflow in the above manner should cause
60         // the allocator to yield an error anyway.)
61 
62         let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
63         len_rounded_up.wrapping_sub(len)
64     }
65 
repeat(&self, n: usize) -> Result<(Layout, usize), LayoutErr>66     fn repeat(&self, n: usize) -> Result<(Layout, usize), LayoutErr> {
67         let padded_size = self
68             .size()
69             .checked_add(self.padding_needed_for(self.align()))
70             .ok_or_else(new_layout_err)?;
71         let alloc_size = padded_size.checked_mul(n).ok_or_else(new_layout_err)?;
72 
73         unsafe {
74             // self.align is already known to be valid and alloc_size has been
75             // padded already.
76             Ok((
77                 Layout::from_size_align_unchecked(alloc_size, self.align()),
78                 padded_size,
79             ))
80         }
81     }
82 
array<T>(n: usize) -> Result<Layout, LayoutErr>83     fn array<T>(n: usize) -> Result<Layout, LayoutErr> {
84         Layout::new::<T>().repeat(n).map(|(k, offs)| {
85             debug_assert!(offs == mem::size_of::<T>());
86             k
87         })
88     }
89 }
90 
91 /// Represents the combination of a starting address and
92 /// a total capacity of the returned block.
93 // #[unstable(feature = "allocator_api", issue = "32838")]
94 #[derive(Debug)]
95 pub struct Excess(pub NonNull<u8>, pub usize);
96 
size_align<T>() -> (usize, usize)97 fn size_align<T>() -> (usize, usize) {
98     (mem::size_of::<T>(), mem::align_of::<T>())
99 }
100 
101 /// The `AllocErr` error indicates an allocation failure
102 /// that may be due to resource exhaustion or to
103 /// something wrong when combining the given input arguments with this
104 /// allocator.
105 // #[unstable(feature = "allocator_api", issue = "32838")]
106 #[derive(Clone, PartialEq, Eq, Debug)]
107 pub struct AllocErr;
108 
109 // (we need this for downstream impl of trait Error)
110 // #[unstable(feature = "allocator_api", issue = "32838")]
111 impl fmt::Display for AllocErr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result112     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113         f.write_str("memory allocation failed")
114     }
115 }
116 
117 /// The `CannotReallocInPlace` error is used when `grow_in_place` or
118 /// `shrink_in_place` were unable to reuse the given memory block for
119 /// a requested layout.
120 // #[unstable(feature = "allocator_api", issue = "32838")]
121 #[derive(Clone, PartialEq, Eq, Debug)]
122 pub struct CannotReallocInPlace;
123 
124 // #[unstable(feature = "allocator_api", issue = "32838")]
125 impl CannotReallocInPlace {
description(&self) -> &str126     pub fn description(&self) -> &str {
127         "cannot reallocate allocator's memory in place"
128     }
129 }
130 
131 // (we need this for downstream impl of trait Error)
132 // #[unstable(feature = "allocator_api", issue = "32838")]
133 impl fmt::Display for CannotReallocInPlace {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result134     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135         write!(f, "{}", self.description())
136     }
137 }
138 
139 /// An implementation of `Alloc` can allocate, reallocate, and
140 /// deallocate arbitrary blocks of data described via `Layout`.
141 ///
142 /// Some of the methods require that a memory block be *currently
143 /// allocated* via an allocator. This means that:
144 ///
145 /// * the starting address for that memory block was previously
146 ///   returned by a previous call to an allocation method (`alloc`,
147 ///   `alloc_zeroed`, `alloc_excess`, `alloc_one`, `alloc_array`) or
148 ///   reallocation method (`realloc`, `realloc_excess`, or
149 ///   `realloc_array`), and
150 ///
151 /// * the memory block has not been subsequently deallocated, where
152 ///   blocks are deallocated either by being passed to a deallocation
153 ///   method (`dealloc`, `dealloc_one`, `dealloc_array`) or by being
154 ///   passed to a reallocation method (see above) that returns `Ok`.
155 ///
156 /// A note regarding zero-sized types and zero-sized layouts: many
157 /// methods in the `Alloc` trait state that allocation requests
158 /// must be non-zero size, or else undefined behavior can result.
159 ///
160 /// * However, some higher-level allocation methods (`alloc_one`,
161 ///   `alloc_array`) are well-defined on zero-sized types and can
162 ///   optionally support them: it is left up to the implementor
163 ///   whether to return `Err`, or to return `Ok` with some pointer.
164 ///
165 /// * If an `Alloc` implementation chooses to return `Ok` in this
166 ///   case (i.e. the pointer denotes a zero-sized inaccessible block)
167 ///   then that returned pointer must be considered "currently
168 ///   allocated". On such an allocator, *all* methods that take
169 ///   currently-allocated pointers as inputs must accept these
170 ///   zero-sized pointers, *without* causing undefined behavior.
171 ///
172 /// * In other words, if a zero-sized pointer can flow out of an
173 ///   allocator, then that allocator must likewise accept that pointer
174 ///   flowing back into its deallocation and reallocation methods.
175 ///
176 /// Some of the methods require that a layout *fit* a memory block.
177 /// What it means for a layout to "fit" a memory block means (or
178 /// equivalently, for a memory block to "fit" a layout) is that the
179 /// following two conditions must hold:
180 ///
181 /// 1. The block's starting address must be aligned to `layout.align()`.
182 ///
183 /// 2. The block's size must fall in the range `[use_min, use_max]`, where:
184 ///
185 ///    * `use_min` is `self.usable_size(layout).0`, and
186 ///
187 ///    * `use_max` is the capacity that was (or would have been)
188 ///      returned when (if) the block was allocated via a call to
189 ///      `alloc_excess` or `realloc_excess`.
190 ///
191 /// Note that:
192 ///
193 ///  * the size of the layout most recently used to allocate the block
194 ///    is guaranteed to be in the range `[use_min, use_max]`, and
195 ///
196 ///  * a lower-bound on `use_max` can be safely approximated by a call to
197 ///    `usable_size`.
198 ///
199 ///  * if a layout `k` fits a memory block (denoted by `ptr`)
200 ///    currently allocated via an allocator `a`, then it is legal to
201 ///    use that layout to deallocate it, i.e. `a.dealloc(ptr, k);`.
202 ///
203 /// # Unsafety
204 ///
205 /// The `Alloc` trait is an `unsafe` trait for a number of reasons, and
206 /// implementors must ensure that they adhere to these contracts:
207 ///
208 /// * Pointers returned from allocation functions must point to valid memory and
209 ///   retain their validity until at least the instance of `Alloc` is dropped
210 ///   itself.
211 ///
212 /// * `Layout` queries and calculations in general must be correct. Callers of
213 ///   this trait are allowed to rely on the contracts defined on each method,
214 ///   and implementors must ensure such contracts remain true.
215 ///
216 /// Note that this list may get tweaked over time as clarifications are made in
217 /// the future.
218 // #[unstable(feature = "allocator_api", issue = "32838")]
219 pub unsafe trait Alloc {
220     // (Note: some existing allocators have unspecified but well-defined
221     // behavior in response to a zero size allocation request ;
222     // e.g. in C, `malloc` of 0 will either return a null pointer or a
223     // unique pointer, but will not have arbitrary undefined
224     // behavior.
225     // However in jemalloc for example,
226     // `mallocx(0)` is documented as undefined behavior.)
227 
228     /// Returns a pointer meeting the size and alignment guarantees of
229     /// `layout`.
230     ///
231     /// If this method returns an `Ok(addr)`, then the `addr` returned
232     /// will be non-null address pointing to a block of storage
233     /// suitable for holding an instance of `layout`.
234     ///
235     /// The returned block of storage may or may not have its contents
236     /// initialized. (Extension subtraits might restrict this
237     /// behavior, e.g. to ensure initialization to particular sets of
238     /// bit patterns.)
239     ///
240     /// # Safety
241     ///
242     /// This function is unsafe because undefined behavior can result
243     /// if the caller does not ensure that `layout` has non-zero size.
244     ///
245     /// (Extension subtraits might provide more specific bounds on
246     /// behavior, e.g. guarantee a sentinel address or a null pointer
247     /// in response to a zero-size allocation request.)
248     ///
249     /// # Errors
250     ///
251     /// Returning `Err` indicates that either memory is exhausted or
252     /// `layout` does not meet allocator's size or alignment
253     /// constraints.
254     ///
255     /// Implementations are encouraged to return `Err` on memory
256     /// exhaustion rather than panicking or aborting, but this is not
257     /// a strict requirement. (Specifically: it is *legal* to
258     /// implement this trait atop an underlying native allocation
259     /// library that aborts on memory exhaustion.)
260     ///
261     /// Clients wishing to abort computation in response to an
262     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
263     /// rather than directly invoking `panic!` or similar.
264     ///
265     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>266     unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>;
267 
268     /// Deallocate the memory referenced by `ptr`.
269     ///
270     /// # Safety
271     ///
272     /// This function is unsafe because undefined behavior can result
273     /// if the caller does not ensure all of the following:
274     ///
275     /// * `ptr` must denote a block of memory currently allocated via
276     ///   this allocator,
277     ///
278     /// * `layout` must *fit* that block of memory,
279     ///
280     /// * In addition to fitting the block of memory `layout`, the
281     ///   alignment of the `layout` must match the alignment used
282     ///   to allocate that block of memory.
dealloc(&mut self, ptr: NonNull<u8>, layout: Layout)283     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
284 
285     // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS ==
286     // usable_size
287 
288     /// Returns bounds on the guaranteed usable size of a successful
289     /// allocation created with the specified `layout`.
290     ///
291     /// In particular, if one has a memory block allocated via a given
292     /// allocator `a` and layout `k` where `a.usable_size(k)` returns
293     /// `(l, u)`, then one can pass that block to `a.dealloc()` with a
294     /// layout in the size range [l, u].
295     ///
296     /// (All implementors of `usable_size` must ensure that
297     /// `l <= k.size() <= u`)
298     ///
299     /// Both the lower- and upper-bounds (`l` and `u` respectively)
300     /// are provided, because an allocator based on size classes could
301     /// misbehave if one attempts to deallocate a block without
302     /// providing a correct value for its size (i.e., one within the
303     /// range `[l, u]`).
304     ///
305     /// Clients who wish to make use of excess capacity are encouraged
306     /// to use the `alloc_excess` and `realloc_excess` instead, as
307     /// this method is constrained to report conservative values that
308     /// serve as valid bounds for *all possible* allocation method
309     /// calls.
310     ///
311     /// However, for clients that do not wish to track the capacity
312     /// returned by `alloc_excess` locally, this method is likely to
313     /// produce useful results.
314     #[inline]
usable_size(&self, layout: &Layout) -> (usize, usize)315     fn usable_size(&self, layout: &Layout) -> (usize, usize) {
316         (layout.size(), layout.size())
317     }
318 
319     // == METHODS FOR MEMORY REUSE ==
320     // realloc. alloc_excess, realloc_excess
321 
322     /// Returns a pointer suitable for holding data described by
323     /// a new layout with `layout`’s alignment and a size given
324     /// by `new_size`. To
325     /// accomplish this, this may extend or shrink the allocation
326     /// referenced by `ptr` to fit the new layout.
327     ///
328     /// If this returns `Ok`, then ownership of the memory block
329     /// referenced by `ptr` has been transferred to this
330     /// allocator. The memory may or may not have been freed, and
331     /// should be considered unusable (unless of course it was
332     /// transferred back to the caller again via the return value of
333     /// this method).
334     ///
335     /// If this method returns `Err`, then ownership of the memory
336     /// block has not been transferred to this allocator, and the
337     /// contents of the memory block are unaltered.
338     ///
339     /// # Safety
340     ///
341     /// This function is unsafe because undefined behavior can result
342     /// if the caller does not ensure all of the following:
343     ///
344     /// * `ptr` must be currently allocated via this allocator,
345     ///
346     /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
347     ///   argument need not fit it.)
348     ///
349     /// * `new_size` must be greater than zero.
350     ///
351     /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
352     ///   must not overflow (i.e. the rounded value must be less than `usize::MAX`).
353     ///
354     /// (Extension subtraits might provide more specific bounds on
355     /// behavior, e.g. guarantee a sentinel address or a null pointer
356     /// in response to a zero-size allocation request.)
357     ///
358     /// # Errors
359     ///
360     /// Returns `Err` only if the new layout
361     /// does not meet the allocator's size
362     /// and alignment constraints of the allocator, or if reallocation
363     /// otherwise fails.
364     ///
365     /// Implementations are encouraged to return `Err` on memory
366     /// exhaustion rather than panicking or aborting, but this is not
367     /// a strict requirement. (Specifically: it is *legal* to
368     /// implement this trait atop an underlying native allocation
369     /// library that aborts on memory exhaustion.)
370     ///
371     /// Clients wishing to abort computation in response to a
372     /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
373     /// rather than directly invoking `panic!` or similar.
374     ///
375     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
realloc( &mut self, ptr: NonNull<u8>, layout: Layout, new_size: usize, ) -> Result<NonNull<u8>, AllocErr>376     unsafe fn realloc(
377         &mut self,
378         ptr: NonNull<u8>,
379         layout: Layout,
380         new_size: usize,
381     ) -> Result<NonNull<u8>, AllocErr> {
382         let old_size = layout.size();
383 
384         if new_size >= old_size {
385             if let Ok(()) = self.grow_in_place(ptr, layout, new_size) {
386                 return Ok(ptr);
387             }
388         } else if new_size < old_size {
389             if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) {
390                 return Ok(ptr);
391             }
392         }
393 
394         // otherwise, fall back on alloc + copy + dealloc.
395         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
396         let result = self.alloc(new_layout);
397         if let Ok(new_ptr) = result {
398             ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
399             self.dealloc(ptr, layout);
400         }
401         result
402     }
403 
404     /// Behaves like `alloc`, but also ensures that the contents
405     /// are set to zero before being returned.
406     ///
407     /// # Safety
408     ///
409     /// This function is unsafe for the same reasons that `alloc` is.
410     ///
411     /// # Errors
412     ///
413     /// Returning `Err` indicates that either memory is exhausted or
414     /// `layout` does not meet allocator's size or alignment
415     /// constraints, just as in `alloc`.
416     ///
417     /// Clients wishing to abort computation in response to an
418     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
419     /// rather than directly invoking `panic!` or similar.
420     ///
421     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>422     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
423         let size = layout.size();
424         let p = self.alloc(layout);
425         if let Ok(p) = p {
426             ptr::write_bytes(p.as_ptr(), 0, size);
427         }
428         p
429     }
430 
431     /// Behaves like `alloc`, but also returns the whole size of
432     /// the returned block. For some `layout` inputs, like arrays, this
433     /// may include extra storage usable for additional data.
434     ///
435     /// # Safety
436     ///
437     /// This function is unsafe for the same reasons that `alloc` is.
438     ///
439     /// # Errors
440     ///
441     /// Returning `Err` indicates that either memory is exhausted or
442     /// `layout` does not meet allocator's size or alignment
443     /// constraints, just as in `alloc`.
444     ///
445     /// Clients wishing to abort computation in response to an
446     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
447     /// rather than directly invoking `panic!` or similar.
448     ///
449     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr>450     unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
451         let usable_size = self.usable_size(&layout);
452         self.alloc(layout).map(|p| Excess(p, usable_size.1))
453     }
454 
455     /// Behaves like `realloc`, but also returns the whole size of
456     /// the returned block. For some `layout` inputs, like arrays, this
457     /// may include extra storage usable for additional data.
458     ///
459     /// # Safety
460     ///
461     /// This function is unsafe for the same reasons that `realloc` is.
462     ///
463     /// # Errors
464     ///
465     /// Returning `Err` indicates that either memory is exhausted or
466     /// `layout` does not meet allocator's size or alignment
467     /// constraints, just as in `realloc`.
468     ///
469     /// Clients wishing to abort computation in response to a
470     /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
471     /// rather than directly invoking `panic!` or similar.
472     ///
473     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
realloc_excess( &mut self, ptr: NonNull<u8>, layout: Layout, new_size: usize, ) -> Result<Excess, AllocErr>474     unsafe fn realloc_excess(
475         &mut self,
476         ptr: NonNull<u8>,
477         layout: Layout,
478         new_size: usize,
479     ) -> Result<Excess, AllocErr> {
480         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
481         let usable_size = self.usable_size(&new_layout);
482         self.realloc(ptr, layout, new_size)
483             .map(|p| Excess(p, usable_size.1))
484     }
485 
486     /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
487     ///
488     /// If this returns `Ok`, then the allocator has asserted that the
489     /// memory block referenced by `ptr` now fits `new_size`, and thus can
490     /// be used to carry data of a layout of that size and same alignment as
491     /// `layout`. (The allocator is allowed to
492     /// expend effort to accomplish this, such as extending the memory block to
493     /// include successor blocks, or virtual memory tricks.)
494     ///
495     /// Regardless of what this method returns, ownership of the
496     /// memory block referenced by `ptr` has not been transferred, and
497     /// the contents of the memory block are unaltered.
498     ///
499     /// # Safety
500     ///
501     /// This function is unsafe because undefined behavior can result
502     /// if the caller does not ensure all of the following:
503     ///
504     /// * `ptr` must be currently allocated via this allocator,
505     ///
506     /// * `layout` must *fit* the `ptr` (see above); note the
507     ///   `new_size` argument need not fit it,
508     ///
509     /// * `new_size` must not be less than `layout.size()`,
510     ///
511     /// # Errors
512     ///
513     /// Returns `Err(CannotReallocInPlace)` when the allocator is
514     /// unable to assert that the memory block referenced by `ptr`
515     /// could fit `layout`.
516     ///
517     /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
518     /// function; clients are expected either to be able to recover from
519     /// `grow_in_place` failures without aborting, or to fall back on
520     /// another reallocation method before resorting to an abort.
grow_in_place( &mut self, ptr: NonNull<u8>, layout: Layout, new_size: usize, ) -> Result<(), CannotReallocInPlace>521     unsafe fn grow_in_place(
522         &mut self,
523         ptr: NonNull<u8>,
524         layout: Layout,
525         new_size: usize,
526     ) -> Result<(), CannotReallocInPlace> {
527         let _ = ptr; // this default implementation doesn't care about the actual address.
528         debug_assert!(new_size >= layout.size());
529         let (_l, u) = self.usable_size(&layout);
530         // _l <= layout.size()                       [guaranteed by usable_size()]
531         //       layout.size() <= new_layout.size()  [required by this method]
532         if new_size <= u {
533             Ok(())
534         } else {
535             Err(CannotReallocInPlace)
536         }
537     }
538 
539     /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
540     ///
541     /// If this returns `Ok`, then the allocator has asserted that the
542     /// memory block referenced by `ptr` now fits `new_size`, and
543     /// thus can only be used to carry data of that smaller
544     /// layout. (The allocator is allowed to take advantage of this,
545     /// carving off portions of the block for reuse elsewhere.) The
546     /// truncated contents of the block within the smaller layout are
547     /// unaltered, and ownership of block has not been transferred.
548     ///
549     /// If this returns `Err`, then the memory block is considered to
550     /// still represent the original (larger) `layout`. None of the
551     /// block has been carved off for reuse elsewhere, ownership of
552     /// the memory block has not been transferred, and the contents of
553     /// the memory block are unaltered.
554     ///
555     /// # Safety
556     ///
557     /// This function is unsafe because undefined behavior can result
558     /// if the caller does not ensure all of the following:
559     ///
560     /// * `ptr` must be currently allocated via this allocator,
561     ///
562     /// * `layout` must *fit* the `ptr` (see above); note the
563     ///   `new_size` argument need not fit it,
564     ///
565     /// * `new_size` must not be greater than `layout.size()`
566     ///   (and must be greater than zero),
567     ///
568     /// # Errors
569     ///
570     /// Returns `Err(CannotReallocInPlace)` when the allocator is
571     /// unable to assert that the memory block referenced by `ptr`
572     /// could fit `layout`.
573     ///
574     /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
575     /// function; clients are expected either to be able to recover from
576     /// `shrink_in_place` failures without aborting, or to fall back
577     /// on another reallocation method before resorting to an abort.
shrink_in_place( &mut self, ptr: NonNull<u8>, layout: Layout, new_size: usize, ) -> Result<(), CannotReallocInPlace>578     unsafe fn shrink_in_place(
579         &mut self,
580         ptr: NonNull<u8>,
581         layout: Layout,
582         new_size: usize,
583     ) -> Result<(), CannotReallocInPlace> {
584         let _ = ptr; // this default implementation doesn't care about the actual address.
585         debug_assert!(new_size <= layout.size());
586         let (l, _u) = self.usable_size(&layout);
587         //                      layout.size() <= _u  [guaranteed by usable_size()]
588         // new_layout.size() <= layout.size()        [required by this method]
589         if l <= new_size {
590             Ok(())
591         } else {
592             Err(CannotReallocInPlace)
593         }
594     }
595 
596     // == COMMON USAGE PATTERNS ==
597     // alloc_one, dealloc_one, alloc_array, realloc_array. dealloc_array
598 
599     /// Allocates a block suitable for holding an instance of `T`.
600     ///
601     /// Captures a common usage pattern for allocators.
602     ///
603     /// The returned block is suitable for passing to the
604     /// `alloc`/`realloc` methods of this allocator.
605     ///
606     /// Note to implementors: If this returns `Ok(ptr)`, then `ptr`
607     /// must be considered "currently allocated" and must be
608     /// acceptable input to methods such as `realloc` or `dealloc`,
609     /// *even if* `T` is a zero-sized type. In other words, if your
610     /// `Alloc` implementation overrides this method in a manner
611     /// that can return a zero-sized `ptr`, then all reallocation and
612     /// deallocation methods need to be similarly overridden to accept
613     /// such values as input.
614     ///
615     /// # Errors
616     ///
617     /// Returning `Err` indicates that either memory is exhausted or
618     /// `T` does not meet allocator's size or alignment constraints.
619     ///
620     /// For zero-sized `T`, may return either of `Ok` or `Err`, but
621     /// will *not* yield undefined behavior.
622     ///
623     /// Clients wishing to abort computation in response to an
624     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
625     /// rather than directly invoking `panic!` or similar.
626     ///
627     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr> where Self: Sized,628     fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr>
629     where
630         Self: Sized,
631     {
632         let k = Layout::new::<T>();
633         if k.size() > 0 {
634             unsafe { self.alloc(k).map(|p| p.cast()) }
635         } else {
636             Err(AllocErr)
637         }
638     }
639 
640     /// Deallocates a block suitable for holding an instance of `T`.
641     ///
642     /// The given block must have been produced by this allocator,
643     /// and must be suitable for storing a `T` (in terms of alignment
644     /// as well as minimum and maximum size); otherwise yields
645     /// undefined behavior.
646     ///
647     /// Captures a common usage pattern for allocators.
648     ///
649     /// # Safety
650     ///
651     /// This function is unsafe because undefined behavior can result
652     /// if the caller does not ensure both:
653     ///
654     /// * `ptr` must denote a block of memory currently allocated via this allocator
655     ///
656     /// * the layout of `T` must *fit* that block of memory.
dealloc_one<T>(&mut self, ptr: NonNull<T>) where Self: Sized,657     unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
658     where
659         Self: Sized,
660     {
661         let k = Layout::new::<T>();
662         if k.size() > 0 {
663             self.dealloc(ptr.cast(), k);
664         }
665     }
666 
667     /// Allocates a block suitable for holding `n` instances of `T`.
668     ///
669     /// Captures a common usage pattern for allocators.
670     ///
671     /// The returned block is suitable for passing to the
672     /// `alloc`/`realloc` methods of this allocator.
673     ///
674     /// Note to implementors: If this returns `Ok(ptr)`, then `ptr`
675     /// must be considered "currently allocated" and must be
676     /// acceptable input to methods such as `realloc` or `dealloc`,
677     /// *even if* `T` is a zero-sized type. In other words, if your
678     /// `Alloc` implementation overrides this method in a manner
679     /// that can return a zero-sized `ptr`, then all reallocation and
680     /// deallocation methods need to be similarly overridden to accept
681     /// such values as input.
682     ///
683     /// # Errors
684     ///
685     /// Returning `Err` indicates that either memory is exhausted or
686     /// `[T; n]` does not meet allocator's size or alignment
687     /// constraints.
688     ///
689     /// For zero-sized `T` or `n == 0`, may return either of `Ok` or
690     /// `Err`, but will *not* yield undefined behavior.
691     ///
692     /// Always returns `Err` on arithmetic overflow.
693     ///
694     /// Clients wishing to abort computation in response to an
695     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
696     /// rather than directly invoking `panic!` or similar.
697     ///
698     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr> where Self: Sized,699     fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
700     where
701         Self: Sized,
702     {
703         match Layout::array::<T>(n) {
704             Ok(layout) if layout.size() > 0 => unsafe { self.alloc(layout).map(|p| p.cast()) },
705             _ => Err(AllocErr),
706         }
707     }
708 
709     /// Reallocates a block previously suitable for holding `n_old`
710     /// instances of `T`, returning a block suitable for holding
711     /// `n_new` instances of `T`.
712     ///
713     /// Captures a common usage pattern for allocators.
714     ///
715     /// The returned block is suitable for passing to the
716     /// `alloc`/`realloc` methods of this allocator.
717     ///
718     /// # Safety
719     ///
720     /// This function is unsafe because undefined behavior can result
721     /// if the caller does not ensure all of the following:
722     ///
723     /// * `ptr` must be currently allocated via this allocator,
724     ///
725     /// * the layout of `[T; n_old]` must *fit* that block of memory.
726     ///
727     /// # Errors
728     ///
729     /// Returning `Err` indicates that either memory is exhausted or
730     /// `[T; n_new]` does not meet allocator's size or alignment
731     /// constraints.
732     ///
733     /// For zero-sized `T` or `n_new == 0`, may return either of `Ok` or
734     /// `Err`, but will *not* yield undefined behavior.
735     ///
736     /// Always returns `Err` on arithmetic overflow.
737     ///
738     /// Clients wishing to abort computation in response to a
739     /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
740     /// rather than directly invoking `panic!` or similar.
741     ///
742     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
realloc_array<T>( &mut self, ptr: NonNull<T>, n_old: usize, n_new: usize, ) -> Result<NonNull<T>, AllocErr> where Self: Sized,743     unsafe fn realloc_array<T>(
744         &mut self,
745         ptr: NonNull<T>,
746         n_old: usize,
747         n_new: usize,
748     ) -> Result<NonNull<T>, AllocErr>
749     where
750         Self: Sized,
751     {
752         match (Layout::array::<T>(n_old), Layout::array::<T>(n_new)) {
753             (Ok(ref k_old), Ok(ref k_new)) if k_old.size() > 0 && k_new.size() > 0 => {
754                 debug_assert!(k_old.align() == k_new.align());
755                 self.realloc(ptr.cast(), k_old.clone(), k_new.size())
756                     .map(NonNull::cast)
757             }
758             _ => Err(AllocErr),
759         }
760     }
761 
762     /// Deallocates a block suitable for holding `n` instances of `T`.
763     ///
764     /// Captures a common usage pattern for allocators.
765     ///
766     /// # Safety
767     ///
768     /// This function is unsafe because undefined behavior can result
769     /// if the caller does not ensure both:
770     ///
771     /// * `ptr` must denote a block of memory currently allocated via this allocator
772     ///
773     /// * the layout of `[T; n]` must *fit* that block of memory.
774     ///
775     /// # Errors
776     ///
777     /// Returning `Err` indicates that either `[T; n]` or the given
778     /// memory block does not meet allocator's size or alignment
779     /// constraints.
780     ///
781     /// Always returns `Err` on arithmetic overflow.
dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr> where Self: Sized,782     unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr>
783     where
784         Self: Sized,
785     {
786         match Layout::array::<T>(n) {
787             Ok(k) if k.size() > 0 => {
788                 self.dealloc(ptr.cast(), k);
789                 Ok(())
790             }
791             _ => Err(AllocErr),
792         }
793     }
794 }
795