/// and implementors must ensure such contracts remain true.
///
/// * You may not rely on allocations actually happening, even if there are explicit
-/// heap allocations in the source. The optimizer may detect allocation/deallocation
-/// pairs that it can instead move to stack allocations/deallocations and thus never
-/// invoke the allocator here.
-/// More concretely, the following code example is unsound, irrespective of whether your
-/// custom allocator allows counting how many allocations have happened.
-///
-/// ```text
+/// heap allocations in the source. The optimizer may detect unused allocations that it can either
+/// eliminate entirely or move to the stack and thus never invoke the allocator. The
+/// optimizer may further assume that allocation is infallible, so code that used to fail due
+/// to allocator failures may now suddenly work because the optimizer worked around the
+/// need for an allocation. More concretely, the following code example is unsound, irrespective
+/// of whether your custom allocator allows counting how many allocations have happened.
+///
+/// ```rust,ignore (unsound and has placeholders)
/// drop(Box::new(42));
/// let number_of_heap_allocs = /* call private allocator API */;
/// unsafe { std::intrinsics::assume(number_of_heap_allocs > 0); }
/// ```
///
-/// Note that allocation/deallocation pairs being moved to the stack is not the only
+/// Note that the optimizations mentioned above are not the only
/// optimization that can be applied. You may generally not rely on heap allocations
-/// happening, if they can be removed without changing program behaviour.
-/// Whether allocations happen or not is not part of the program behaviour, even if it
-/// could be detected via an allocator that tracks allocations.
+/// happening if they can be removed without changing program behavior.
+/// Whether allocations happen or not is not part of the program behavior, even if it
+/// could be detected via an allocator that tracks allocations by printing or otherwise
+/// having side effects.
#[stable(feature = "global_alloc", since = "1.28.0")]
pub unsafe trait GlobalAlloc {
/// Allocate memory as described by the given `layout`.
/// this allocator,
///
/// * `layout` must be the same layout that was used
- /// to allocate that block of memory,
+ /// to allocate that block of memory.
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
/// and should be considered unusable (unless of course it was
/// transferred back to the caller again via the return value of
/// this method). The new memory block is allocated with `layout`, but
- /// with the `size` updated to `new_size`.
+ /// with the `size` updated to `new_size`. This new layout should be
+ /// used when deallocating the new memory block with `dealloc`. The range
+ /// `0..min(layout.size(), new_size)` of the new memory block is
+ /// guaranteed to have the same values as the original block.
///
/// If this method returns null, then ownership of the memory
/// block has not been transferred to this allocator, and the