diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 9fb0de63e6fc5..90699410647df 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -163,15 +163,18 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { } #[unstable(feature = "allocator_api", issue = "32838")] -unsafe impl AllocRef for Global { +unsafe impl DeallocRef for Global { #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(alloc(layout)).ok_or(AllocErr) + unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + dealloc(ptr.as_ptr(), layout) } +} +#[unstable(feature = "allocator_api", issue = "32838")] +unsafe impl AllocRef for Global { #[inline] - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - dealloc(ptr.as_ptr(), layout) + unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + NonNull::new(alloc(layout)).ok_or(AllocErr) } #[inline] diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index abf926186e82c..93cf5dc48e16c 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -37,7 +37,7 @@ use core::mem::{self, MaybeUninit}; use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{AllocRef, Global, Layout}; +use crate::alloc::{DeallocRef, Global, Layout}; use crate::boxed::Box; const B: usize = 6; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index e1b549bed18a6..d341f07040ca5 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -7,7 +7,7 @@ use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{handle_alloc_error, AllocErr, AllocRef, Global, Layout}; +use crate::alloc::{handle_alloc_error, AllocErr, AllocRef, DeallocRef, Global, Layout}; use crate::boxed::Box; use crate::collections::TryReserveError::{self, *}; @@ -42,13 +42,13 @@ mod tests; /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. #[allow(missing_debug_implementations)] -pub struct RawVec { +pub struct RawVec { ptr: Unique, cap: usize, a: A, } -impl RawVec { +impl RawVec { /// Like `new`, but parameterized over the choice of allocator for /// the returned `RawVec`. pub const fn new_in(a: A) -> Self { @@ -57,7 +57,9 @@ impl RawVec { // `Unique::empty()` doubles as "unallocated" and "zero-sized allocation". RawVec { ptr: Unique::empty(), cap, a } } +} +impl RawVec { /// Like `with_capacity`, but parameterized over the choice of /// allocator for the returned `RawVec`. #[inline] @@ -147,7 +149,7 @@ impl RawVec { } } -impl RawVec { +impl RawVec { /// Reconstitutes a `RawVec` from a pointer, capacity, and allocator. /// /// # Undefined Behavior @@ -182,7 +184,7 @@ impl RawVec { } } -impl RawVec { +impl RawVec { /// 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. @@ -221,7 +223,9 @@ impl RawVec { } } } +} +impl RawVec { /// Doubles the size of the type's backing allocation. This is common enough /// to want to do that it's easiest to just have a dedicated method. Slightly /// more efficient logic can be provided for this than the general case. @@ -700,7 +704,7 @@ impl RawVec { } } -impl RawVec { +impl RawVec { /// 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::(); @@ -712,7 +716,7 @@ impl RawVec { } } -unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec { +unsafe impl<#[may_dangle] T, A: DeallocRef> Drop for RawVec { /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. fn drop(&mut self) { unsafe { diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index 63087501f0e27..8dc1efbf42db1 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -19,6 +19,11 @@ fn allocator_param() { struct BoundedAlloc { fuel: usize, } + unsafe impl DeallocRef for BoundedAlloc { + unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + Global.dealloc(ptr, layout) + } + } unsafe impl AllocRef for BoundedAlloc { unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { let size = layout.size(); @@ -33,9 +38,6 @@ fn allocator_param() { err @ Err(_) => err, } } - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - Global.dealloc(ptr, layout) - } } let a = BoundedAlloc { fuel: 500 }; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9dc5447397f09..4d9445237efd7 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -252,7 +252,7 @@ use core::ptr::{self, NonNull}; use core::slice::{self, from_raw_parts_mut}; use core::usize; -use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout}; +use crate::alloc::{box_free, handle_alloc_error, AllocRef, DeallocRef, Global, Layout}; use crate::string::String; use crate::vec::Vec; diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index fd285242d5be4..4a6b967b9683a 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -25,7 +25,7 @@ use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::{isize, usize}; -use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout}; +use crate::alloc::{box_free, handle_alloc_error, AllocRef, DeallocRef, Global, Layout}; use crate::boxed::Box; use crate::rc::is_dangling; use crate::string::String; diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 38df843d258d3..21cd946c44dd3 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -580,6 +580,26 @@ pub unsafe trait GlobalAlloc { } } +/// An implementation of `DeallocRef` can deallocate arbitrary blocks of +/// data described via `Layout`. +/// +/// Please see the documentation of [`AllocRef`][] for more information. +#[unstable(feature = "allocator_api", issue = "32838")] +pub unsafe trait DeallocRef { + /// Deallocate the memory referenced by `ptr`. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must denote a block of memory owned by this allocator, + /// * `layout` must *fit* that block of memory, + /// * the alignment of the `layout` must match the alignment used + /// to allocate that block of memory. + unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout); +} + /// An implementation of `AllocRef` can allocate, reallocate, and /// deallocate arbitrary blocks of data described via `Layout`. /// @@ -668,7 +688,7 @@ pub unsafe trait GlobalAlloc { /// 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 AllocRef { +pub unsafe trait AllocRef: DeallocRef { // (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 @@ -717,23 +737,6 @@ pub unsafe trait AllocRef { /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr>; - /// Deallocate the memory referenced by `ptr`. - /// - /// # Safety - /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure all of the following: - /// - /// * `ptr` must denote a block of memory currently allocated via - /// this allocator, - /// - /// * `layout` must *fit* that block of memory, - /// - /// * In addition to fitting the block of memory `layout`, the - /// alignment of the `layout` must match the alignment used - /// to allocate that block of memory. - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout); - // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS == // usable_size diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 8965c6860c4e9..0802e7f21f8a9 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -133,7 +133,15 @@ pub use alloc_crate::alloc::*; #[derive(Debug, Default, Copy, Clone)] pub struct System; -// The AllocRef impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`. +// The (De-)allocRef impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`. +#[unstable(feature = "allocator_api", issue = "32838")] +unsafe impl DeallocRef for System { + #[inline] + unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) + } +} + #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for System { #[inline] @@ -146,11 +154,6 @@ unsafe impl AllocRef for System { NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) } - #[inline] - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) - } - #[inline] unsafe fn realloc( &mut self, diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs index 0b1f6d5a96e56..b08dd49018433 100644 --- a/src/test/ui/allocator/custom.rs +++ b/src/test/ui/allocator/custom.rs @@ -7,7 +7,7 @@ extern crate helper; -use std::alloc::{self, Global, AllocRef, System, Layout}; +use std::alloc::{self, Global, AllocRef, DeallocRef, System, Layout}; use std::sync::atomic::{AtomicUsize, Ordering}; static HITS: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/ui/allocator/xcrate-use.rs b/src/test/ui/allocator/xcrate-use.rs index 37b28c195df5b..835bb8ddccca1 100644 --- a/src/test/ui/allocator/xcrate-use.rs +++ b/src/test/ui/allocator/xcrate-use.rs @@ -9,7 +9,7 @@ extern crate custom; extern crate helper; -use std::alloc::{Global, AllocRef, System, Layout}; +use std::alloc::{Global, AllocRef, DeallocRef, System, Layout}; use std::sync::atomic::{Ordering, AtomicUsize}; #[global_allocator] diff --git a/src/test/ui/realloc-16687.rs b/src/test/ui/realloc-16687.rs index 425aa83e70a85..f7ebdc860d3c8 100644 --- a/src/test/ui/realloc-16687.rs +++ b/src/test/ui/realloc-16687.rs @@ -6,7 +6,7 @@ #![feature(allocator_api)] -use std::alloc::{Global, AllocRef, Layout, handle_alloc_error}; +use std::alloc::{Global, AllocRef, DeallocRef, Layout, handle_alloc_error}; use std::ptr::{self, NonNull}; fn main() { diff --git a/src/test/ui/regions/regions-mock-codegen.rs b/src/test/ui/regions/regions-mock-codegen.rs index f50b1c8b17f28..d663a38655949 100644 --- a/src/test/ui/regions/regions-mock-codegen.rs +++ b/src/test/ui/regions/regions-mock-codegen.rs @@ -6,7 +6,7 @@ #![feature(allocator_api)] -use std::alloc::{AllocRef, Global, Layout, handle_alloc_error}; +use std::alloc::{AllocRef, DeallocRef, Global, Layout, handle_alloc_error}; use std::ptr::NonNull; struct arena(());