]> git.lizzy.rs Git - rust.git/blob - src/libcore/alloc.rs
Update alloc.rs
[rust.git] / src / libcore / alloc.rs
1 //! Memory allocation APIs
2
3 // ignore-tidy-undocumented-unsafe
4
5 #![stable(feature = "alloc_module", since = "1.28.0")]
6
7 use crate::cmp;
8 use crate::fmt;
9 use crate::mem;
10 use crate::num::NonZeroUsize;
11 use crate::ptr::{self, NonNull};
12 use crate::usize;
13
14 const fn size_align<T>() -> (usize, usize) {
15     (mem::size_of::<T>(), mem::align_of::<T>())
16 }
17
18 /// Layout of a block of memory.
19 ///
20 /// An instance of `Layout` describes a particular layout of memory.
21 /// You build a `Layout` up as an input to give to an allocator.
22 ///
23 /// All layouts have an associated non-negative size and a
24 /// power-of-two alignment.
25 ///
26 /// (Note however that layouts are *not* required to have positive
27 /// size, even though many allocators require that all memory
28 /// requests have positive size. A caller to the `AllocRef::alloc`
29 /// method must either ensure that conditions like this are met, or
30 /// use specific allocators with looser requirements.)
31 #[stable(feature = "alloc_layout", since = "1.28.0")]
32 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
33 #[lang = "alloc_layout"]
34 pub struct Layout {
35     // size of the requested block of memory, measured in bytes.
36     size_: usize,
37
38     // alignment of the requested block of memory, measured in bytes.
39     // we ensure that this is always a power-of-two, because API's
40     // like `posix_memalign` require it and it is a reasonable
41     // constraint to impose on Layout constructors.
42     //
43     // (However, we do not analogously require `align >= sizeof(void*)`,
44     //  even though that is *also* a requirement of `posix_memalign`.)
45     align_: NonZeroUsize,
46 }
47
48 impl Layout {
49     /// Constructs a `Layout` from a given `size` and `align`,
50     /// or returns `LayoutErr` if any of the following conditions
51     /// are not met:
52     ///
53     /// * `align` must not be zero,
54     ///
55     /// * `align` must be a power of two,
56     ///
57     /// * `size`, when rounded up to the nearest multiple of `align`,
58     ///    must not overflow (i.e., the rounded value must be less than
59     ///    `usize::MAX`).
60     #[stable(feature = "alloc_layout", since = "1.28.0")]
61     #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
62     #[inline]
63     pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
64         if !align.is_power_of_two() {
65             return Err(LayoutErr { private: () });
66         }
67
68         // (power-of-two implies align != 0.)
69
70         // Rounded up size is:
71         //   size_rounded_up = (size + align - 1) & !(align - 1);
72         //
73         // We know from above that align != 0. If adding (align - 1)
74         // does not overflow, then rounding up will be fine.
75         //
76         // Conversely, &-masking with !(align - 1) will subtract off
77         // only low-order-bits. Thus if overflow occurs with the sum,
78         // the &-mask cannot subtract enough to undo that overflow.
79         //
80         // Above implies that checking for summation overflow is both
81         // necessary and sufficient.
82         if size > usize::MAX - (align - 1) {
83             return Err(LayoutErr { private: () });
84         }
85
86         unsafe { Ok(Layout::from_size_align_unchecked(size, align)) }
87     }
88
89     /// Creates a layout, bypassing all checks.
90     ///
91     /// # Safety
92     ///
93     /// This function is unsafe as it does not verify the preconditions from
94     /// [`Layout::from_size_align`](#method.from_size_align).
95     #[stable(feature = "alloc_layout", since = "1.28.0")]
96     #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")]
97     #[inline]
98     pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
99         Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) }
100     }
101
102     /// The minimum size in bytes for a memory block of this layout.
103     #[stable(feature = "alloc_layout", since = "1.28.0")]
104     #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
105     #[inline]
106     pub const fn size(&self) -> usize {
107         self.size_
108     }
109
110     /// The minimum byte alignment for a memory block of this layout.
111     #[stable(feature = "alloc_layout", since = "1.28.0")]
112     #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
113     #[inline]
114     pub const fn align(&self) -> usize {
115         self.align_.get()
116     }
117
118     /// Constructs a `Layout` suitable for holding a value of type `T`.
119     #[stable(feature = "alloc_layout", since = "1.28.0")]
120     #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
121     #[inline]
122     pub const fn new<T>() -> Self {
123         let (size, align) = size_align::<T>();
124         // Note that the align is guaranteed by rustc to be a power of two and
125         // the size+align combo is guaranteed to fit in our address space. As a
126         // result use the unchecked constructor here to avoid inserting code
127         // that panics if it isn't optimized well enough.
128         unsafe { Layout::from_size_align_unchecked(size, align) }
129     }
130
131     /// Produces layout describing a record that could be used to
132     /// allocate backing structure for `T` (which could be a trait
133     /// or other unsized type like a slice).
134     #[stable(feature = "alloc_layout", since = "1.28.0")]
135     #[inline]
136     pub fn for_value<T: ?Sized>(t: &T) -> Self {
137         let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
138         // See rationale in `new` for why this is using an unsafe variant below
139         debug_assert!(Layout::from_size_align(size, align).is_ok());
140         unsafe { Layout::from_size_align_unchecked(size, align) }
141     }
142
143     /// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
144     ///
145     /// Note that the pointer value may potentially represent a valid pointer,
146     /// which means this must not be used as a "not yet initialized"
147     /// sentinel value. Types that lazily allocate must track initialization by
148     /// some other means.
149     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
150     pub const fn dangling(&self) -> NonNull<u8> {
151         // align is non-zero and a power of two
152         unsafe { NonNull::new_unchecked(self.align() as *mut u8) }
153     }
154
155     /// Creates a layout describing the record that can hold a value
156     /// of the same layout as `self`, but that also is aligned to
157     /// alignment `align` (measured in bytes).
158     ///
159     /// If `self` already meets the prescribed alignment, then returns
160     /// `self`.
161     ///
162     /// Note that this method does not add any padding to the overall
163     /// size, regardless of whether the returned layout has a different
164     /// alignment. In other words, if `K` has size 16, `K.align_to(32)`
165     /// will *still* have size 16.
166     ///
167     /// Returns an error if the combination of `self.size()` and the given
168     /// `align` violates the conditions listed in
169     /// [`Layout::from_size_align`](#method.from_size_align).
170     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
171     #[inline]
172     pub fn align_to(&self, align: usize) -> Result<Self, LayoutErr> {
173         Layout::from_size_align(self.size(), cmp::max(self.align(), align))
174     }
175
176     /// Returns the amount of padding we must insert after `self`
177     /// to ensure that the following address will satisfy `align`
178     /// (measured in bytes).
179     ///
180     /// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)`
181     /// returns 3, because that is the minimum number of bytes of
182     /// padding required to get a 4-aligned address (assuming that the
183     /// corresponding memory block starts at a 4-aligned address).
184     ///
185     /// The return value of this function has no meaning if `align` is
186     /// not a power-of-two.
187     ///
188     /// Note that the utility of the returned value requires `align`
189     /// to be less than or equal to the alignment of the starting
190     /// address for the whole allocated block of memory. One way to
191     /// satisfy this constraint is to ensure `align <= self.align()`.
192     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
193     #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
194     #[inline]
195     pub const fn padding_needed_for(&self, align: usize) -> usize {
196         let len = self.size();
197
198         // Rounded up value is:
199         //   len_rounded_up = (len + align - 1) & !(align - 1);
200         // and then we return the padding difference: `len_rounded_up - len`.
201         //
202         // We use modular arithmetic throughout:
203         //
204         // 1. align is guaranteed to be > 0, so align - 1 is always
205         //    valid.
206         //
207         // 2. `len + align - 1` can overflow by at most `align - 1`,
208         //    so the &-mask with `!(align - 1)` will ensure that in the
209         //    case of overflow, `len_rounded_up` will itself be 0.
210         //    Thus the returned padding, when added to `len`, yields 0,
211         //    which trivially satisfies the alignment `align`.
212         //
213         // (Of course, attempts to allocate blocks of memory whose
214         // size and padding overflow in the above manner should cause
215         // the allocator to yield an error anyway.)
216
217         let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
218         len_rounded_up.wrapping_sub(len)
219     }
220
221     /// Creates a layout by rounding the size of this layout up to a multiple
222     /// of the layout's alignment.
223     ///
224     /// This is equivalent to adding the result of `padding_needed_for`
225     /// to the layout's current size.
226     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
227     #[inline]
228     pub fn pad_to_align(&self) -> Layout {
229         let pad = self.padding_needed_for(self.align());
230         // This cannot overflow. Quoting from the invariant of Layout:
231         // > `size`, when rounded up to the nearest multiple of `align`,
232         // > must not overflow (i.e., the rounded value must be less than
233         // > `usize::MAX`)
234         let new_size = self.size() + pad;
235
236         Layout::from_size_align(new_size, self.align()).unwrap()
237     }
238
239     /// Creates a layout describing the record for `n` instances of
240     /// `self`, with a suitable amount of padding between each to
241     /// ensure that each instance is given its requested size and
242     /// alignment. On success, returns `(k, offs)` where `k` is the
243     /// layout of the array and `offs` is the distance between the start
244     /// of each element in the array.
245     ///
246     /// On arithmetic overflow, returns `LayoutErr`.
247     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
248     #[inline]
249     pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
250         // This cannot overflow. Quoting from the invariant of Layout:
251         // > `size`, when rounded up to the nearest multiple of `align`,
252         // > must not overflow (i.e., the rounded value must be less than
253         // > `usize::MAX`)
254         let padded_size = self.size() + self.padding_needed_for(self.align());
255         let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
256
257         unsafe {
258             // self.align is already known to be valid and alloc_size has been
259             // padded already.
260             Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size))
261         }
262     }
263
264     /// Creates a layout describing the record for `self` followed by
265     /// `next`, including any necessary padding to ensure that `next`
266     /// will be properly aligned. Note that the resulting layout will
267     /// satisfy the alignment properties of both `self` and `next`.
268     ///
269     /// The resulting layout will be the same as that of a C struct containing
270     /// two fields with the layouts of `self` and `next`, in that order.
271     ///
272     /// Returns `Some((k, offset))`, where `k` is layout of the concatenated
273     /// record and `offset` is the relative location, in bytes, of the
274     /// start of the `next` embedded within the concatenated record
275     /// (assuming that the record itself starts at offset 0).
276     ///
277     /// On arithmetic overflow, returns `LayoutErr`.
278     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
279     #[inline]
280     pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
281         let new_align = cmp::max(self.align(), next.align());
282         let pad = self.padding_needed_for(next.align());
283
284         let offset = self.size().checked_add(pad).ok_or(LayoutErr { private: () })?;
285         let new_size = offset.checked_add(next.size()).ok_or(LayoutErr { private: () })?;
286
287         let layout = Layout::from_size_align(new_size, new_align)?;
288         Ok((layout, offset))
289     }
290
291     /// Creates a layout describing the record for `n` instances of
292     /// `self`, with no padding between each instance.
293     ///
294     /// Note that, unlike `repeat`, `repeat_packed` does not guarantee
295     /// that the repeated instances of `self` will be properly
296     /// aligned, even if a given instance of `self` is properly
297     /// aligned. In other words, if the layout returned by
298     /// `repeat_packed` is used to allocate an array, it is not
299     /// guaranteed that all elements in the array will be properly
300     /// aligned.
301     ///
302     /// On arithmetic overflow, returns `LayoutErr`.
303     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
304     #[inline]
305     pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
306         let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
307         Layout::from_size_align(size, self.align())
308     }
309
310     /// Creates a layout describing the record for `self` followed by
311     /// `next` with no additional padding between the two. Since no
312     /// padding is inserted, the alignment of `next` is irrelevant,
313     /// and is not incorporated *at all* into the resulting layout.
314     ///
315     /// On arithmetic overflow, returns `LayoutErr`.
316     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
317     #[inline]
318     pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutErr> {
319         let new_size = self.size().checked_add(next.size()).ok_or(LayoutErr { private: () })?;
320         Layout::from_size_align(new_size, self.align())
321     }
322
323     /// Creates a layout describing the record for a `[T; n]`.
324     ///
325     /// On arithmetic overflow, returns `LayoutErr`.
326     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
327     #[inline]
328     pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
329         Layout::new::<T>().repeat(n).map(|(k, offs)| {
330             debug_assert!(offs == mem::size_of::<T>());
331             k
332         })
333     }
334 }
335
336 /// The parameters given to `Layout::from_size_align`
337 /// or some other `Layout` constructor
338 /// do not satisfy its documented constraints.
339 #[stable(feature = "alloc_layout", since = "1.28.0")]
340 #[derive(Clone, PartialEq, Eq, Debug)]
341 pub struct LayoutErr {
342     private: (),
343 }
344
345 // (we need this for downstream impl of trait Error)
346 #[stable(feature = "alloc_layout", since = "1.28.0")]
347 impl fmt::Display for LayoutErr {
348     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349         f.write_str("invalid parameters to Layout::from_size_align")
350     }
351 }
352
353 /// The `AllocErr` error indicates an allocation failure
354 /// that may be due to resource exhaustion or to
355 /// something wrong when combining the given input arguments with this
356 /// allocator.
357 #[unstable(feature = "allocator_api", issue = "32838")]
358 #[derive(Clone, PartialEq, Eq, Debug)]
359 pub struct AllocErr;
360
361 // (we need this for downstream impl of trait Error)
362 #[unstable(feature = "allocator_api", issue = "32838")]
363 impl fmt::Display for AllocErr {
364     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
365         f.write_str("memory allocation failed")
366     }
367 }
368
369 /// The `CannotReallocInPlace` error is used when [`grow_in_place`] or
370 /// [`shrink_in_place`] were unable to reuse the given memory block for
371 /// a requested layout.
372 ///
373 /// [`grow_in_place`]: ./trait.AllocRef.html#method.grow_in_place
374 /// [`shrink_in_place`]: ./trait.AllocRef.html#method.shrink_in_place
375 #[unstable(feature = "allocator_api", issue = "32838")]
376 #[derive(Clone, PartialEq, Eq, Debug)]
377 pub struct CannotReallocInPlace;
378
379 #[unstable(feature = "allocator_api", issue = "32838")]
380 impl CannotReallocInPlace {
381     pub fn description(&self) -> &str {
382         "cannot reallocate allocator's memory in place"
383     }
384 }
385
386 // (we need this for downstream impl of trait Error)
387 #[unstable(feature = "allocator_api", issue = "32838")]
388 impl fmt::Display for CannotReallocInPlace {
389     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390         write!(f, "{}", self.description())
391     }
392 }
393
394 /// A memory allocator that can be registered as the standard library’s default
395 /// through the `#[global_allocator]` attribute.
396 ///
397 /// Some of the methods require that a memory block be *currently
398 /// allocated* via an allocator. This means that:
399 ///
400 /// * the starting address for that memory block was previously
401 ///   returned by a previous call to an allocation method
402 ///   such as `alloc`, and
403 ///
404 /// * the memory block has not been subsequently deallocated, where
405 ///   blocks are deallocated either by being passed to a deallocation
406 ///   method such as `dealloc` or by being
407 ///   passed to a reallocation method that returns a non-null pointer.
408 ///
409 ///
410 /// # Example
411 ///
412 /// ```no_run
413 /// use std::alloc::{GlobalAlloc, Layout, alloc};
414 /// use std::ptr::null_mut;
415 ///
416 /// struct MyAllocator;
417 ///
418 /// unsafe impl GlobalAlloc for MyAllocator {
419 ///     unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
420 ///     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
421 /// }
422 ///
423 /// #[global_allocator]
424 /// static A: MyAllocator = MyAllocator;
425 ///
426 /// fn main() {
427 ///     unsafe {
428 ///         assert!(alloc(Layout::new::<u32>()).is_null())
429 ///     }
430 /// }
431 /// ```
432 ///
433 /// # Safety
434 ///
435 /// The `GlobalAlloc` trait is an `unsafe` trait for a number of reasons, and
436 /// implementors must ensure that they adhere to these contracts:
437 ///
438 /// * It's undefined behavior if global allocators unwind. This restriction may
439 ///   be lifted in the future, but currently a panic from any of these
440 ///   functions may lead to memory unsafety.
441 ///
442 /// * `Layout` queries and calculations in general must be correct. Callers of
443 ///   this trait are allowed to rely on the contracts defined on each method,
444 ///   and implementors must ensure such contracts remain true.
445 #[stable(feature = "global_alloc", since = "1.28.0")]
446 pub unsafe trait GlobalAlloc {
447     /// Allocate memory as described by the given `layout`.
448     ///
449     /// Returns a pointer to newly-allocated memory,
450     /// or null to indicate allocation failure.
451     ///
452     /// # Safety
453     ///
454     /// This function is unsafe because undefined behavior can result
455     /// if the caller does not ensure that `layout` has non-zero size.
456     ///
457     /// (Extension subtraits might provide more specific bounds on
458     /// behavior, e.g., guarantee a sentinel address or a null pointer
459     /// in response to a zero-size allocation request.)
460     ///
461     /// The allocated block of memory may or may not be initialized.
462     ///
463     /// # Errors
464     ///
465     /// Returning a null pointer indicates that either memory is exhausted
466     /// or `layout` does not meet this allocator's size or alignment constraints.
467     ///
468     /// Implementations are encouraged to return null on memory
469     /// exhaustion rather than aborting, but this is not
470     /// a strict requirement. (Specifically: it is *legal* to
471     /// implement this trait atop an underlying native allocation
472     /// library that aborts on memory exhaustion.)
473     ///
474     /// Clients wishing to abort computation in response to an
475     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
476     /// rather than directly invoking `panic!` or similar.
477     ///
478     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
479     #[stable(feature = "global_alloc", since = "1.28.0")]
480     unsafe fn alloc(&self, layout: Layout) -> *mut u8;
481
482     /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
483     ///
484     /// # Safety
485     ///
486     /// This function is unsafe because undefined behavior can result
487     /// if the caller does not ensure all of the following:
488     ///
489     /// * `ptr` must denote a block of memory currently allocated via
490     ///   this allocator,
491     ///
492     /// * `layout` must be the same layout that was used
493     ///   to allocate that block of memory,
494     #[stable(feature = "global_alloc", since = "1.28.0")]
495     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
496
497     /// Behaves like `alloc`, but also ensures that the contents
498     /// are set to zero before being returned.
499     ///
500     /// # Safety
501     ///
502     /// This function is unsafe for the same reasons that `alloc` is.
503     /// However the allocated block of memory is guaranteed to be initialized.
504     ///
505     /// # Errors
506     ///
507     /// Returning a null pointer indicates that either memory is exhausted
508     /// or `layout` does not meet allocator's size or alignment constraints,
509     /// just as in `alloc`.
510     ///
511     /// Clients wishing to abort computation in response to an
512     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
513     /// rather than directly invoking `panic!` or similar.
514     ///
515     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
516     #[stable(feature = "global_alloc", since = "1.28.0")]
517     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
518         let size = layout.size();
519         let ptr = self.alloc(layout);
520         if !ptr.is_null() {
521             ptr::write_bytes(ptr, 0, size);
522         }
523         ptr
524     }
525
526     /// Shrink or grow a block of memory to the given `new_size`.
527     /// The block is described by the given `ptr` pointer and `layout`.
528     ///
529     /// If this returns a non-null pointer, then ownership of the memory block
530     /// referenced by `ptr` has been transferred to this allocator.
531     /// The memory may or may not have been deallocated,
532     /// and should be considered unusable (unless of course it was
533     /// transferred back to the caller again via the return value of
534     /// this method). The new memory block is allocated with `layout`, but
535     /// with the `size` updated to `new_size`.
536     ///
537     /// If this method returns null, then ownership of the memory
538     /// block has not been transferred to this allocator, and the
539     /// contents of the memory block are unaltered.
540     ///
541     /// # Safety
542     ///
543     /// This function is unsafe because undefined behavior can result
544     /// if the caller does not ensure all of the following:
545     ///
546     /// * `ptr` must be currently allocated via this allocator,
547     ///
548     /// * `layout` must be the same layout that was used
549     ///   to allocate that block of memory,
550     ///
551     /// * `new_size` must be greater than zero.
552     ///
553     /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
554     ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
555     ///
556     /// (Extension subtraits might provide more specific bounds on
557     /// behavior, e.g., guarantee a sentinel address or a null pointer
558     /// in response to a zero-size allocation request.)
559     ///
560     /// # Errors
561     ///
562     /// Returns null if the new layout does not meet the size
563     /// and alignment constraints of the allocator, or if reallocation
564     /// otherwise fails.
565     ///
566     /// Implementations are encouraged to return null on memory
567     /// exhaustion rather than panicking or aborting, but this is not
568     /// a strict requirement. (Specifically: it is *legal* to
569     /// implement this trait atop an underlying native allocation
570     /// library that aborts on memory exhaustion.)
571     ///
572     /// Clients wishing to abort computation in response to a
573     /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
574     /// rather than directly invoking `panic!` or similar.
575     ///
576     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
577     #[stable(feature = "global_alloc", since = "1.28.0")]
578     unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
579         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
580         let new_ptr = self.alloc(new_layout);
581         if !new_ptr.is_null() {
582             ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size));
583             self.dealloc(ptr, layout);
584         }
585         new_ptr
586     }
587 }
588
589 /// An implementation of `AllocRef` can allocate, reallocate, and
590 /// deallocate arbitrary blocks of data described via `Layout`.
591 ///
592 /// `AllocRef` is designed to be implemented on ZSTs, references, or
593 /// smart pointers because having an allocator like `MyAlloc([u8; N])`
594 /// cannot be moved, without updating the pointers to the allocated
595 /// memory.
596 ///
597 /// Some of the methods require that a memory block be *currently
598 /// allocated* via an allocator. This means that:
599 ///
600 /// * the starting address for that memory block was previously
601 ///   returned by a previous call to an allocation method (`alloc`,
602 ///   `alloc_zeroed`) or reallocation method (`realloc`), and
603 ///
604 /// * the memory block has not been subsequently deallocated, where
605 ///   blocks are deallocated either by being passed to a deallocation
606 ///   method (`dealloc`) or by being passed to a reallocation method
607 ///  (see above) that returns `Ok`.
608 ///
609 /// A note regarding zero-sized types and zero-sized layouts: many
610 /// methods in the `AllocRef` trait state that allocation requests
611 /// must be non-zero size, or else undefined behavior can result.
612 ///
613 /// * If an `AllocRef` implementation chooses to return `Ok` in this
614 ///   case (i.e., the pointer denotes a zero-sized inaccessible block)
615 ///   then that returned pointer must be considered "currently
616 ///   allocated". On such an allocator, *all* methods that take
617 ///   currently-allocated pointers as inputs must accept these
618 ///   zero-sized pointers, *without* causing undefined behavior.
619 ///
620 /// * In other words, if a zero-sized pointer can flow out of an
621 ///   allocator, then that allocator must likewise accept that pointer
622 ///   flowing back into its deallocation and reallocation methods.
623 ///
624 /// Some of the methods require that a layout *fit* a memory block.
625 /// What it means for a layout to "fit" a memory block means (or
626 /// equivalently, for a memory block to "fit" a layout) is that the
627 /// following two conditions must hold:
628 ///
629 /// 1. The block's starting address must be aligned to `layout.align()`.
630 ///
631 /// 2. The block's size must fall in the range `[use_min, use_max]`, where:
632 ///
633 ///    * `use_min` is `layout.size()`, and
634 ///
635 ///    * `use_max` is the capacity that was returned.
636 ///
637 /// Note that:
638 ///
639 ///  * the size of the layout most recently used to allocate the block
640 ///    is guaranteed to be in the range `[use_min, use_max]`, and
641 ///
642 ///  * a lower-bound on `use_max` can be safely approximated by a call to
643 ///    `usable_size`.
644 ///
645 ///  * if a layout `k` fits a memory block (denoted by `ptr`)
646 ///    currently allocated via an allocator `a`, then it is legal to
647 ///    use that layout to deallocate it, i.e., `a.dealloc(ptr, k);`.
648 ///
649 ///  * if an allocator does not support overallocating, it is fine to
650 ///    simply return `layout.size()` as the allocated size.
651 ///
652 /// # Safety
653 ///
654 /// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and
655 /// implementors must ensure that they adhere to these contracts:
656 ///
657 /// * Pointers returned from allocation functions must point to valid memory and
658 ///   retain their validity until at least one instance of `AllocRef` is dropped
659 ///   itself.
660 ///
661 /// * Cloning or moving the allocator must not invalidate pointers returned
662 ///   from this allocator. Cloning must return a reference to the same allocator.
663 ///
664 /// * `Layout` queries and calculations in general must be correct. Callers of
665 ///   this trait are allowed to rely on the contracts defined on each method,
666 ///   and implementors must ensure such contracts remain true.
667 ///
668 /// Note that this list may get tweaked over time as clarifications are made in
669 /// the future.
670 #[unstable(feature = "allocator_api", issue = "32838")]
671 pub unsafe trait AllocRef {
672     // (Note: some existing allocators have unspecified but well-defined
673     // behavior in response to a zero size allocation request ;
674     // e.g., in C, `malloc` of 0 will either return a null pointer or a
675     // unique pointer, but will not have arbitrary undefined
676     // behavior.
677     // However in jemalloc for example,
678     // `mallocx(0)` is documented as undefined behavior.)
679
680     /// On success, returns a pointer meeting the size and alignment
681     /// guarantees of `layout` and the actual size of the allocated block,
682     /// which must be greater than or equal to `layout.size()`.
683     ///
684     /// If this method returns an `Ok(addr)`, then the `addr` returned
685     /// will be non-null address pointing to a block of storage
686     /// suitable for holding an instance of `layout`.
687     ///
688     /// The returned block of storage may or may not have its contents
689     /// initialized. (Extension subtraits might restrict this
690     /// behavior, e.g., to ensure initialization to particular sets of
691     /// bit patterns.)
692     ///
693     /// # Safety
694     ///
695     /// This function is unsafe because undefined behavior can result
696     /// if the caller does not ensure that `layout` has non-zero size.
697     ///
698     /// (Extension subtraits might provide more specific bounds on
699     /// behavior, e.g., guarantee a sentinel address or a null pointer
700     /// in response to a zero-size allocation request.)
701     ///
702     /// # Errors
703     ///
704     /// Returning `Err` indicates that either memory is exhausted or
705     /// `layout` does not meet allocator's size or alignment
706     /// constraints.
707     ///
708     /// Implementations are encouraged to return `Err` on memory
709     /// exhaustion rather than panicking or aborting, but this is not
710     /// a strict requirement. (Specifically: it is *legal* to
711     /// implement this trait atop an underlying native allocation
712     /// library that aborts on memory exhaustion.)
713     ///
714     /// Clients wishing to abort computation in response to an
715     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
716     /// rather than directly invoking `panic!` or similar.
717     ///
718     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
719     unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>;
720
721     /// Deallocate the memory referenced by `ptr`.
722     ///
723     /// # Safety
724     ///
725     /// This function is unsafe because undefined behavior can result
726     /// if the caller does not ensure all of the following:
727     ///
728     /// * `ptr` must denote a block of memory currently allocated via
729     ///   this allocator,
730     ///
731     /// * `layout` must *fit* that block of memory,
732     ///
733     /// * In addition to fitting the block of memory `layout`, the
734     ///   alignment of the `layout` must match the alignment used
735     ///   to allocate that block of memory.
736     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
737
738     /// Behaves like `alloc`, but also ensures that the contents
739     /// are set to zero before being returned.
740     ///
741     /// # Safety
742     ///
743     /// This function is unsafe for the same reasons that `alloc` is.
744     ///
745     /// # Errors
746     ///
747     /// Returning `Err` indicates that either memory is exhausted or
748     /// `layout` does not meet allocator's size or alignment
749     /// constraints, just as in `alloc`.
750     ///
751     /// Clients wishing to abort computation in response to an
752     /// allocation error are encouraged to call the [`handle_alloc_error`] function,
753     /// rather than directly invoking `panic!` or similar.
754     ///
755     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
756     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
757         let size = layout.size();
758         let result = self.alloc(layout);
759         if let Ok((p, _)) = result {
760             ptr::write_bytes(p.as_ptr(), 0, size);
761         }
762         result
763     }
764
765     // == METHODS FOR MEMORY REUSE ==
766     // realloc. alloc_excess, realloc_excess
767
768     /// Returns a pointer suitable for holding data described by
769     /// a new layout with `layout`’s alignment and a size given
770     /// by `new_size` and the actual size of the allocated block.
771     /// The latter is greater than or equal to `layout.size()`.
772     /// To accomplish this, the allocator may extend or shrink
773     /// the allocation referenced by `ptr` to fit the new layout.
774     ///
775     /// If this returns `Ok`, then ownership of the memory block
776     /// referenced by `ptr` has been transferred to this
777     /// allocator. The memory may or may not have been freed, and
778     /// should be considered unusable (unless of course it was
779     /// transferred back to the caller again via the return value of
780     /// this method).
781     ///
782     /// If this method returns `Err`, then ownership of the memory
783     /// block has not been transferred to this allocator, and the
784     /// contents of the memory block are unaltered.
785     ///
786     /// # Safety
787     ///
788     /// This function is unsafe because undefined behavior can result
789     /// if the caller does not ensure all of the following:
790     ///
791     /// * `ptr` must be currently allocated via this allocator,
792     ///
793     /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
794     ///   argument need not fit it.)
795     ///
796     /// * `new_size` must be greater than zero.
797     ///
798     /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
799     ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
800     ///
801     /// (Extension subtraits might provide more specific bounds on
802     /// behavior, e.g., guarantee a sentinel address or a null pointer
803     /// in response to a zero-size allocation request.)
804     ///
805     /// # Errors
806     ///
807     /// Returns `Err` only if the new layout
808     /// does not meet the allocator's size
809     /// and alignment constraints of the allocator, or if reallocation
810     /// otherwise fails.
811     ///
812     /// Implementations are encouraged to return `Err` on memory
813     /// exhaustion rather than panicking or aborting, but this is not
814     /// a strict requirement. (Specifically: it is *legal* to
815     /// implement this trait atop an underlying native allocation
816     /// library that aborts on memory exhaustion.)
817     ///
818     /// Clients wishing to abort computation in response to a
819     /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
820     /// rather than directly invoking `panic!` or similar.
821     ///
822     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
823     unsafe fn realloc(
824         &mut self,
825         ptr: NonNull<u8>,
826         layout: Layout,
827         new_size: usize,
828     ) -> Result<(NonNull<u8>, usize), AllocErr> {
829         let old_size = layout.size();
830
831         if new_size > old_size {
832             if let Ok(size) = self.grow_in_place(ptr, layout, new_size) {
833                 return Ok((ptr, size));
834             }
835         } else if new_size < old_size {
836             if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) {
837                 return Ok((ptr, size));
838             }
839         } else {
840             return Ok((ptr, new_size));
841         }
842
843         // otherwise, fall back on alloc + copy + dealloc.
844         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
845         let result = self.alloc(new_layout);
846         if let Ok((new_ptr, _)) = result {
847             ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
848             self.dealloc(ptr, layout);
849         }
850         result
851     }
852
853     /// Behaves like `realloc`, but also ensures that the new contents
854     /// are set to zero before being returned.
855     ///
856     /// # Safety
857     ///
858     /// This function is unsafe for the same reasons that `realloc` is.
859     ///
860     /// # Errors
861     ///
862     /// Returns `Err` only if the new layout
863     /// does not meet the allocator's size
864     /// and alignment constraints of the allocator, or if reallocation
865     /// otherwise fails.
866     ///
867     /// Implementations are encouraged to return `Err` on memory
868     /// exhaustion rather than panicking or aborting, but this is not
869     /// a strict requirement. (Specifically: it is *legal* to
870     /// implement this trait atop an underlying native allocation
871     /// library that aborts on memory exhaustion.)
872     ///
873     /// Clients wishing to abort computation in response to a
874     /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
875     /// rather than directly invoking `panic!` or similar.
876     ///
877     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
878     unsafe fn realloc_zeroed(
879         &mut self,
880         ptr: NonNull<u8>,
881         layout: Layout,
882         new_size: usize,
883     ) -> Result<(NonNull<u8>, usize), AllocErr> {
884         let old_size = layout.size();
885
886         if new_size > old_size {
887             if let Ok(size) = self.grow_in_place_zeroed(ptr, layout, new_size) {
888                 return Ok((ptr, size));
889             }
890         } else if new_size < old_size {
891             if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) {
892                 return Ok((ptr, size));
893             }
894         } else {
895             return Ok((ptr, new_size));
896         }
897
898         // otherwise, fall back on alloc + copy + dealloc.
899         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
900         let result = self.alloc_zeroed(new_layout);
901         if let Ok((new_ptr, _)) = result {
902             ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
903             self.dealloc(ptr, layout);
904         }
905         result
906     }
907
908     /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
909     ///
910     /// If this returns `Ok`, then the allocator has asserted that the
911     /// memory block referenced by `ptr` now fits `new_size`, and thus can
912     /// be used to carry data of a layout of that size and same alignment as
913     /// `layout`. The returned value is the new size of the allocated block.
914     /// (The allocator is allowed to expend effort to accomplish this, such
915     /// as extending the memory block to include successor blocks, or virtual
916     /// memory tricks.)
917     ///
918     /// Regardless of what this method returns, ownership of the
919     /// memory block referenced by `ptr` has not been transferred, and
920     /// the contents of the memory block are unaltered.
921     ///
922     /// # Safety
923     ///
924     /// This function is unsafe because undefined behavior can result
925     /// if the caller does not ensure all of the following:
926     ///
927     /// * `ptr` must be currently allocated via this allocator,
928     ///
929     /// * `layout` must *fit* the `ptr` (see above); note the
930     ///   `new_size` argument need not fit it,
931     ///
932     /// * `new_size` must not be less than `layout.size()`,
933     ///
934     /// # Errors
935     ///
936     /// Returns `Err(CannotReallocInPlace)` when the allocator is
937     /// unable to assert that the memory block referenced by `ptr`
938     /// could fit `layout`.
939     ///
940     /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
941     /// function; clients are expected either to be able to recover from
942     /// `grow_in_place` failures without aborting, or to fall back on
943     /// another reallocation method before resorting to an abort.
944     #[inline]
945     unsafe fn grow_in_place(
946         &mut self,
947         ptr: NonNull<u8>,
948         layout: Layout,
949         new_size: usize,
950     ) -> Result<usize, CannotReallocInPlace> {
951         let _ = ptr;
952         let _ = layout;
953         let _ = new_size;
954         Err(CannotReallocInPlace)
955     }
956
957     /// Behaves like `grow_in_place`, but also ensures that the new
958     /// contents are set to zero before being returned.
959     ///
960     /// # Safety
961     ///
962     /// This function is unsafe for the same reasons that `grow_in_place` is.
963     ///
964     /// # Errors
965     ///
966     /// Returns `Err(CannotReallocInPlace)` when the allocator is
967     /// unable to assert that the memory block referenced by `ptr`
968     /// could fit `layout`.
969     ///
970     /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
971     /// function; clients are expected either to be able to recover from
972     /// `grow_in_place` failures without aborting, or to fall back on
973     /// another reallocation method before resorting to an abort.
974     unsafe fn grow_in_place_zeroed(
975         &mut self,
976         ptr: NonNull<u8>,
977         layout: Layout,
978         new_size: usize,
979     ) -> Result<usize, CannotReallocInPlace> {
980         let size = self.grow_in_place(ptr, layout, new_size)?;
981         ptr.as_ptr().add(layout.size()).write_bytes(0, new_size - layout.size());
982         Ok(size)
983     }
984
985     /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
986     ///
987     /// If this returns `Ok`, then the allocator has asserted that the
988     /// memory block referenced by `ptr` now fits `new_size`, and
989     /// thus can only be used to carry data of that smaller
990     /// layout. The returned value is the new size the allocated block.
991     /// (The allocator is allowed to take advantage of this,
992     /// carving off portions of the block for reuse elsewhere.) The
993     /// truncated contents of the block within the smaller layout are
994     /// unaltered, and ownership of block has not been transferred.
995     ///
996     /// If this returns `Err`, then the memory block is considered to
997     /// still represent the original (larger) `layout`. None of the
998     /// block has been carved off for reuse elsewhere, ownership of
999     /// the memory block has not been transferred, and the contents of
1000     /// the memory block are unaltered.
1001     ///
1002     /// # Safety
1003     ///
1004     /// This function is unsafe because undefined behavior can result
1005     /// if the caller does not ensure all of the following:
1006     ///
1007     /// * `ptr` must be currently allocated via this allocator,
1008     ///
1009     /// * `layout` must *fit* the `ptr` (see above); note the
1010     ///   `new_size` argument need not fit it,
1011     ///
1012     /// * `new_size` must not be greater than `layout.size()`
1013     ///   (and must be greater than zero),
1014     ///
1015     /// # Errors
1016     ///
1017     /// Returns `Err(CannotReallocInPlace)` when the allocator is
1018     /// unable to assert that the memory block referenced by `ptr`
1019     /// could fit `layout`.
1020     ///
1021     /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
1022     /// function; clients are expected either to be able to recover from
1023     /// `shrink_in_place` failures without aborting, or to fall back
1024     /// on another reallocation method before resorting to an abort.
1025     #[inline]
1026     unsafe fn shrink_in_place(
1027         &mut self,
1028         ptr: NonNull<u8>,
1029         layout: Layout,
1030         new_size: usize,
1031     ) -> Result<usize, CannotReallocInPlace> {
1032         let _ = ptr;
1033         let _ = layout;
1034         let _ = new_size;
1035         Err(CannotReallocInPlace)
1036     }
1037 }