Skip to content

Commit ecf76bf

Browse files
committed
alloc: stabilise Allocator
1 parent 54333ff commit ecf76bf

10 files changed

Lines changed: 83 additions & 35 deletions

File tree

library/alloc/src/alloc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ impl Global {
440440
}
441441
}
442442

443-
#[unstable(feature = "allocator_api", issue = "32838")]
443+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
444444
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
445445
unsafe impl const Allocator for Global {
446446
#[inline]

library/alloc/src/boxed.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -507,14 +507,12 @@ impl<T, A: Allocator> Box<T, A> {
507507
/// # Examples
508508
///
509509
/// ```
510-
/// #![feature(allocator_api)]
511-
///
512510
/// use std::alloc::System;
513511
///
514512
/// let five = Box::new_in(5, System);
515513
/// ```
516514
#[cfg(not(no_global_oom_handling))]
517-
#[unstable(feature = "allocator_api", issue = "32838")]
515+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
518516
#[must_use]
519517
#[inline]
520518
pub fn new_in(x: T, alloc: A) -> Self
@@ -801,7 +799,6 @@ impl<T: ?Sized + CloneToUninit> Box<T> {
801799
///
802800
/// ```
803801
/// #![feature(clone_from_ref)]
804-
/// #![feature(allocator_api)]
805802
///
806803
/// let hello: Box<str> = Box::try_clone_from_ref("hello")?;
807804
/// # Ok::<(), std::alloc::AllocError>(())
@@ -2432,7 +2429,7 @@ impl<E: Error> Error for Box<E> {
24322429
}
24332430
}
24342431

2435-
#[unstable(feature = "allocator_api", issue = "32838")]
2432+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
24362433
unsafe impl<T: ?Sized + Allocator, A: Allocator> Allocator for Box<T, A> {
24372434
#[inline]
24382435
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {

library/alloc/src/boxed/thin.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ impl<T> ThinBox<T> {
7878
/// # Examples
7979
///
8080
/// ```
81-
/// #![feature(allocator_api)]
8281
/// #![feature(thin_box)]
8382
/// use std::boxed::ThinBox;
8483
///

library/alloc/src/collections/binary_heap/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ impl<T, A: Allocator> BinaryHeap<T, A> {
553553
/// let heap : BinaryHeap<i32, System> = BinaryHeap::new_in(System);
554554
/// ```
555555
#[unstable(feature = "allocator_api", issue = "32838")]
556+
#[rustc_const_unstable(feature = "allocator_api", issue = "32838")]
556557
#[must_use]
557558
pub const fn new_in(alloc: A) -> BinaryHeap<T, A> {
558559
BinaryHeap { data: Vec::new_in(alloc) }

library/alloc/src/rc.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,6 @@ impl<T: ?Sized + CloneToUninit> Rc<T> {
13321332
///
13331333
/// ```
13341334
/// #![feature(clone_from_ref)]
1335-
/// #![feature(allocator_api)]
13361335
/// use std::rc::Rc;
13371336
///
13381337
/// let hello: Rc<str> = Rc::try_clone_from_ref("hello")?;
@@ -2973,7 +2972,7 @@ impl From<String> for Rc<str> {
29732972

29742973
#[cfg(not(no_global_oom_handling))]
29752974
#[stable(feature = "shared_from_slice", since = "1.21.0")]
2976-
impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Rc<T, A> {
2975+
impl<T: ?Sized> From<Box<T>> for Rc<T> {
29772976
/// Move a boxed object to a new, reference counted, allocation.
29782977
///
29792978
/// # Example
@@ -2985,7 +2984,7 @@ impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Rc<T, A> {
29852984
/// assert_eq!(1, *shared);
29862985
/// ```
29872986
#[inline]
2988-
fn from(v: Box<T, A>) -> Rc<T, A> {
2987+
fn from(v: Box<T>) -> Rc<T> {
29892988
Rc::from_box_in(v)
29902989
}
29912990
}
@@ -4549,7 +4548,7 @@ impl<T: ?Sized, A: Allocator> Drop for UniqueRcUninit<T, A> {
45494548
}
45504549
}
45514550

4552-
#[unstable(feature = "allocator_api", issue = "32838")]
4551+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
45534552
unsafe impl<T: ?Sized + Allocator, A: Allocator> Allocator for Rc<T, A> {
45544553
#[inline]
45554554
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {

library/alloc/src/sync.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,7 +1480,6 @@ impl<T: ?Sized + CloneToUninit> Arc<T> {
14801480
///
14811481
/// ```
14821482
/// #![feature(clone_from_ref)]
1483-
/// #![feature(allocator_api)]
14841483
/// use std::sync::Arc;
14851484
///
14861485
/// let hello: Arc<str> = Arc::try_clone_from_ref("hello")?;
@@ -4011,7 +4010,7 @@ impl From<String> for Arc<str> {
40114010

40124011
#[cfg(not(no_global_oom_handling))]
40134012
#[stable(feature = "shared_from_slice", since = "1.21.0")]
4014-
impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Arc<T, A> {
4013+
impl<T: ?Sized> From<Box<T>> for Arc<T> {
40154014
/// Move a boxed object to a new, reference-counted allocation.
40164015
///
40174016
/// # Example
@@ -4023,7 +4022,7 @@ impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Arc<T, A> {
40234022
/// assert_eq!("eggplant", &shared[..]);
40244023
/// ```
40254024
#[inline]
4026-
fn from(v: Box<T, A>) -> Arc<T, A> {
4025+
fn from(v: Box<T>) -> Arc<T> {
40274026
Arc::from_box_in(v)
40284027
}
40294028
}
@@ -4918,7 +4917,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc<T, A> {
49184917
}
49194918
}
49204919

4921-
#[unstable(feature = "allocator_api", issue = "32838")]
4920+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
49224921
unsafe impl<T: ?Sized + Allocator, A: Allocator> Allocator for Arc<T, A> {
49234922
#[inline]
49244923
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {

library/alloc/src/vec/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1065,7 +1065,8 @@ impl<T, A: Allocator> Vec<T, A> {
10651065
/// let vec: Vec<i32, System> = Vec::new_in(System);
10661066
/// ```
10671067
#[inline]
1068-
#[unstable(feature = "allocator_api", issue = "32838")]
1068+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
1069+
#[rustc_const_unstable(feature = "allocator_api", issue = "32838")]
10691070
pub const fn new_in(alloc: A) -> Self {
10701071
Vec { buf: RawVec::new_in(alloc), len: 0 }
10711072
}

library/core/src/alloc/global.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,33 @@ pub unsafe trait GlobalAlloc {
301301
new_ptr
302302
}
303303
}
304+
305+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
306+
unsafe impl<A: super::Allocator + ?Sized> GlobalAlloc for A {
307+
default unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
308+
self.allocate(layout).map_or(ptr::null_mut(), |p| p.as_mut_ptr())
309+
}
310+
311+
default unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
312+
// SAFETY: Guaranteed by caller.
313+
unsafe { self.deallocate(ptr::NonNull::new_unchecked(ptr), layout) }
314+
}
315+
316+
default unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
317+
self.allocate_zeroed(layout).map_or(ptr::null_mut(), |p| p.as_mut_ptr())
318+
}
319+
320+
default unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
321+
// SAFETY: Guaranteed by caller.
322+
unsafe {
323+
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
324+
let ptr = ptr::NonNull::new_unchecked(ptr);
325+
if layout.size() > new_size {
326+
self.shrink(ptr, layout, new_layout)
327+
} else {
328+
self.grow(ptr, layout, new_layout)
329+
}
330+
}
331+
.map_or(ptr::null_mut(), |p| p.as_mut_ptr())
332+
}
333+
}

library/core/src/alloc/mod.rs

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,15 @@ use crate::ptr::{self, NonNull};
2727
/// that may be due to resource exhaustion or to
2828
/// something wrong when combining the given input arguments with this
2929
/// allocator.
30-
#[unstable(feature = "allocator_api", issue = "32838")]
30+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
3131
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
3232
pub struct AllocError;
3333

34-
#[unstable(
35-
feature = "allocator_api",
36-
reason = "the precise API and guarantees it provides may be tweaked.",
37-
issue = "32838"
38-
)]
34+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
3935
impl Error for AllocError {}
4036

4137
// (we need this for downstream impl of trait Error)
42-
#[unstable(feature = "allocator_api", issue = "32838")]
38+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
4339
impl fmt::Display for AllocError {
4440
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4541
f.write_str("memory allocation failed")
@@ -100,15 +96,29 @@ impl fmt::Display for AllocError {
10096
/// A memory block which is [*currently allocated*] may be passed to
10197
/// any method of the allocator that accepts such an argument.
10298
///
99+
/// No [*currently allocated*] memory may be accessed by the allocator except
100+
/// through the pointer passed back in within `grow`, `shrink`, and `deallocate`
101+
/// until that memory has been deallocated.
102+
///
103+
/// Implementors of `Allocator` which are also [`PartialEq`] must ensure equality
104+
/// guarantees that memory allocated with one can be freed with the other.
105+
///
106+
/// Behaviour when unwinding out of any of the allocating or deallocating
107+
/// functions is undefined.
108+
///
103109
/// Additionally, any memory block returned by the allocator must
104110
/// satisfy the allocation invariants described in `core::ptr`.
105111
/// In particular, if a block has base address `p` and size `n`,
106112
/// then `p as usize + n <= usize::MAX` must hold.
107113
///
108114
/// This ensures that pointer arithmetic within the allocation
109115
/// (for example, `ptr.add(len)`) cannot overflow the address space.
116+
///
117+
/// Note that some of the stated safety requirements are still experimental and
118+
/// may be relaxed in the future.
119+
///
110120
/// [*currently allocated*]: #currently-allocated-memory
111-
#[unstable(feature = "allocator_api", issue = "32838")]
121+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
112122
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
113123
pub const unsafe trait Allocator {
114124
/// Attempts to allocate a block of memory.
@@ -129,14 +139,15 @@ pub const unsafe trait Allocator {
129139
/// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
130140
/// allocator's size or alignment constraints.
131141
///
132-
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
142+
/// Implementations are encouraged to return `Err` on memory exhaustion rather than
133143
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
134144
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
135145
///
136146
/// Clients wishing to abort computation in response to an allocation error are encouraged to
137147
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
138148
///
139149
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
150+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
140151
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
141152

142153
/// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized.
@@ -146,14 +157,15 @@ pub const unsafe trait Allocator {
146157
/// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
147158
/// allocator's size or alignment constraints.
148159
///
149-
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
160+
/// Implementations are encouraged to return `Err` on memory exhaustion rather than
150161
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
151162
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
152163
///
153164
/// Clients wishing to abort computation in response to an allocation error are encouraged to
154165
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
155166
///
156167
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
168+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
157169
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
158170
let ptr = self.allocate(layout)?;
159171
// SAFETY: `alloc` returns a valid memory block
@@ -165,11 +177,12 @@ pub const unsafe trait Allocator {
165177
///
166178
/// # Safety
167179
///
168-
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator, and
169-
/// * `layout` must [*fit*] that block of memory.
180+
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
181+
/// * `layout` must [*fit*] that block of memory, and
170182
///
171183
/// [*currently allocated*]: #currently-allocated-memory
172184
/// [*fit*]: #memory-fitting
185+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
173186
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
174187

175188
/// Attempts to extend the memory block.
@@ -190,7 +203,7 @@ pub const unsafe trait Allocator {
190203
///
191204
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
192205
/// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
193-
/// * `new_layout.size()` must be greater than or equal to `old_layout.size()`.
206+
/// * `new_layout.size()` must be greater than or equal to `old_layout.size()`
194207
///
195208
/// Note that `new_layout.align()` need not be the same as `old_layout.align()`.
196209
///
@@ -202,14 +215,15 @@ pub const unsafe trait Allocator {
202215
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
203216
/// constraints of the allocator, or if growing otherwise fails.
204217
///
205-
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
218+
/// Implementations are encouraged to return `Err` on memory exhaustion rather than
206219
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
207220
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
208221
///
209222
/// Clients wishing to abort computation in response to an allocation error are encouraged to
210223
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
211224
///
212225
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
226+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
213227
unsafe fn grow(
214228
&self,
215229
ptr: NonNull<u8>,
@@ -265,14 +279,15 @@ pub const unsafe trait Allocator {
265279
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
266280
/// constraints of the allocator, or if growing otherwise fails.
267281
///
268-
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
282+
/// Implementations are encouraged to return `Err` on memory exhaustion rather than
269283
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
270284
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
271285
///
272286
/// Clients wishing to abort computation in response to an allocation error are encouraged to
273287
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
274288
///
275289
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
290+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
276291
unsafe fn grow_zeroed(
277292
&self,
278293
ptr: NonNull<u8>,
@@ -329,14 +344,15 @@ pub const unsafe trait Allocator {
329344
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
330345
/// constraints of the allocator, or if shrinking otherwise fails.
331346
///
332-
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
347+
/// Implementations are encouraged to return `Err` on memory exhaustion rather than
333348
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
334349
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
335350
///
336351
/// Clients wishing to abort computation in response to an allocation error are encouraged to
337352
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
338353
///
339354
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
355+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
340356
unsafe fn shrink(
341357
&self,
342358
ptr: NonNull<u8>,
@@ -366,16 +382,22 @@ pub const unsafe trait Allocator {
366382
/// Creates a "by reference" adapter for this instance of `Allocator`.
367383
///
368384
/// The returned adapter also implements `Allocator` and will simply borrow this.
385+
#[unstable(feature = "allocator_api", issue = "32838")]
369386
#[inline(always)]
370387
fn by_ref(&self) -> &Self
371388
where
372389
Self: Sized,
373390
{
374391
self
375392
}
393+
394+
/// Dummy function. Used to make `Allocator` non-`dyn` compatible for now.
395+
#[doc(hidden)]
396+
#[unstable(feature = "allocator_api", issue = "32838")]
397+
fn dummy_no_dyn() {}
376398
}
377399

378-
#[unstable(feature = "allocator_api", issue = "32838")]
400+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
379401
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
380402
unsafe impl<A> const Allocator for &A
381403
where
@@ -431,7 +453,7 @@ where
431453
}
432454
}
433455

434-
#[unstable(feature = "allocator_api", issue = "32838")]
456+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
435457
unsafe impl<A> Allocator for &mut A
436458
where
437459
A: Allocator + ?Sized,

library/std/src/alloc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl System {
207207

208208
// The Allocator impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
209209
// which is in `std::sys::*::alloc`.
210-
#[unstable(feature = "allocator_api", issue = "32838")]
210+
#[stable(feature = "min_allocator", since = "CURRENT_RUSTC_VERSION")]
211211
unsafe impl Allocator for System {
212212
#[inline]
213213
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {

0 commit comments

Comments
 (0)