From 33ee398fdaa849e096e4935dba7cf599b9f6b832 Mon Sep 17 00:00:00 2001
From: Kevin Reid <kpreid@switchb.org>
Date: Tue, 25 Feb 2025 13:02:48 -0800
Subject: [PATCH] More precisely document `Global::deallocate()`'s safety.

There is a subtlety which "other conditions must be upheld by the caller"
does not capture: `GlobalAlloc`/`alloc::dealloc()` require that the
provided layout will be *equal*, not just that it "fits", the layout
used to allocate. This is always true here due to how `allocate()`,
`grow()`, and `shrink()` are implemented (they never return a larger
allocation than requested), but that is a non-local property of the
implementation, so it should be documented explicitly.
---
 library/alloc/src/alloc.rs | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index e686a02f29b0c..3bfdc68dcdaf6 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -264,8 +264,14 @@ unsafe impl Allocator for Global {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
         if layout.size() != 0 {
-            // SAFETY: `layout` is non-zero in size,
-            // other conditions must be upheld by the caller
+            // SAFETY:
+            // * We have checked that `layout` is non-zero in size.
+            // * The caller is obligated to provide a layout that "fits", and in this case,
+            //   "fit" always means a layout that is equal to the original, because our
+            //   `allocate()`, `grow()`, and `shrink()` implementations never returns a larger
+            //   allocation than requested.
+            // * Other conditions must be upheld by the caller, as per `Allocator::deallocate()`'s
+            //   safety documentation.
             unsafe { dealloc(ptr.as_ptr(), layout) }
         }
     }