Skip to content

Commit 9c24afd

Browse files
committed
Restrict Allocator impl to &'static A
Arbitrary &'_ Allocators cannot satisfy the safety requirement that memory blocks returned by an Allocator must remain valid until the instance and all of its clones are dropped. &'static Allocators can still satisfy this safety requirement because their lifetime ensures that they are never moved or dropped.
1 parent 502d6aa commit 9c24afd

File tree

5 files changed

+26
-25
lines changed

5 files changed

+26
-25
lines changed

library/core/src/alloc/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ pub unsafe trait Allocator {
351351
}
352352

353353
#[unstable(feature = "allocator_api", issue = "32838")]
354-
unsafe impl<A> Allocator for &A
354+
unsafe impl<A> Allocator for &'static A
355355
where
356356
A: Allocator + ?Sized,
357357
{

library/std/src/alloc.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ impl System {
189189
old_size => unsafe {
190190
let new_ptr = self.alloc_impl(new_layout, zeroed)?;
191191
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size);
192-
Allocator::deallocate(&self, ptr, old_layout);
192+
Allocator::deallocate(self, ptr, old_layout);
193193
Ok(new_ptr)
194194
},
195195
}
@@ -256,7 +256,7 @@ unsafe impl Allocator for System {
256256
match new_layout.size() {
257257
// SAFETY: conditions must be upheld by the caller
258258
0 => unsafe {
259-
Allocator::deallocate(&self, ptr, old_layout);
259+
Allocator::deallocate(self, ptr, old_layout);
260260
Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
261261
},
262262

@@ -276,9 +276,9 @@ unsafe impl Allocator for System {
276276
// `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
277277
// for `dealloc` must be upheld by the caller.
278278
new_size => unsafe {
279-
let new_ptr = Allocator::allocate(&self, new_layout)?;
279+
let new_ptr = Allocator::allocate(self, new_layout)?;
280280
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size);
281-
Allocator::deallocate(&self, ptr, old_layout);
281+
Allocator::deallocate(self, ptr, old_layout);
282282
Ok(new_ptr)
283283
},
284284
}

src/test/ui/box/leak-alloc.rs renamed to src/test/ui/box/alloc-static.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ unsafe impl Allocator for Alloc {
1919

2020
fn use_value(_: u32) {}
2121

22+
const GLOBAL_ALLOC: Alloc = Alloc {};
23+
2224
fn main() {
25+
let boxed_global = Box::new_in(10, &GLOBAL_ALLOC);
26+
2327
let alloc = Alloc {};
24-
let boxed = Box::new_in(10, alloc.by_ref());
25-
let theref = Box::leak(boxed);
26-
drop(alloc);
27-
//~^ ERROR cannot move out of `alloc` because it is borrowed
28-
use_value(*theref)
28+
let boxed = Box::new_in(10, &alloc);
29+
//~^ ERROR `alloc` does not live long enough
2930
}

src/test/ui/box/alloc-static.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0597]: `alloc` does not live long enough
2+
--> $DIR/alloc-static.rs:28:33
3+
|
4+
LL | let boxed = Box::new_in(10, &alloc);
5+
| ----------------^^^^^^-
6+
| | |
7+
| | borrowed value does not live long enough
8+
| argument requires that `alloc` is borrowed for `'static`
9+
LL |
10+
LL | }
11+
| - `alloc` dropped here while still borrowed
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0597`.

src/test/ui/box/leak-alloc.stderr

-15
This file was deleted.

0 commit comments

Comments
 (0)