Auto merge of #68529 - TimDiekmann:rename-alloc, r=Amanieu

Rename `Alloc` to `AllocRef`

The allocator-wg has decided to merge this change upstream in https://github.com/rust-lang/wg-allocators/issues/8#issuecomment-577122958.

This renames `Alloc` to `AllocRef` because types that implement `Alloc` are a reference, smart pointer, or ZSTs. It is not possible to have an allocator like `MyAlloc([u8; N])`, that owns the memory and also implements `Alloc`, since that would mean, that moving a `Vec<T, MyAlloc>` would need to correct the internal pointer, which is not possible as we don't have move constructors.

For further explanation please see https://github.com/rust-lang/wg-allocators/issues/8#issuecomment-489464843 and the comments after that one.

Additionally it clarifies the semantics of `Clone` on an allocator. In the case of `AllocRef`, it is clear that the cloned handle still points to the same allocator instance, and that you can free data allocated from one handle with another handle.

The initial proposal was to rename `Alloc` to `AllocHandle`, but `Ref` expresses the semantics better than `Handle`. Also, the only appearance of `Handle` in `std` are for windows specific resources, which might be confusing.

Blocked on https://github.com/rust-lang/miri/pull/1160
This commit is contained in:
bors 2020-01-28 08:44:20 +00:00
commit b181835a6b
16 changed files with 60 additions and 45 deletions

View File

@ -9,7 +9,7 @@ The tracking issue for this feature is [#32838]
Sometimes you want the memory for one collection to use a different
allocator than the memory for another collection. In this case,
replacing the global allocator is not a workable option. Instead,
you need to pass in an instance of an `Alloc` to each collection
you need to pass in an instance of an `AllocRef` to each collection
for which you want a custom allocator.
TBD

View File

@ -31,14 +31,14 @@
/// The global memory allocator.
///
/// This type implements the [`Alloc`] trait by forwarding calls
/// This type implements the [`AllocRef`] trait by forwarding calls
/// to the allocator registered with the `#[global_allocator]` attribute
/// if there is one, or the `std` crates default.
///
/// Note: while this type is unstable, the functionality it provides can be
/// accessed through the [free functions in `alloc`](index.html#functions).
///
/// [`Alloc`]: trait.Alloc.html
/// [`AllocRef`]: trait.AllocRef.html
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Copy, Clone, Default, Debug)]
pub struct Global;
@ -50,14 +50,14 @@
/// if there is one, or the `std` crates default.
///
/// This function is expected to be deprecated in favor of the `alloc` method
/// of the [`Global`] type when it and the [`Alloc`] trait become stable.
/// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
///
/// # Safety
///
/// See [`GlobalAlloc::alloc`].
///
/// [`Global`]: struct.Global.html
/// [`Alloc`]: trait.Alloc.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc
///
/// # Examples
@ -88,14 +88,14 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
/// if there is one, or the `std` crates default.
///
/// This function is expected to be deprecated in favor of the `dealloc` method
/// of the [`Global`] type when it and the [`Alloc`] trait become stable.
/// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
///
/// # Safety
///
/// See [`GlobalAlloc::dealloc`].
///
/// [`Global`]: struct.Global.html
/// [`Alloc`]: trait.Alloc.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc
#[stable(feature = "global_alloc", since = "1.28.0")]
#[inline]
@ -110,14 +110,14 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
/// if there is one, or the `std` crates default.
///
/// This function is expected to be deprecated in favor of the `realloc` method
/// of the [`Global`] type when it and the [`Alloc`] trait become stable.
/// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
///
/// # Safety
///
/// See [`GlobalAlloc::realloc`].
///
/// [`Global`]: struct.Global.html
/// [`Alloc`]: trait.Alloc.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc
#[stable(feature = "global_alloc", since = "1.28.0")]
#[inline]
@ -132,14 +132,14 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
/// if there is one, or the `std` crates default.
///
/// This function is expected to be deprecated in favor of the `alloc_zeroed` method
/// of the [`Global`] type when it and the [`Alloc`] trait become stable.
/// of the [`Global`] type when it and the [`AllocRef`] trait become stable.
///
/// # Safety
///
/// See [`GlobalAlloc::alloc_zeroed`].
///
/// [`Global`]: struct.Global.html
/// [`Alloc`]: trait.Alloc.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed
///
/// # Examples
@ -163,7 +163,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
}
#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl Alloc for Global {
unsafe impl AllocRef for Global {
#[inline]
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
NonNull::new(alloc(layout)).ok_or(AllocErr)

View File

@ -145,7 +145,7 @@
use core::slice;
use core::task::{Context, Poll};
use crate::alloc::{self, Alloc, Global};
use crate::alloc::{self, AllocRef, Global};
use crate::raw_vec::RawVec;
use crate::str::from_boxed_utf8_unchecked;
use crate::vec::Vec;

View File

@ -36,7 +36,7 @@
use core::ptr::{self, NonNull, Unique};
use core::slice;
use crate::alloc::{Alloc, Global, Layout};
use crate::alloc::{AllocRef, Global, Layout};
use crate::boxed::Box;
const B: usize = 6;

View File

@ -7,7 +7,7 @@
use core::ptr::{self, NonNull, Unique};
use core::slice;
use crate::alloc::{handle_alloc_error, Alloc, AllocErr, Global, Layout};
use crate::alloc::{handle_alloc_error, AllocErr, AllocRef, Global, Layout};
use crate::boxed::Box;
use crate::collections::TryReserveError::{self, *};
@ -42,13 +42,13 @@
/// field. This allows zero-sized types to not be special-cased by consumers of
/// this type.
#[allow(missing_debug_implementations)]
pub struct RawVec<T, A: Alloc = Global> {
pub struct RawVec<T, A: AllocRef = Global> {
ptr: Unique<T>,
cap: usize,
a: A,
}
impl<T, A: Alloc> RawVec<T, A> {
impl<T, A: AllocRef> RawVec<T, A> {
/// Like `new`, but parameterized over the choice of allocator for
/// the returned `RawVec`.
pub const fn new_in(a: A) -> Self {
@ -147,7 +147,7 @@ pub fn with_capacity_zeroed(capacity: usize) -> Self {
}
}
impl<T, A: Alloc> RawVec<T, A> {
impl<T, A: AllocRef> RawVec<T, A> {
/// Reconstitutes a `RawVec` from a pointer, capacity, and allocator.
///
/// # Undefined Behavior
@ -182,7 +182,7 @@ pub fn from_box(mut slice: Box<[T]>) -> Self {
}
}
impl<T, A: Alloc> RawVec<T, A> {
impl<T, A: AllocRef> RawVec<T, A> {
/// Gets a raw pointer to the start of the allocation. Note that this is
/// `Unique::empty()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
/// be careful.
@ -622,7 +622,7 @@ enum ReserveStrategy {
use ReserveStrategy::*;
impl<T, A: Alloc> RawVec<T, A> {
impl<T, A: AllocRef> RawVec<T, A> {
fn reserve_internal(
&mut self,
used_capacity: usize,
@ -700,7 +700,7 @@ pub unsafe fn into_box(self) -> Box<[T]> {
}
}
impl<T, A: Alloc> RawVec<T, A> {
impl<T, A: AllocRef> RawVec<T, A> {
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
pub unsafe fn dealloc_buffer(&mut self) {
let elem_size = mem::size_of::<T>();
@ -712,7 +712,7 @@ pub unsafe fn dealloc_buffer(&mut self) {
}
}
unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
fn drop(&mut self) {
unsafe {

View File

@ -19,7 +19,7 @@ fn allocator_param() {
struct BoundedAlloc {
fuel: usize,
}
unsafe impl Alloc for BoundedAlloc {
unsafe impl AllocRef for BoundedAlloc {
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
let size = layout.size();
if size > self.fuel {

View File

@ -252,7 +252,7 @@
use core::slice::{self, from_raw_parts_mut};
use core::usize;
use crate::alloc::{box_free, handle_alloc_error, Alloc, Global, Layout};
use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
use crate::string::String;
use crate::vec::Vec;

View File

@ -25,7 +25,7 @@
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
use core::{isize, usize};
use crate::alloc::{box_free, handle_alloc_error, Alloc, Global, Layout};
use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
use crate::boxed::Box;
use crate::rc::is_dangling;
use crate::string::String;

View File

@ -1,4 +1,4 @@
use std::alloc::{Alloc, Global, Layout, System};
use std::alloc::{AllocRef, Global, Layout, System};
/// Issue #45955 and #62251.
#[test]
@ -11,7 +11,7 @@ fn std_heap_overaligned_request() {
check_overalign_requests(Global)
}
fn check_overalign_requests<T: Alloc>(mut allocator: T) {
fn check_overalign_requests<T: AllocRef>(mut allocator: T) {
for &align in &[4, 8, 16, 32] {
// less than and bigger than `MIN_ALIGN`
for &size in &[align / 2, align - 1] {

View File

@ -31,7 +31,7 @@ const fn size_align<T>() -> (usize, usize) {
///
/// (Note however that layouts are *not* required to have positive
/// size, even though many allocators require that all memory
/// requests have positive size. A caller to the `Alloc::alloc`
/// requests have positive size. A caller to the `AllocRef::alloc`
/// method must either ensure that conditions like this are met, or
/// use specific allocators with looser requirements.)
#[stable(feature = "alloc_layout", since = "1.28.0")]
@ -364,8 +364,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// [`shrink_in_place`] were unable to reuse the given memory block for
/// a requested layout.
///
/// [`grow_in_place`]: ./trait.Alloc.html#method.grow_in_place
/// [`shrink_in_place`]: ./trait.Alloc.html#method.shrink_in_place
/// [`grow_in_place`]: ./trait.AllocRef.html#method.grow_in_place
/// [`shrink_in_place`]: ./trait.AllocRef.html#method.shrink_in_place
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct CannotReallocInPlace;
@ -580,9 +580,14 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
}
}
/// An implementation of `Alloc` can allocate, reallocate, and
/// An implementation of `AllocRef` can allocate, reallocate, and
/// deallocate arbitrary blocks of data described via `Layout`.
///
/// `AllocRef` is designed to be implemented on ZSTs, references, or
/// smart pointers because having an allocator like `MyAlloc([u8; N])`
/// cannot be moved, without updating the pointers to the allocated
/// memory.
///
/// Some of the methods require that a memory block be *currently
/// allocated* via an allocator. This means that:
///
@ -598,7 +603,7 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
/// passed to a reallocation method (see above) that returns `Ok`.
///
/// A note regarding zero-sized types and zero-sized layouts: many
/// methods in the `Alloc` trait state that allocation requests
/// methods in the `AllocRef` trait state that allocation requests
/// must be non-zero size, or else undefined behavior can result.
///
/// * However, some higher-level allocation methods (`alloc_one`,
@ -606,7 +611,7 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
/// optionally support them: it is left up to the implementor
/// whether to return `Err`, or to return `Ok` with some pointer.
///
/// * If an `Alloc` implementation chooses to return `Ok` in this
/// * If an `AllocRef` implementation chooses to return `Ok` in this
/// case (i.e., the pointer denotes a zero-sized inaccessible block)
/// then that returned pointer must be considered "currently
/// allocated". On such an allocator, *all* methods that take
@ -646,13 +651,16 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
///
/// # Safety
///
/// The `Alloc` trait is an `unsafe` trait for a number of reasons, and
/// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and
/// implementors must ensure that they adhere to these contracts:
///
/// * Pointers returned from allocation functions must point to valid memory and
/// retain their validity until at least the instance of `Alloc` is dropped
/// retain their validity until at least one instance of `AllocRef` is dropped
/// itself.
///
/// * Cloning or moving the allocator must not invalidate pointers returned
/// from this allocator. Cloning must return a reference to the same allocator.
///
/// * `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.
@ -660,7 +668,7 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
/// Note that this list may get tweaked over time as clarifications are made in
/// the future.
#[unstable(feature = "allocator_api", issue = "32838")]
pub unsafe trait Alloc {
pub unsafe trait AllocRef {
// (Note: some existing allocators have unspecified but well-defined
// behavior in response to a zero size allocation request ;
// e.g., in C, `malloc` of 0 will either return a null pointer or a
@ -1042,7 +1050,7 @@ unsafe fn shrink_in_place(
/// must be considered "currently allocated" and must be
/// acceptable input to methods such as `realloc` or `dealloc`,
/// *even if* `T` is a zero-sized type. In other words, if your
/// `Alloc` implementation overrides this method in a manner
/// `AllocRef` implementation overrides this method in a manner
/// that can return a zero-sized `ptr`, then all reallocation and
/// deallocation methods need to be similarly overridden to accept
/// such values as input.
@ -1106,7 +1114,7 @@ unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
/// must be considered "currently allocated" and must be
/// acceptable input to methods such as `realloc` or `dealloc`,
/// *even if* `T` is a zero-sized type. In other words, if your
/// `Alloc` implementation overrides this method in a manner
/// `AllocRef` implementation overrides this method in a manner
/// that can return a zero-sized `ptr`, then all reallocation and
/// deallocation methods need to be similarly overridden to accept
/// such values as input.
@ -1219,3 +1227,10 @@ unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), A
}
}
}
// In order to rename `Alloc` to `AllocRef`, some submoduleshas to be updated as well. The CI fails
// if either of the submodules fails to compile. The submodules have their own CI depending on a
// specific Rust version, which don't have `AllocRef` yet. This alias is used to make the submodules
// compile and pass the CI.
#[unstable(feature = "allocator_api", issue = "32838")]
pub use self::AllocRef as Alloc;

View File

@ -133,9 +133,9 @@
#[derive(Debug, Default, Copy, Clone)]
pub struct System;
// The Alloc impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`.
// The AllocRef impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`.
#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl Alloc for System {
unsafe impl AllocRef for System {
#[inline]
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)

View File

@ -4,7 +4,7 @@
#![feature(allocator_api, nonnull)]
use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
use std::alloc::{AllocRef, Global, Layout, handle_alloc_error};
fn main() {
unsafe {

View File

@ -7,7 +7,7 @@
extern crate helper;
use std::alloc::{self, Global, Alloc, System, Layout};
use std::alloc::{self, Global, AllocRef, System, Layout};
use std::sync::atomic::{AtomicUsize, Ordering};
static HITS: AtomicUsize = AtomicUsize::new(0);

View File

@ -9,7 +9,7 @@
extern crate custom;
extern crate helper;
use std::alloc::{Global, Alloc, System, Layout};
use std::alloc::{Global, AllocRef, System, Layout};
use std::sync::atomic::{Ordering, AtomicUsize};
#[global_allocator]

View File

@ -6,7 +6,7 @@
#![feature(allocator_api)]
use std::alloc::{Global, Alloc, Layout, handle_alloc_error};
use std::alloc::{Global, AllocRef, Layout, handle_alloc_error};
use std::ptr::{self, NonNull};
fn main() {

View File

@ -6,7 +6,7 @@
#![feature(allocator_api)]
use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
use std::alloc::{AllocRef, Global, Layout, handle_alloc_error};
use std::ptr::NonNull;
struct arena(());