about summary refs log tree commit diff
path: root/library/core/src/alloc
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/alloc')
-rw-r--r--library/core/src/alloc/global.rs13
-rw-r--r--library/core/src/alloc/mod.rs12
2 files changed, 25 insertions, 0 deletions
diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs
index c198797e650..65406125a3d 100644
--- a/library/core/src/alloc/global.rs
+++ b/library/core/src/alloc/global.rs
@@ -53,6 +53,19 @@ use crate::ptr;
 /// * `Layout` queries and calculations in general must be correct. Callers of
 ///   this trait are allowed to rely on the contracts defined on each method,
 ///   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.
+///
+///   ```rust,ignore
+///   drop(Box::new(42));
+///   let number_of_heap_allocs = /* call private allocator API */;
+///   unsafe { std::intrinsics::assume(number_of_heap_allocs > 0); }
+///   ```
 #[stable(feature = "global_alloc", since = "1.28.0")]
 pub unsafe trait GlobalAlloc {
     /// Allocate memory as described by the given `layout`.
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index c61c19cc7d1..47d5ad9ad56 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -94,6 +94,18 @@ pub unsafe trait AllocRef {
     /// The returned block may have a larger size than specified by `layout.size()`, and may or may
     /// not have its contents initialized.
     ///
+    /// Note that you may not rely on this method actually getting called, even if there are calls
+    /// to it 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.
+    ///
+    /// ```rust,ignore
+    /// Global::dealloc(Global::alloc(some_layout));
+    /// let number_of_heap_allocs = /* call private allocator API */;
+    /// unsafe { std::intrinsics::assume(number_of_heap_allocs > 0); }
+    /// ```
+    ///
     /// # Errors
     ///
     /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet