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