From f6ab74b8e7efed01c1045773b6693f23f6ebd93c Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 31 May 2018 15:57:43 +0900 Subject: Remove alloc::Opaque and use *mut u8 as pointer type for GlobalAlloc --- src/libstd/alloc.rs | 10 +++++----- src/libstd/collections/hash/table.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 3b1a3a439e7..ac7da5e9dba 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -74,7 +74,7 @@ pub extern fn rust_oom(layout: Layout) -> ! { #[doc(hidden)] #[allow(unused_attributes)] pub mod __default_lib_allocator { - use super::{System, Layout, GlobalAlloc, Opaque}; + use super::{System, Layout, GlobalAlloc}; // for symbol names src/librustc/middle/allocator.rs // for signatures src/librustc_allocator/lib.rs @@ -85,7 +85,7 @@ pub mod __default_lib_allocator { #[rustc_std_internal_symbol] pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 { let layout = Layout::from_size_align_unchecked(size, align); - System.alloc(layout) as *mut u8 + System.alloc(layout) } #[no_mangle] @@ -93,7 +93,7 @@ pub mod __default_lib_allocator { pub unsafe extern fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) { - System.dealloc(ptr as *mut Opaque, Layout::from_size_align_unchecked(size, align)) + System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) } #[no_mangle] @@ -103,13 +103,13 @@ pub mod __default_lib_allocator { align: usize, new_size: usize) -> *mut u8 { let old_layout = Layout::from_size_align_unchecked(old_size, align); - System.realloc(ptr as *mut Opaque, old_layout, new_size) as *mut u8 + System.realloc(ptr, old_layout, new_size) } #[no_mangle] #[rustc_std_internal_symbol] pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 { let layout = Layout::from_size_align_unchecked(size, align); - System.alloc_zeroed(layout) as *mut u8 + System.alloc_zeroed(layout) } } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index d997fb28d42..55f9f4f7cfe 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -1124,7 +1124,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { let (layout, _) = calculate_layout::(self.capacity()) .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }); unsafe { - Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).as_opaque(), layout); + Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).cast(), layout); // Remember how everything was allocated out of one buffer // during initialization? We only need one call to free here. } -- cgit 1.4.1-3-g733a5 From 3373204ac49ebdb7194020ea9c556ce87910f7b7 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 31 May 2018 16:10:01 +0900 Subject: Replace `impl GlobalAlloc for Global` with a set of free functions --- src/liballoc/alloc.rs | 48 ++++++++++++++++-------------- src/libstd/alloc.rs | 1 + src/test/run-pass/allocator/xcrate-use2.rs | 6 ++-- 3 files changed, 29 insertions(+), 26 deletions(-) (limited to 'src/libstd') diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 102910f4198..8c2dda77226 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -49,37 +49,39 @@ pub type Heap = Global; #[allow(non_upper_case_globals)] pub const Heap: Global = Global; -unsafe impl GlobalAlloc for Global { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - __rust_alloc(layout.size(), layout.align()) - } +#[unstable(feature = "allocator_api", issue = "32838")] +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + __rust_alloc(layout.size(), layout.align()) +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - __rust_dealloc(ptr, layout.size(), layout.align()) - } +#[unstable(feature = "allocator_api", issue = "32838")] +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + __rust_dealloc(ptr, layout.size(), layout.align()) +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - __rust_realloc(ptr, layout.size(), layout.align(), new_size) - } +#[unstable(feature = "allocator_api", issue = "32838")] +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + __rust_realloc(ptr, layout.size(), layout.align(), new_size) +} - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - __rust_alloc_zeroed(layout.size(), layout.align()) - } +#[unstable(feature = "allocator_api", issue = "32838")] +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + __rust_alloc_zeroed(layout.size(), layout.align()) } unsafe impl Alloc for Global { #[inline] unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr) + NonNull::new(alloc(layout)).ok_or(AllocErr) } #[inline] unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) + dealloc(ptr.as_ptr(), layout) } #[inline] @@ -89,12 +91,12 @@ unsafe impl Alloc for Global { new_size: usize) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) + NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) } #[inline] unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) + NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr) } } @@ -108,7 +110,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { align as *mut u8 } else { let layout = Layout::from_size_align_unchecked(size, align); - let ptr = Global.alloc(layout); + let ptr = alloc(layout); if !ptr.is_null() { ptr } else { @@ -126,7 +128,7 @@ pub(crate) unsafe fn box_free(ptr: Unique) { // We do not allocate for Box when T is ZST, so deallocation is also not necessary. if size != 0 { let layout = Layout::from_size_align_unchecked(size, align); - Global.dealloc(ptr as *mut u8, layout); + dealloc(ptr as *mut u8, layout); } } diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index ac7da5e9dba..3f31fa8e1dd 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -14,6 +14,7 @@ #[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap; #[doc(inline)] pub use alloc_crate::alloc::{Global, Layout, oom}; +#[doc(inline)] pub use alloc_crate::alloc::{alloc, alloc_zeroed, dealloc, realloc}; #[doc(inline)] pub use alloc_system::System; #[doc(inline)] pub use core::alloc::*; diff --git a/src/test/run-pass/allocator/xcrate-use2.rs b/src/test/run-pass/allocator/xcrate-use2.rs index b8e844522dc..fbde7e855c2 100644 --- a/src/test/run-pass/allocator/xcrate-use2.rs +++ b/src/test/run-pass/allocator/xcrate-use2.rs @@ -19,7 +19,7 @@ extern crate custom; extern crate custom_as_global; extern crate helper; -use std::alloc::{Global, Alloc, GlobalAlloc, System, Layout}; +use std::alloc::{alloc, dealloc, GlobalAlloc, System, Layout}; use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT}; static GLOBAL: custom::A = custom::A(ATOMIC_USIZE_INIT); @@ -30,10 +30,10 @@ fn main() { let layout = Layout::from_size_align(4, 2).unwrap(); // Global allocator routes to the `custom_as_global` global - let ptr = Global.alloc(layout.clone()); + let ptr = alloc(layout.clone()); helper::work_with(&ptr); assert_eq!(custom_as_global::get(), n + 1); - Global.dealloc(ptr, layout.clone()); + dealloc(ptr, layout.clone()); assert_eq!(custom_as_global::get(), n + 2); // Usage of the system allocator avoids all globals -- cgit 1.4.1-3-g733a5 From 8c30c5168694b8ee740dade3a0145eef8aba66c6 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 30 May 2018 20:46:59 +0200 Subject: Remove deprecated heap modules The heap.rs file was already unused. --- src/liballoc/heap.rs | 110 ------------------------------------------ src/liballoc/lib.rs | 8 --- src/libcore/lib.rs | 7 --- src/libstd/collections/mod.rs | 2 +- src/libstd/error.rs | 2 +- src/libstd/lib.rs | 7 --- 6 files changed, 2 insertions(+), 134 deletions(-) delete mode 100644 src/liballoc/heap.rs (limited to 'src/libstd') diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs deleted file mode 100644 index 5ea37ceeb2b..00000000000 --- a/src/liballoc/heap.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(deprecated)] - -pub use alloc::{Layout, AllocErr, CannotReallocInPlace}; -use core::alloc::Alloc as CoreAlloc; -use core::ptr::NonNull; - -#[doc(hidden)] -pub mod __core { - pub use core::*; -} - -#[derive(Debug)] -pub struct Excess(pub *mut u8, pub usize); - -/// Compatibility with older versions of #[global_allocator] during bootstrap -pub unsafe trait Alloc { - unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>; - unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout); - fn oom(&mut self, err: AllocErr) -> !; - fn usable_size(&self, layout: &Layout) -> (usize, usize); - unsafe fn realloc(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result<*mut u8, AllocErr>; - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>; - unsafe fn alloc_excess(&mut self, layout: Layout) -> Result; - unsafe fn realloc_excess(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result; - unsafe fn grow_in_place(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result<(), CannotReallocInPlace>; - unsafe fn shrink_in_place(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result<(), CannotReallocInPlace>; -} - -unsafe impl Alloc for T where T: CoreAlloc { - unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { - CoreAlloc::alloc(self, layout).map(|ptr| ptr.cast().as_ptr()) - } - - unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { - let ptr = NonNull::new_unchecked(ptr); - CoreAlloc::dealloc(self, ptr, layout) - } - - fn oom(&mut self, _: AllocErr) -> ! { - unsafe { ::core::intrinsics::abort() } - } - - fn usable_size(&self, layout: &Layout) -> (usize, usize) { - CoreAlloc::usable_size(self, layout) - } - - unsafe fn realloc(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result<*mut u8, AllocErr> { - let ptr = NonNull::new_unchecked(ptr); - CoreAlloc::realloc(self, ptr, layout, new_layout.size()).map(|ptr| ptr.cast().as_ptr()) - } - - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { - CoreAlloc::alloc_zeroed(self, layout).map(|ptr| ptr.cast().as_ptr()) - } - - unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { - CoreAlloc::alloc_excess(self, layout) - .map(|e| Excess(e.0 .cast().as_ptr(), e.1)) - } - - unsafe fn realloc_excess(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result { - let ptr = NonNull::new_unchecked(ptr); - CoreAlloc::realloc_excess(self, ptr, layout, new_layout.size()) - .map(|e| Excess(e.0 .cast().as_ptr(), e.1)) - } - - unsafe fn grow_in_place(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result<(), CannotReallocInPlace> { - let ptr = NonNull::new_unchecked(ptr); - CoreAlloc::grow_in_place(self, ptr, layout, new_layout.size()) - } - - unsafe fn shrink_in_place(&mut self, - ptr: *mut u8, - layout: Layout, - new_layout: Layout) -> Result<(), CannotReallocInPlace> { - let ptr = NonNull::new_unchecked(ptr); - CoreAlloc::shrink_in_place(self, ptr, layout, new_layout.size()) - } -} diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 242c7d2e70f..828461fe8d7 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -150,18 +150,10 @@ pub mod allocator { pub mod alloc; -#[unstable(feature = "allocator_api", issue = "32838")] -#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")] -/// Use the `alloc` module instead. -pub mod heap { - pub use alloc::*; -} - #[unstable(feature = "futures_api", reason = "futures in libcore are unstable", issue = "50547")] pub mod task; - // Primitive types using the heaps above // Need to conditionally define the mod from `boxed.rs` to avoid diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a2ee0033872..5ba77edee6e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -215,13 +215,6 @@ pub mod task; #[allow(missing_docs)] pub mod alloc; -#[unstable(feature = "allocator_api", issue = "32838")] -#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")] -/// Use the `alloc` module instead. -pub mod heap { - pub use alloc::*; -} - // note: does not need to be public mod iter_private; mod nonzero; diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index d8e79b97970..42113414183 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -438,7 +438,7 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub use heap::CollectionAllocErr; +pub use alloc::CollectionAllocErr; mod hash; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 817eea5eaf1..3160485375f 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -23,13 +23,13 @@ // coherence challenge (e.g., specialization, neg impls, etc) we can // reconsider what crate these items belong in. +use alloc::{AllocErr, LayoutErr, CannotReallocInPlace}; use any::TypeId; use borrow::Cow; use cell; use char; use core::array; use fmt::{self, Debug, Display}; -use heap::{AllocErr, LayoutErr, CannotReallocInPlace}; use mem::transmute; use num; use str; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 4bf52224ae6..3972763a051 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -499,13 +499,6 @@ pub mod process; pub mod sync; pub mod time; -#[unstable(feature = "allocator_api", issue = "32838")] -#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")] -/// Use the `alloc` module instead. -pub mod heap { - pub use alloc::*; -} - // Platform-abstraction modules #[macro_use] mod sys_common; -- cgit 1.4.1-3-g733a5 From 11f992c9584f05f56664627ac1ec42e4cd1f0e3e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 30 May 2018 21:15:40 +0200 Subject: Remove the deprecated Heap type/const --- src/liballoc/alloc.rs | 9 --------- src/libstd/alloc.rs | 1 - 2 files changed, 10 deletions(-) (limited to 'src/libstd') diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 8c2dda77226..710da9a475b 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -40,15 +40,6 @@ extern "Rust" { #[derive(Copy, Clone, Default, Debug)] pub struct Global; -#[unstable(feature = "allocator_api", issue = "32838")] -#[rustc_deprecated(since = "1.27.0", reason = "type renamed to `Global`")] -pub type Heap = Global; - -#[unstable(feature = "allocator_api", issue = "32838")] -#[rustc_deprecated(since = "1.27.0", reason = "type renamed to `Global`")] -#[allow(non_upper_case_globals)] -pub const Heap: Global = Global; - #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn alloc(layout: Layout) -> *mut u8 { diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 3f31fa8e1dd..9904634f1fa 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -12,7 +12,6 @@ #![unstable(issue = "32838", feature = "allocator_api")] -#[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap; #[doc(inline)] pub use alloc_crate::alloc::{Global, Layout, oom}; #[doc(inline)] pub use alloc_crate::alloc::{alloc, alloc_zeroed, dealloc, realloc}; #[doc(inline)] pub use alloc_system::System; -- cgit 1.4.1-3-g733a5 From e9fd063edb4f6783fbd91a82a0f61626dacf8dad Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 31 May 2018 18:23:42 +0200 Subject: Document memory allocation APIs Add some docs where they were missing, attempt to fix them where they were out of date. --- src/liballoc/alloc.rs | 65 +++++++++++++ src/liballoc_system/lib.rs | 1 + src/libcore/alloc.rs | 227 +++++++++++++++++++++++++++++++++++---------- src/libstd/alloc.rs | 2 +- 4 files changed, 245 insertions(+), 50 deletions(-) (limited to 'src/libstd') diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 710da9a475b..c9430a29e4c 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Memory allocation APIs + #![unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked \ slightly, especially to possibly take into account the \ @@ -37,27 +39,80 @@ extern "Rust" { fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; } +/// The global memory allocator. +/// +/// This type implements the [`Alloc`] trait by forwarding calls +/// to the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. #[derive(Copy, Clone, Default, Debug)] pub struct Global; +/// Allocate memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::alloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s 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. +/// +/// # Safety +/// +/// See [`GlobalAlloc::alloc`]. #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn alloc(layout: Layout) -> *mut u8 { __rust_alloc(layout.size(), layout.align()) } +/// Deallocate memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::dealloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s 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. +/// +/// # Safety +/// +/// See [`GlobalAlloc::dealloc`]. #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { __rust_dealloc(ptr, layout.size(), layout.align()) } +/// Reallocate memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::realloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s 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. +/// +/// # Safety +/// +/// See [`GlobalAlloc::realloc`]. #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } +/// Allocate zero-initialized memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s 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. +/// +/// # Safety +/// +/// See [`GlobalAlloc::alloc_zeroed`]. #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { @@ -123,6 +178,16 @@ pub(crate) unsafe fn box_free(ptr: Unique) { } } +/// Abort on memory allocation error or failure. +/// +/// Callers of memory allocation APIs wishing to abort computation +/// in response to an allocation error are encouraged to call this function, +/// rather than directly invoking `panic!` or similar. +/// +/// The default behavior of this function is to print a message to standard error +/// and abort the process. +/// It can be replaced with [`std::alloc::set_oom_hook`] +/// and [`std::alloc::take_oom_hook`]. #[rustc_allocator_nounwind] pub fn oom(layout: Layout) -> ! { #[allow(improper_ctypes)] diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 82fda8d639e..85bf43a5429 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -44,6 +44,7 @@ const MIN_ALIGN: usize = 16; use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout}; use core::ptr::NonNull; +/// The default memory allocator provided by the operating system. #[unstable(feature = "allocator_api", issue = "32838")] pub struct System; diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 2815ef6400d..8fcd8555cdc 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Memory allocation APIs + #![unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked \ slightly, especially to possibly take into account the \ @@ -315,8 +317,9 @@ impl Layout { } } -/// The parameters given to `Layout::from_size_align` do not satisfy -/// its documented constraints. +/// The parameters given to `Layout::from_size_align` +/// or some other `Layout` constructor +/// do not satisfy its documented constraints. #[derive(Clone, PartialEq, Eq, Debug)] pub struct LayoutErr { private: () @@ -329,8 +332,8 @@ impl fmt::Display for LayoutErr { } } -/// The `AllocErr` error specifies whether an allocation failure is -/// specifically due to resource exhaustion or if it is due to +/// The `AllocErr` error indicates an allocation failure +/// that may be due to resource exhaustion or to /// something wrong when combining the given input arguments with this /// allocator. #[derive(Clone, PartialEq, Eq, Debug)] @@ -346,6 +349,7 @@ impl fmt::Display for AllocErr { /// The `CannotReallocInPlace` error is used when `grow_in_place` or /// `shrink_in_place` were unable to reuse the given memory block for /// a requested layout. +// FIXME: should this be in libcore or liballoc? #[derive(Clone, PartialEq, Eq, Debug)] pub struct CannotReallocInPlace; @@ -363,6 +367,7 @@ impl fmt::Display for CannotReallocInPlace { } /// Augments `AllocErr` with a CapacityOverflow variant. +// FIXME: should this be in libcore or liballoc? #[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] pub enum CollectionAllocErr { @@ -389,27 +394,125 @@ impl From for CollectionAllocErr { } } -/// A memory allocator that can be registered to be the one backing `std::alloc::Global` +/// A memory allocator that can be registered as the standard library’s default /// though the `#[global_allocator]` attributes. +/// +/// Some of the methods require that a memory block be *currently +/// allocated* via an allocator. This means that: +/// +/// * the starting address for that memory block was previously +/// returned by a previous call to an allocation method +/// such as `alloc`, and +/// +/// * the memory block has not been subsequently deallocated, where +/// blocks are deallocated either by being passed to a deallocation +/// method such as `dealloc` or by being +/// passed to a reallocation method that returns a non-null pointer. +/// +/// +/// # Example +/// +/// ```no_run +/// use std::alloc::{GlobalAlloc, Layout, alloc}; +/// use std::ptr::null_mut; +/// +/// struct MyAllocator; +/// +/// unsafe impl GlobalAlloc for MyAllocator { +/// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() } +/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +/// } +/// +/// #[global_allocator] +/// static A: MyAllocator = MyAllocator; +/// +/// fn main() { +/// unsafe { +/// assert!(alloc(Layout::new::()).is_null()) +/// } +/// } +/// ``` +/// +/// # Unsafety +/// +/// The `GlobalAlloc` 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 `GlobalAlloc` is dropped +/// itself. +/// +/// * It's undefined behavior if global allocators unwind. This restriction may +/// be lifted in the future, but currently a panic from any of these +/// functions may lead to memory unsafety. +/// +/// * `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. pub unsafe trait GlobalAlloc { /// Allocate memory as described by the given `layout`. /// /// Returns a pointer to newly-allocated memory, - /// or NULL to indicate allocation failure. + /// or null to indicate allocation failure. /// /// # Safety /// - /// **FIXME:** what are the exact requirements? + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure that `layout` has non-zero size. + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g. guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// The allocated block of memory may or may not be initialized. + /// + /// # Errors + /// + /// Returning a null pointer indicates that either memory is exhausted + /// or `layout` does not meet allocator's size or alignment constraints. + /// + /// Implementations are encouraged to return null on memory + /// exhaustion rather than aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn alloc(&self, layout: Layout) -> *mut u8; /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`. /// /// # Safety /// - /// **FIXME:** what are the exact requirements? - /// In particular around layout *fit*. (See docs for the `Alloc` trait.) + /// 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 be the same layout that was used + /// to allocated that block of memory, unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); + /// Behaves like `alloc`, but also ensures that the contents + /// are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// However the allocated block of memory is guaranteed to be initialized. + /// + /// # Errors + /// + /// Returning a null pointer indicates that either memory is exhausted + /// or `layout` does not meet allocator's size or alignment constraints, + /// just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { let size = layout.size(); let ptr = self.alloc(layout); @@ -422,19 +525,51 @@ pub unsafe trait GlobalAlloc { /// Shink or grow a block of memory to the given `new_size`. /// The block is described by the given `ptr` pointer and `layout`. /// - /// Return a new pointer (which may or may not be the same as `ptr`), - /// or NULL to indicate reallocation failure. + /// If this returns a non-null pointer, then ownership of the memory block + /// referenced by `ptr` has been transferred to this alloctor. + /// The memory may or may not have been deallocated, + /// and should be considered unusable (unless of course it was + /// transferred back to the caller again via the return value of + /// this method). /// - /// If reallocation is successful, the old `ptr` pointer is considered - /// to have been deallocated. + /// If this method returns null, then ownership of the memory + /// block has not been transferred to this allocator, and the + /// contents of the memory block are unaltered. /// /// # Safety /// - /// `new_size`, when rounded up to the nearest multiple of `old_layout.align()`, - /// must not overflow (i.e. the rounded value must be less than `usize::MAX`). + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * `layout` must be the same layout that was used + /// to allocated that block of memory, + /// + /// * `new_size` must be greater than zero. + /// + /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, + /// must not overflow (i.e. the rounded value must be less than `usize::MAX`). + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g. guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// # Errors + /// + /// Returns null if the new layout does not meet the size + /// and alignment constraints of the allocator, or if reallocation + /// otherwise fails. + /// + /// Implementations are encouraged to return null on memory + /// exhaustion rather than panicking or aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) /// - /// **FIXME:** what are the exact requirements? - /// In particular around layout *fit*. (See docs for the `Alloc` trait.) + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); let new_ptr = self.alloc(new_layout); @@ -523,27 +658,21 @@ pub unsafe trait GlobalAlloc { /// retain their validity until at least the instance of `Alloc` is dropped /// itself. /// -/// * It's undefined behavior if global allocators unwind. This restriction may -/// be lifted in the future, but currently a panic from any of these -/// functions may lead to memory unsafety. Note that as of the time of this -/// writing allocators *not* intending to be global allocators can still panic -/// in their implementation without violating memory safety. -/// /// * `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. /// /// Note that this list may get tweaked over time as clarifications are made in -/// the future. Additionally global allocators may gain unique requirements for -/// how to safely implement one in the future as well. +/// the future. pub unsafe trait Alloc { - // (Note: existing allocators have unspecified but well-defined + // (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 // unique pointer, but will not have arbitrary undefined - // behavior. Rust should consider revising the alloc::heap crate - // to reflect this reality.) + // behavior. + // However in jemalloc for example, + // `mallocx(0)` is documented as undefined behavior.) /// Returns a pointer meeting the size and alignment guarantees of /// `layout`. @@ -579,8 +708,8 @@ pub unsafe trait Alloc { /// library that aborts on memory exhaustion.) /// /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// allocation error are encouraged to call the `oom` function, + /// rather than directly invoking `panic!` or similar. unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr>; /// Deallocate the memory referenced by `ptr`. @@ -686,9 +815,9 @@ pub unsafe trait Alloc { /// implement this trait atop an underlying native allocation /// library that aborts on memory exhaustion.) /// - /// Clients wishing to abort computation in response to an - /// reallocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn realloc(&mut self, ptr: NonNull, layout: Layout, @@ -731,8 +860,8 @@ pub unsafe trait Alloc { /// constraints, just as in `alloc`. /// /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// allocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { let size = layout.size(); let p = self.alloc(layout); @@ -757,8 +886,8 @@ pub unsafe trait Alloc { /// constraints, just as in `alloc`. /// /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// allocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { let usable_size = self.usable_size(&layout); self.alloc(layout).map(|p| Excess(p, usable_size.1)) @@ -778,9 +907,9 @@ pub unsafe trait Alloc { /// `layout` does not meet allocator's size or alignment /// constraints, just as in `realloc`. /// - /// Clients wishing to abort computation in response to an - /// reallocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn realloc_excess(&mut self, ptr: NonNull, layout: Layout, @@ -823,7 +952,7 @@ pub unsafe trait Alloc { /// could fit `layout`. /// /// Note that one cannot pass `CannotReallocInPlace` to the `oom` - /// method; clients are expected either to be able to recover from + /// function; clients are expected either to be able to recover from /// `grow_in_place` failures without aborting, or to fall back on /// another reallocation method before resorting to an abort. unsafe fn grow_in_place(&mut self, @@ -878,7 +1007,7 @@ pub unsafe trait Alloc { /// could fit `layout`. /// /// Note that one cannot pass `CannotReallocInPlace` to the `oom` - /// method; clients are expected either to be able to recover from + /// function; clients are expected either to be able to recover from /// `shrink_in_place` failures without aborting, or to fall back /// on another reallocation method before resorting to an abort. unsafe fn shrink_in_place(&mut self, @@ -926,8 +1055,8 @@ pub unsafe trait Alloc { /// will *not* yield undefined behavior. /// /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// allocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. fn alloc_one(&mut self) -> Result, AllocErr> where Self: Sized { @@ -993,8 +1122,8 @@ pub unsafe trait Alloc { /// Always returns `Err` on arithmetic overflow. /// /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// allocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. fn alloc_array(&mut self, n: usize) -> Result, AllocErr> where Self: Sized { @@ -1037,9 +1166,9 @@ pub unsafe trait Alloc { /// /// Always returns `Err` on arithmetic overflow. /// - /// Clients wishing to abort computation in response to an - /// reallocation error are encouraged to call the allocator's `oom` - /// method, rather than directly invoking `panic!` or similar. + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`oom`] function, + /// rather than directly invoking `panic!` or similar. unsafe fn realloc_array(&mut self, ptr: NonNull, n_old: usize, diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 9904634f1fa..9126155a7c9 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! dox +//! Memory allocation APIs #![unstable(issue = "32838", feature = "allocator_api")] -- cgit 1.4.1-3-g733a5 From 951bc28fd09f5fed793021c6be1645e034394491 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 31 May 2018 18:36:51 +0200 Subject: Stablize the alloc module without changing stability of its contents. --- src/liballoc/alloc.rs | 11 ++++----- src/libcore/alloc.rs | 32 +++++++++++++++++++++----- src/libstd/alloc.rs | 19 ++++++++++----- src/test/compile-fail/lint-stability-fields.rs | 7 ++++++ 4 files changed, 51 insertions(+), 18 deletions(-) (limited to 'src/libstd') diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index c9430a29e4c..fc3d0151ec0 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -10,17 +10,13 @@ //! Memory allocation APIs -#![unstable(feature = "allocator_api", - reason = "the precise API and guarantees it provides may be tweaked \ - slightly, especially to possibly take into account the \ - types being stored to make room for a future \ - tracing garbage collector", - issue = "32838")] +#![stable(feature = "alloc_module", since = "1.28.0")] use core::intrinsics::{min_align_of_val, size_of_val}; use core::ptr::{NonNull, Unique}; use core::usize; +#[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] pub use core::alloc::*; @@ -44,6 +40,7 @@ extern "Rust" { /// This type implements the [`Alloc`] trait by forwarding calls /// to the allocator registered with the `#[global_allocator]` attribute /// if there is one, or the `std` crate’s default. +#[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] pub struct Global; @@ -119,6 +116,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { __rust_alloc_zeroed(layout.size(), layout.align()) } +#[unstable(feature = "allocator_api", issue = "32838")] unsafe impl Alloc for Global { #[inline] unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { @@ -188,6 +186,7 @@ pub(crate) unsafe fn box_free(ptr: Unique) { /// and abort the process. /// It can be replaced with [`std::alloc::set_oom_hook`] /// and [`std::alloc::take_oom_hook`]. +#[unstable(feature = "allocator_api", issue = "32838")] #[rustc_allocator_nounwind] pub fn oom(layout: Layout) -> ! { #[allow(improper_ctypes)] diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 8fcd8555cdc..ae9f77d35cf 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -10,12 +10,7 @@ //! Memory allocation APIs -#![unstable(feature = "allocator_api", - reason = "the precise API and guarantees it provides may be tweaked \ - slightly, especially to possibly take into account the \ - types being stored to make room for a future \ - tracing garbage collector", - issue = "32838")] +#![stable(feature = "alloc_module", since = "1.28.0")] use cmp; use fmt; @@ -24,11 +19,13 @@ use usize; use ptr::{self, NonNull}; use num::NonZeroUsize; +#[unstable(feature = "allocator_api", issue = "32838")] #[cfg(stage0)] pub type Opaque = u8; /// Represents the combination of a starting address and /// a total capacity of the returned block. +#[unstable(feature = "allocator_api", issue = "32838")] #[derive(Debug)] pub struct Excess(pub NonNull, pub usize); @@ -49,6 +46,7 @@ fn size_align() -> (usize, usize) { /// requests have positive size. A caller to the `Alloc::alloc` /// method must either ensure that conditions like this are met, or /// use specific allocators with looser requirements.) +#[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Layout { // size of the requested block of memory, measured in bytes. @@ -74,6 +72,7 @@ impl Layout { /// * `size`, when rounded up to the nearest multiple of `align`, /// must not overflow (i.e. the rounded value must be less than /// `usize::MAX`). + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn from_size_align(size: usize, align: usize) -> Result { if !align.is_power_of_two() { @@ -109,20 +108,24 @@ impl Layout { /// /// This function is unsafe as it does not verify the preconditions from /// [`Layout::from_size_align`](#method.from_size_align). + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) } } /// The minimum size in bytes for a memory block of this layout. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn size(&self) -> usize { self.size_ } /// The minimum byte alignment for a memory block of this layout. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn align(&self) -> usize { self.align_.get() } /// Constructs a `Layout` suitable for holding a value of type `T`. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new() -> Self { let (size, align) = size_align::(); @@ -139,6 +142,7 @@ impl Layout { /// Produces layout describing a record that could be used to /// allocate backing structure for `T` (which could be a trait /// or other unsized type like a slice). + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn for_value(t: &T) -> Self { let (size, align) = (mem::size_of_val(t), mem::align_of_val(t)); @@ -166,6 +170,7 @@ impl Layout { /// Panics if the combination of `self.size()` and the given `align` /// violates the conditions listed in /// [`Layout::from_size_align`](#method.from_size_align). + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn align_to(&self, align: usize) -> Self { Layout::from_size_align(self.size(), cmp::max(self.align(), align)).unwrap() @@ -187,6 +192,7 @@ impl Layout { /// to be less than or equal to the alignment of the starting /// address for the whole allocated block of memory. One way to /// satisfy this constraint is to ensure `align <= self.align()`. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn padding_needed_for(&self, align: usize) -> usize { let len = self.size(); @@ -223,6 +229,7 @@ impl Layout { /// of each element in the array. /// /// On arithmetic overflow, returns `LayoutErr`. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> { let padded_size = self.size().checked_add(self.padding_needed_for(self.align())) @@ -248,6 +255,7 @@ impl Layout { /// (assuming that the record itself starts at offset 0). /// /// On arithmetic overflow, returns `LayoutErr`. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> { let new_align = cmp::max(self.align(), next.align()); @@ -274,6 +282,7 @@ impl Layout { /// aligned. /// /// On arithmetic overflow, returns `LayoutErr`. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn repeat_packed(&self, n: usize) -> Result { let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?; @@ -295,6 +304,7 @@ impl Layout { /// `extend`.) /// /// On arithmetic overflow, returns `LayoutErr`. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn extend_packed(&self, next: Self) -> Result<(Self, usize), LayoutErr> { let new_size = self.size().checked_add(next.size()) @@ -306,6 +316,7 @@ impl Layout { /// Creates a layout describing the record for a `[T; n]`. /// /// On arithmetic overflow, returns `LayoutErr`. + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn array(n: usize) -> Result { Layout::new::() @@ -320,12 +331,14 @@ impl Layout { /// The parameters given to `Layout::from_size_align` /// or some other `Layout` constructor /// do not satisfy its documented constraints. +#[unstable(feature = "allocator_api", issue = "32838")] #[derive(Clone, PartialEq, Eq, Debug)] pub struct LayoutErr { private: () } // (we need this for downstream impl of trait Error) +#[unstable(feature = "allocator_api", issue = "32838")] impl fmt::Display for LayoutErr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("invalid parameters to Layout::from_size_align") @@ -336,10 +349,12 @@ impl fmt::Display for LayoutErr { /// that may be due to resource exhaustion or to /// something wrong when combining the given input arguments with this /// allocator. +#[unstable(feature = "allocator_api", issue = "32838")] #[derive(Clone, PartialEq, Eq, Debug)] pub struct AllocErr; // (we need this for downstream impl of trait Error) +#[unstable(feature = "allocator_api", issue = "32838")] impl fmt::Display for AllocErr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("memory allocation failed") @@ -350,9 +365,11 @@ impl fmt::Display for AllocErr { /// `shrink_in_place` were unable to reuse the given memory block for /// a requested layout. // FIXME: should this be in libcore or liballoc? +#[unstable(feature = "allocator_api", issue = "32838")] #[derive(Clone, PartialEq, Eq, Debug)] pub struct CannotReallocInPlace; +#[unstable(feature = "allocator_api", issue = "32838")] impl CannotReallocInPlace { pub fn description(&self) -> &str { "cannot reallocate allocator's memory in place" @@ -360,6 +377,7 @@ impl CannotReallocInPlace { } // (we need this for downstream impl of trait Error) +#[unstable(feature = "allocator_api", issue = "32838")] impl fmt::Display for CannotReallocInPlace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) @@ -449,6 +467,7 @@ impl From for CollectionAllocErr { /// * `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. +#[unstable(feature = "allocator_api", issue = "32838")] pub unsafe trait GlobalAlloc { /// Allocate memory as described by the given `layout`. /// @@ -664,6 +683,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 Alloc { // (Note: some existing allocators have unspecified but well-defined diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 9126155a7c9..1a4869f87c9 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -10,17 +10,20 @@ //! Memory allocation APIs -#![unstable(issue = "32838", feature = "allocator_api")] - -#[doc(inline)] pub use alloc_crate::alloc::{Global, Layout, oom}; -#[doc(inline)] pub use alloc_crate::alloc::{alloc, alloc_zeroed, dealloc, realloc}; -#[doc(inline)] pub use alloc_system::System; -#[doc(inline)] pub use core::alloc::*; +#![stable(feature = "alloc_module", since = "1.28.0")] use core::sync::atomic::{AtomicPtr, Ordering}; use core::{mem, ptr}; use sys_common::util::dumb_print; +#[stable(feature = "alloc_module", since = "1.28.0")] +#[doc(inline)] +pub use alloc_crate::alloc::*; + +#[unstable(feature = "allocator_api", issue = "32838")] +#[doc(inline)] +pub use alloc_system::System; + static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// Registers a custom OOM hook, replacing any that was previously registered. @@ -34,6 +37,7 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// about the allocation that failed. /// /// The OOM hook is a global resource. +#[unstable(feature = "allocator_api", issue = "32838")] pub fn set_oom_hook(hook: fn(Layout)) { HOOK.store(hook as *mut (), Ordering::SeqCst); } @@ -43,6 +47,7 @@ pub fn set_oom_hook(hook: fn(Layout)) { /// *See also the function [`set_oom_hook`].* /// /// If no custom hook is registered, the default hook will be returned. +#[unstable(feature = "allocator_api", issue = "32838")] pub fn take_oom_hook() -> fn(Layout) { let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); if hook.is_null() { @@ -59,6 +64,7 @@ fn default_oom_hook(layout: Layout) { #[cfg(not(test))] #[doc(hidden)] #[lang = "oom"] +#[unstable(feature = "allocator_api", issue = "32838")] pub extern fn rust_oom(layout: Layout) -> ! { let hook = HOOK.load(Ordering::SeqCst); let hook: fn(Layout) = if hook.is_null() { @@ -73,6 +79,7 @@ pub extern fn rust_oom(layout: Layout) -> ! { #[cfg(not(test))] #[doc(hidden)] #[allow(unused_attributes)] +#[unstable(feature = "allocator_api", issue = "32838")] pub mod __default_lib_allocator { use super::{System, Layout, GlobalAlloc}; // for symbol names src/librustc/middle/allocator.rs diff --git a/src/test/compile-fail/lint-stability-fields.rs b/src/test/compile-fail/lint-stability-fields.rs index 1b605bdb893..b1b1a9a1fbf 100644 --- a/src/test/compile-fail/lint-stability-fields.rs +++ b/src/test/compile-fail/lint-stability-fields.rs @@ -18,6 +18,11 @@ mod cross_crate { extern crate lint_stability_fields; + mod reexport { + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::lint_stability_fields::*; + } + use self::lint_stability_fields::*; pub fn foo() { @@ -73,6 +78,8 @@ mod cross_crate { // the patterns are all fine: { .. } = x; + // Unstable items are still unstable even when used through a stable "pub use". + let x = reexport::Unstable2(1, 2, 3); //~ ERROR use of unstable let x = Unstable2(1, 2, 3); //~ ERROR use of unstable -- cgit 1.4.1-3-g733a5 From 75e17da87358751becc950b9319f5d4aa82744ce Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 31 May 2018 18:38:39 +0200 Subject: Mark as permanently-unstable some implementation details --- src/libcore/alloc.rs | 2 +- src/libstd/alloc.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd') diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index ae9f77d35cf..97ad55304be 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -19,7 +19,7 @@ use usize; use ptr::{self, NonNull}; use num::NonZeroUsize; -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "alloc_internals", issue = "0")] #[cfg(stage0)] pub type Opaque = u8; diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 1a4869f87c9..55325006e74 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -64,7 +64,7 @@ fn default_oom_hook(layout: Layout) { #[cfg(not(test))] #[doc(hidden)] #[lang = "oom"] -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "alloc_internals", issue = "0")] pub extern fn rust_oom(layout: Layout) -> ! { let hook = HOOK.load(Ordering::SeqCst); let hook: fn(Layout) = if hook.is_null() { @@ -79,7 +79,7 @@ pub extern fn rust_oom(layout: Layout) -> ! { #[cfg(not(test))] #[doc(hidden)] #[allow(unused_attributes)] -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "alloc_internals", issue = "0")] pub mod __default_lib_allocator { use super::{System, Layout, GlobalAlloc}; // for symbol names src/librustc/middle/allocator.rs -- cgit 1.4.1-3-g733a5 From 90d19728fc93157465c1a586dbd35c6dc4cf78c9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 31 May 2018 19:15:11 +0200 Subject: Move set_oom_hook and take_oom_hook to a dedicated tracking issue --- src/libstd/alloc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 55325006e74..fd829bfe753 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -37,7 +37,7 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// about the allocation that failed. /// /// The OOM hook is a global resource. -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "oom_hook", issue = "51245")] pub fn set_oom_hook(hook: fn(Layout)) { HOOK.store(hook as *mut (), Ordering::SeqCst); } @@ -47,7 +47,7 @@ pub fn set_oom_hook(hook: fn(Layout)) { /// *See also the function [`set_oom_hook`].* /// /// If no custom hook is registered, the default hook will be returned. -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "oom_hook", issue = "51245")] pub fn take_oom_hook() -> fn(Layout) { let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); if hook.is_null() { -- cgit 1.4.1-3-g733a5 From 8111717da1d5854495b001be49346985ac3f208d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 31 May 2018 19:16:24 +0200 Subject: Stabilize the `System` allocator --- src/liballoc_system/lib.rs | 8 ++++---- src/libstd/alloc.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/libstd') diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 85bf43a5429..a592868cbef 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -45,7 +45,7 @@ use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout}; use core::ptr::NonNull; /// The default memory allocator provided by the operating system. -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "alloc_system_type", since = "1.28.0")] pub struct System; #[unstable(feature = "allocator_api", issue = "32838")] @@ -107,7 +107,7 @@ mod platform { use System; use core::alloc::{GlobalAlloc, Layout}; - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { @@ -240,7 +240,7 @@ mod platform { ptr as *mut u8 } - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { @@ -304,7 +304,7 @@ mod platform { // No need for synchronization here as wasm is currently single-threaded static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT; - #[unstable(feature = "allocator_api", issue = "32838")] + #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index fd829bfe753..6cae8aaa3db 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -20,7 +20,7 @@ use sys_common::util::dumb_print; #[doc(inline)] pub use alloc_crate::alloc::*; -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "alloc_system_type", since = "1.28.0")] #[doc(inline)] pub use alloc_system::System; -- cgit 1.4.1-3-g733a5 From fd6e08a1e6bbccd00e70b23ac72dd9a9a633be30 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 31 May 2018 19:31:00 +0200 Subject: Remove some '#[feature]' attributes for stabilized features --- src/doc/unstable-book/src/library-features/alloc-system.md | 1 - src/liballoc_system/lib.rs | 1 - src/librustc_asan/lib.rs | 3 +-- src/librustc_lsan/lib.rs | 5 ++--- src/librustc_msan/lib.rs | 5 ++--- src/librustc_tsan/lib.rs | 3 +-- src/libstd/lib.rs | 1 - src/test/compile-fail/allocator/auxiliary/system-allocator.rs | 1 - src/test/compile-fail/allocator/auxiliary/system-allocator2.rs | 1 - src/test/compile-fail/allocator/function-allocator.rs | 1 - src/test/compile-fail/allocator/not-an-allocator.rs | 2 -- src/test/compile-fail/allocator/two-allocators.rs | 2 -- src/test/compile-fail/allocator/two-allocators2.rs | 2 -- src/test/compile-fail/allocator/two-allocators3.rs | 1 - src/test/run-make-fulldeps/std-core-cycle/foo.rs | 1 - src/test/run-pass-valgrind/issue-44800.rs | 5 +---- src/test/run-pass/allocator/auxiliary/custom-as-global.rs | 1 - src/test/run-pass/allocator/custom.rs | 2 +- src/test/run-pass/allocator/xcrate-use.rs | 2 +- src/test/run-pass/thin-lto-global-allocator.rs | 2 -- 20 files changed, 9 insertions(+), 33 deletions(-) (limited to 'src/libstd') diff --git a/src/doc/unstable-book/src/library-features/alloc-system.md b/src/doc/unstable-book/src/library-features/alloc-system.md index 9effab202ca..5663b354ac1 100644 --- a/src/doc/unstable-book/src/library-features/alloc-system.md +++ b/src/doc/unstable-book/src/library-features/alloc-system.md @@ -61,7 +61,6 @@ crate.io’s `jemallocator` crate provides equivalent functionality.) jemallocator = "0.1" ``` ```rust,ignore -#![feature(global_allocator)] #![crate_type = "dylib"] extern crate jemallocator; diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index a592868cbef..2b748c4702d 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -14,7 +14,6 @@ reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "32838")] -#![feature(global_allocator)] #![feature(allocator_api)] #![feature(core_intrinsics)] #![feature(staged_api)] diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs index 3429e3bda0f..a7aeed76309 100644 --- a/src/librustc_asan/lib.rs +++ b/src/librustc_asan/lib.rs @@ -10,8 +10,7 @@ #![sanitizer_runtime] #![feature(alloc_system)] -#![feature(allocator_api)] -#![feature(global_allocator)] +#![cfg_attr(stage0, feature(global_allocator))] #![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs index 81a09e7e21a..a7aeed76309 100644 --- a/src/librustc_lsan/lib.rs +++ b/src/librustc_lsan/lib.rs @@ -9,10 +9,9 @@ // except according to those terms. #![sanitizer_runtime] -#![feature(sanitizer_runtime)] #![feature(alloc_system)] -#![feature(allocator_api)] -#![feature(global_allocator)] +#![cfg_attr(stage0, feature(global_allocator))] +#![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] #![unstable(feature = "sanitizer_runtime_lib", diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs index 81a09e7e21a..a7aeed76309 100644 --- a/src/librustc_msan/lib.rs +++ b/src/librustc_msan/lib.rs @@ -9,10 +9,9 @@ // except according to those terms. #![sanitizer_runtime] -#![feature(sanitizer_runtime)] #![feature(alloc_system)] -#![feature(allocator_api)] -#![feature(global_allocator)] +#![cfg_attr(stage0, feature(global_allocator))] +#![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] #![unstable(feature = "sanitizer_runtime_lib", diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs index 3429e3bda0f..a7aeed76309 100644 --- a/src/librustc_tsan/lib.rs +++ b/src/librustc_tsan/lib.rs @@ -10,8 +10,7 @@ #![sanitizer_runtime] #![feature(alloc_system)] -#![feature(allocator_api)] -#![feature(global_allocator)] +#![cfg_attr(stage0, feature(global_allocator))] #![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3972763a051..fa3d39cb1d8 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -263,7 +263,6 @@ #![feature(fnbox)] #![feature(futures_api)] #![feature(hashmap_internals)] -#![feature(heap_api)] #![feature(int_error_internals)] #![feature(integer_atomics)] #![feature(into_cow)] diff --git a/src/test/compile-fail/allocator/auxiliary/system-allocator.rs b/src/test/compile-fail/allocator/auxiliary/system-allocator.rs index 37e64ba7ea1..e5650d5b7b0 100644 --- a/src/test/compile-fail/allocator/auxiliary/system-allocator.rs +++ b/src/test/compile-fail/allocator/auxiliary/system-allocator.rs @@ -10,7 +10,6 @@ // no-prefer-dynamic -#![feature(global_allocator, allocator_api)] #![crate_type = "rlib"] use std::alloc::System; diff --git a/src/test/compile-fail/allocator/auxiliary/system-allocator2.rs b/src/test/compile-fail/allocator/auxiliary/system-allocator2.rs index 37e64ba7ea1..e5650d5b7b0 100644 --- a/src/test/compile-fail/allocator/auxiliary/system-allocator2.rs +++ b/src/test/compile-fail/allocator/auxiliary/system-allocator2.rs @@ -10,7 +10,6 @@ // no-prefer-dynamic -#![feature(global_allocator, allocator_api)] #![crate_type = "rlib"] use std::alloc::System; diff --git a/src/test/compile-fail/allocator/function-allocator.rs b/src/test/compile-fail/allocator/function-allocator.rs index 50f82607b53..989c102b86e 100644 --- a/src/test/compile-fail/allocator/function-allocator.rs +++ b/src/test/compile-fail/allocator/function-allocator.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(global_allocator)] #[global_allocator] fn foo() {} //~ ERROR: allocators must be statics diff --git a/src/test/compile-fail/allocator/not-an-allocator.rs b/src/test/compile-fail/allocator/not-an-allocator.rs index 140cad22f34..6559335960a 100644 --- a/src/test/compile-fail/allocator/not-an-allocator.rs +++ b/src/test/compile-fail/allocator/not-an-allocator.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(global_allocator, heap_api)] - #[global_allocator] static A: usize = 0; //~^ the trait bound `usize: diff --git a/src/test/compile-fail/allocator/two-allocators.rs b/src/test/compile-fail/allocator/two-allocators.rs index 5aa6b5d6777..7a97a11df20 100644 --- a/src/test/compile-fail/allocator/two-allocators.rs +++ b/src/test/compile-fail/allocator/two-allocators.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(global_allocator, allocator_api)] - use std::alloc::System; #[global_allocator] diff --git a/src/test/compile-fail/allocator/two-allocators2.rs b/src/test/compile-fail/allocator/two-allocators2.rs index ec5d985a943..e747140dfe5 100644 --- a/src/test/compile-fail/allocator/two-allocators2.rs +++ b/src/test/compile-fail/allocator/two-allocators2.rs @@ -12,8 +12,6 @@ // no-prefer-dynamic // error-pattern: the #[global_allocator] in -#![feature(global_allocator, allocator_api)] - extern crate system_allocator; use std::alloc::System; diff --git a/src/test/compile-fail/allocator/two-allocators3.rs b/src/test/compile-fail/allocator/two-allocators3.rs index c310d94f6df..dd86b02bd20 100644 --- a/src/test/compile-fail/allocator/two-allocators3.rs +++ b/src/test/compile-fail/allocator/two-allocators3.rs @@ -13,7 +13,6 @@ // no-prefer-dynamic // error-pattern: the #[global_allocator] in -#![feature(global_allocator)] extern crate system_allocator; extern crate system_allocator2; diff --git a/src/test/run-make-fulldeps/std-core-cycle/foo.rs b/src/test/run-make-fulldeps/std-core-cycle/foo.rs index 04742bba3c8..46047fb835d 100644 --- a/src/test/run-make-fulldeps/std-core-cycle/foo.rs +++ b/src/test/run-make-fulldeps/std-core-cycle/foo.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(global_allocator)] #![crate_type = "cdylib"] extern crate bar; diff --git a/src/test/run-pass-valgrind/issue-44800.rs b/src/test/run-pass-valgrind/issue-44800.rs index cfde6f32f66..29cfae16929 100644 --- a/src/test/run-pass-valgrind/issue-44800.rs +++ b/src/test/run-pass-valgrind/issue-44800.rs @@ -8,11 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(global_allocator, alloc_system, allocator_api)] -extern crate alloc_system; - +use std::alloc::System; use std::collections::VecDeque; -use alloc_system::System; #[global_allocator] static ALLOCATOR: System = System; diff --git a/src/test/run-pass/allocator/auxiliary/custom-as-global.rs b/src/test/run-pass/allocator/auxiliary/custom-as-global.rs index 538f36faadf..a3f05a01c5a 100644 --- a/src/test/run-pass/allocator/auxiliary/custom-as-global.rs +++ b/src/test/run-pass/allocator/auxiliary/custom-as-global.rs @@ -10,7 +10,6 @@ // no-prefer-dynamic -#![feature(global_allocator)] #![crate_type = "rlib"] extern crate custom; diff --git a/src/test/run-pass/allocator/custom.rs b/src/test/run-pass/allocator/custom.rs index 5da13bd4cb9..3a7f8fa8620 100644 --- a/src/test/run-pass/allocator/custom.rs +++ b/src/test/run-pass/allocator/custom.rs @@ -11,7 +11,7 @@ // aux-build:helper.rs // no-prefer-dynamic -#![feature(global_allocator, heap_api, allocator_api)] +#![feature(allocator_api)] extern crate helper; diff --git a/src/test/run-pass/allocator/xcrate-use.rs b/src/test/run-pass/allocator/xcrate-use.rs index 78d604a7108..482e3b04aae 100644 --- a/src/test/run-pass/allocator/xcrate-use.rs +++ b/src/test/run-pass/allocator/xcrate-use.rs @@ -12,7 +12,7 @@ // aux-build:helper.rs // no-prefer-dynamic -#![feature(global_allocator, heap_api, allocator_api)] +#![feature(allocator_api)] extern crate custom; extern crate helper; diff --git a/src/test/run-pass/thin-lto-global-allocator.rs b/src/test/run-pass/thin-lto-global-allocator.rs index a0534ff6735..3a0e2fe01db 100644 --- a/src/test/run-pass/thin-lto-global-allocator.rs +++ b/src/test/run-pass/thin-lto-global-allocator.rs @@ -11,8 +11,6 @@ // compile-flags: -Z thinlto -C codegen-units=2 // min-llvm-version 4.0 -#![feature(allocator_api, global_allocator)] - #[global_allocator] static A: std::alloc::System = std::alloc::System; -- cgit 1.4.1-3-g733a5 From a24924f6834ea6e5bd813d006a12aef8e5dbd5e9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 31 May 2018 20:22:59 +0200 Subject: Move Unstable Book sections for #[global_allocator] and System to std::alloc docs --- .../src/language-features/global-allocator.md | 72 -------------------- .../src/library-features/alloc-system.md | 76 ---------------------- src/liballoc_system/lib.rs | 23 +++++++ src/libstd/alloc.rs | 62 ++++++++++++++++++ 4 files changed, 85 insertions(+), 148 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/global-allocator.md delete mode 100644 src/doc/unstable-book/src/library-features/alloc-system.md (limited to 'src/libstd') diff --git a/src/doc/unstable-book/src/language-features/global-allocator.md b/src/doc/unstable-book/src/language-features/global-allocator.md deleted file mode 100644 index 7dfdc487731..00000000000 --- a/src/doc/unstable-book/src/language-features/global-allocator.md +++ /dev/null @@ -1,72 +0,0 @@ -# `global_allocator` - -The tracking issue for this feature is: [#27389] - -[#27389]: https://github.com/rust-lang/rust/issues/27389 - ------------------------- - -Rust programs may need to change the allocator that they're running with from -time to time. This use case is distinct from an allocator-per-collection (e.g. a -`Vec` with a custom allocator) and instead is more related to changing the -global default allocator, e.g. what `Vec` uses by default. - -Currently Rust programs don't have a specified global allocator. The compiler -may link to a version of [jemalloc] on some platforms, but this is not -guaranteed. Libraries, however, like cdylibs and staticlibs are guaranteed -to use the "system allocator" which means something like `malloc` on Unixes and -`HeapAlloc` on Windows. - -[jemalloc]: https://github.com/jemalloc/jemalloc - -The `#[global_allocator]` attribute, however, allows configuring this choice. -You can use this to implement a completely custom global allocator to route all -default allocation requests to a custom object. Defined in [RFC 1974] usage -looks like: - -[RFC 1974]: https://github.com/rust-lang/rfcs/pull/1974 - -```rust -#![feature(global_allocator, allocator_api, heap_api)] - -use std::alloc::{GlobalAlloc, System, Layout}; -use std::ptr::NonNull; - -struct MyAllocator; - -unsafe impl GlobalAlloc for MyAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - System.alloc(layout) - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - System.dealloc(ptr, layout) - } -} - -#[global_allocator] -static GLOBAL: MyAllocator = MyAllocator; - -fn main() { - // This `Vec` will allocate memory through `GLOBAL` above - let mut v = Vec::new(); - v.push(1); -} -``` - -And that's it! The `#[global_allocator]` attribute is applied to a `static` -which implements the `Alloc` trait in the `std::alloc` module. Note, though, -that the implementation is defined for `&MyAllocator`, not just `MyAllocator`. -You may wish, however, to also provide `Alloc for MyAllocator` for other use -cases. - -A crate can only have one instance of `#[global_allocator]` and this instance -may be loaded through a dependency. For example `#[global_allocator]` above -could have been placed in one of the dependencies loaded through `extern crate`. - -Note that `Alloc` itself is an `unsafe` trait, with much documentation on the -trait itself about usage and for implementors. Extra care should be taken when -implementing a global allocator as well as the allocator may be called from many -portions of the standard library, such as the panicking routine. As a result it -is highly recommended to not panic during allocation and work in as many -situations with as few dependencies as possible as well. diff --git a/src/doc/unstable-book/src/library-features/alloc-system.md b/src/doc/unstable-book/src/library-features/alloc-system.md deleted file mode 100644 index 5663b354ac1..00000000000 --- a/src/doc/unstable-book/src/library-features/alloc-system.md +++ /dev/null @@ -1,76 +0,0 @@ -# `alloc_system` - -The tracking issue for this feature is: [#32838] - -[#32838]: https://github.com/rust-lang/rust/issues/32838 - -See also [`global_allocator`](language-features/global-allocator.html). - ------------------------- - -The compiler currently ships two default allocators: `alloc_system` and -`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators -are normal Rust crates and contain an implementation of the routines to -allocate and deallocate memory. The standard library is not compiled assuming -either one, and the compiler will decide which allocator is in use at -compile-time depending on the type of output artifact being produced. - -Binaries generated by the compiler will use `alloc_jemalloc` by default (where -available). In this situation the compiler "controls the world" in the sense of -it has power over the final link. Primarily this means that the allocator -decision can be left up the compiler. - -Dynamic and static libraries, however, will use `alloc_system` by default. Here -Rust is typically a 'guest' in another application or another world where it -cannot authoritatively decide what allocator is in use. As a result it resorts -back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing -memory. - -# Switching Allocators - -Although the compiler's default choices may work most of the time, it's often -necessary to tweak certain aspects. Overriding the compiler's decision about -which allocator is in use is done through the `#[global_allocator]` attribute: - -```rust,no_run -#![feature(alloc_system, global_allocator, allocator_api)] - -extern crate alloc_system; - -use alloc_system::System; - -#[global_allocator] -static A: System = System; - -fn main() { - let a = Box::new(4); // Allocates from the system allocator. - println!("{}", a); -} -``` - -In this example the binary generated will not link to jemalloc by default but -instead use the system allocator. Conversely to generate a dynamic library which -uses jemalloc by default one would write: - -(The `alloc_jemalloc` crate cannot be used to control the global allocator, -crate.io’s `jemallocator` crate provides equivalent functionality.) - -```toml -# Cargo.toml -[dependencies] -jemallocator = "0.1" -``` -```rust,ignore -#![crate_type = "dylib"] - -extern crate jemallocator; - -#[global_allocator] -static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; - -pub fn foo() { - let a = Box::new(4); // Allocates from jemalloc. - println!("{}", a); -} -# fn main() {} -``` diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 2b748c4702d..64348e05de7 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -44,6 +44,29 @@ use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout}; use core::ptr::NonNull; /// The default memory allocator provided by the operating system. +/// +/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows, +/// plus related functions. +/// +/// This type can be used in a `static` item +/// with the `#[global_allocator]` attribute +/// to force the global allocator to be the system’s one. +/// (The default is jemalloc for executables, on some platforms.) +/// +/// ```rust +/// use std::alloc::System; +/// +/// #[global_allocator] +/// static A: System = System; +/// +/// fn main() { +/// let a = Box::new(4); // Allocates from the system allocator. +/// println!("{}", a); +/// } +/// ``` +/// +/// It can also be used directly to allocate memory +/// independently of the standard library’s global allocator. #[stable(feature = "alloc_system_type", since = "1.28.0")] pub struct System; diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 6cae8aaa3db..ae74a71dd06 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -9,6 +9,68 @@ // except according to those terms. //! Memory allocation APIs +//! +//! In a given program, the standard library has one “global” memory allocator +//! that is used for example by `Box` and `Vec`. +//! +//! Currently the default global allocator is unspecified. +//! The compiler may link to a version of [jemalloc] on some platforms, +//! but this is not guaranteed. +//! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed +//! to use the [`System`] by default. +//! +//! [jemalloc]: https://github.com/jemalloc/jemalloc +//! [`System`]: struct.System.html +//! +//! # The `#[global_allocator]` attribute +//! +//! This attribute allows configuring the choice of global allocator. +//! You can use this to implement a completely custom global allocator +//! to route all default allocation requests to a custom object. +//! +//! ```rust +//! use std::alloc::{GlobalAlloc, System, Layout}; +//! +//! struct MyAllocator; +//! +//! unsafe impl GlobalAlloc for MyAllocator { +//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 { +//! System.alloc(layout) +//! } +//! +//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { +//! System.dealloc(ptr, layout) +//! } +//! } +//! +//! #[global_allocator] +//! static GLOBAL: MyAllocator = MyAllocator; +//! +//! fn main() { +//! // This `Vec` will allocate memory through `GLOBAL` above +//! let mut v = Vec::new(); +//! v.push(1); +//! } +//! ``` +//! +//! The attribute is used on a `static` item whose type implements the +//! [`GlobalAlloc`] trait. This type can be provided by an external library: +//! +//! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html +//! +//! ```rust,ignore (demonstrates crates.io usage) +//! extern crate jemallocator; +//! +//! use jemallacator::Jemalloc; +//! +//! #[global_allocator] +//! static GLOBAL: Jemalloc = Jemalloc; +//! +//! fn main() {} +//! ``` +//! +//! The `#[global_allocator]` can only be used once in a crate +//! or its recursive dependencies. #![stable(feature = "alloc_module", since = "1.28.0")] -- cgit 1.4.1-3-g733a5