From 3ec0baa8bc2dfac6d850e78990777d22984c9460 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 5 May 2021 16:20:39 -0400 Subject: [PATCH 1/2] Remote test for alloc `extern_crate` feature. This functionality was removed in 45bf1ed1a1123122ded05ae2eedaf0f190e52726, but the test was left by mistake. --- .../alloc-extern-crates/Makefile | 5 ---- .../alloc-extern-crates/fakealloc.rs | 25 ------------------- 2 files changed, 30 deletions(-) delete mode 100644 src/test/run-make-fulldeps/alloc-extern-crates/Makefile delete mode 100644 src/test/run-make-fulldeps/alloc-extern-crates/fakealloc.rs diff --git a/src/test/run-make-fulldeps/alloc-extern-crates/Makefile b/src/test/run-make-fulldeps/alloc-extern-crates/Makefile deleted file mode 100644 index 63f345944536..000000000000 --- a/src/test/run-make-fulldeps/alloc-extern-crates/Makefile +++ /dev/null @@ -1,5 +0,0 @@ --include ../tools.mk - -all: - $(RUSTC) fakealloc.rs - $(RUSTC) --edition=2018 --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs) diff --git a/src/test/run-make-fulldeps/alloc-extern-crates/fakealloc.rs b/src/test/run-make-fulldeps/alloc-extern-crates/fakealloc.rs deleted file mode 100644 index d4612c325d5a..000000000000 --- a/src/test/run-make-fulldeps/alloc-extern-crates/fakealloc.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![crate_type = "rlib"] -#![no_std] - -#[inline] -pub unsafe fn allocate(_size: usize, _align: usize) -> *mut u8 { - core::ptr::null_mut() -} - -#[inline] -pub unsafe fn deallocate(_ptr: *mut u8, _old_size: usize, _align: usize) { } - -#[inline] -pub unsafe fn reallocate(_ptr: *mut u8, _old_size: usize, _size: usize, _align: usize) -> *mut u8 { - core::ptr::null_mut() -} - -#[inline] -pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize, - _align: usize) -> usize { old_size } - -#[inline] -pub fn usable_size(size: usize, _align: usize) -> usize { size } - -#[inline] -pub fn stats_print() { } From 19be438cda610232be5ca84e08c74925a481c465 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 16 Apr 2021 20:18:04 -0400 Subject: [PATCH 2/2] alloc: Add unstable Cfg feature `no-global_oom_handling` For certain sorts of systems, programming, it's deemed essential that all allocation failures be explicitly handled where they occur. For example, see Linus Torvald's opinion in [1]. Merely not calling global panic handlers, or always `try_reserving` first (for vectors), is not deemed good enough, because the mere presence of the global OOM handlers is burdens static analysis. One option for these projects to use rust would just be to skip `alloc`, rolling their own allocation abstractions. But this would, in my opinion be a real shame. `alloc` has a few `try_*` methods already, and we could easily have more. Features like custom allocator support also demonstrate and existing to support diverse use-cases with the same abstractions. A natural way to add such a feature flag would a Cargo feature, but there are currently uncertainties around how std library crate's Cargo features may or not be stable, so to avoid any risk of stabilizing by mistake we are going with a more low-level "raw cfg" token, which cannot be interacted with via Cargo alone. Note also that since there is no notion of "default cfg tokens" outside of Cargo features, we have to invert the condition from `global_oom_handling` to to `not(no_global_oom_handling)`. This breaks the monotonicity that would be important for a Cargo feature (i.e. turning on more features should never break compatibility), but it doesn't matter for raw cfg tokens which are not intended to be "constraint solved" by Cargo or anything else. To support this use-case we create a new feature, "global-oom-handling", on by default, and put the global OOM handler infra and everything else it that depends on it behind it. By default, nothing is changed, but users concerned about global handling can make sure it is disabled, and be confident that all OOM handling is local and explicit. For this first iteration, non-flat collections are outright disabled. `Vec` and `String` don't yet have `try_*` allocation methods, but are kept anyways since they can be oom-safely created "from parts", and we hope to add those `try_` methods in the future. [1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/ --- library/alloc/src/alloc.rs | 9 ++- library/alloc/src/borrow.rs | 9 ++- library/alloc/src/boxed.rs | 35 +++++++- library/alloc/src/collections/mod.rs | 11 +++ library/alloc/src/fmt.rs | 2 + library/alloc/src/lib.rs | 4 +- library/alloc/src/raw_vec.rs | 16 +++- library/alloc/src/rc.rs | 38 ++++++++- library/alloc/src/slice.rs | 32 +++++++- library/alloc/src/str.rs | 13 +++ library/alloc/src/string.rs | 80 +++++++++++++++++-- library/alloc/src/sync.rs | 38 ++++++++- library/alloc/src/vec/into_iter.rs | 2 + library/alloc/src/vec/mod.rs | 56 ++++++++++++- library/alloc/src/vec/partial_eq.rs | 4 + .../alloc-no-oom-handling/Makefile | 4 + 16 files changed, 326 insertions(+), 27 deletions(-) create mode 100644 src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index cb9daaea0001..a10a027ffda7 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -308,7 +308,7 @@ unsafe fn shrink( /// The allocator for unique pointers. // This function must not unwind. If it does, MIR codegen will fail. -#[cfg(not(test))] +#[cfg(all(not(no_global_oom_handling), not(test)))] #[lang = "exchange_malloc"] #[inline] unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { @@ -337,6 +337,7 @@ pub(crate) unsafe fn box_free(ptr: Unique, alloc: A) // # Allocation error handler +#[cfg(not(no_global_oom_handling))] extern "Rust" { // This is the magic symbol to call the global alloc error handler. rustc generates // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the @@ -358,7 +359,7 @@ pub(crate) unsafe fn box_free(ptr: Unique, alloc: A) /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html #[stable(feature = "global_alloc", since = "1.28.0")] -#[cfg(not(test))] +#[cfg(all(not(no_global_oom_handling), not(test)))] #[rustc_allocator_nounwind] #[cold] pub fn handle_alloc_error(layout: Layout) -> ! { @@ -368,10 +369,10 @@ pub fn handle_alloc_error(layout: Layout) -> ! { } // For alloc test `std::alloc::handle_alloc_error` can be used directly. -#[cfg(test)] +#[cfg(all(not(no_global_oom_handling), test))] pub use std::alloc::handle_alloc_error; -#[cfg(not(any(target_os = "hermit", test)))] +#[cfg(all(not(no_global_oom_handling), not(any(target_os = "hermit", test))))] #[doc(hidden)] #[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index bdb2d67347e4..9d61b3684b82 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -4,12 +4,15 @@ use core::cmp::Ordering; use core::hash::{Hash, Hasher}; -use core::ops::{Add, AddAssign, Deref}; +use core::ops::Deref; +#[cfg(not(no_global_oom_handling))] +use core::ops::{Add, AddAssign}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::borrow::{Borrow, BorrowMut}; use crate::fmt; +#[cfg(not(no_global_oom_handling))] use crate::string::String; use Cow::*; @@ -429,6 +432,7 @@ fn as_ref(&self) -> &T { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_add", since = "1.14.0")] impl<'a> Add<&'a str> for Cow<'a, str> { type Output = Cow<'a, str>; @@ -440,6 +444,7 @@ fn add(mut self, rhs: &'a str) -> Self::Output { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_add", since = "1.14.0")] impl<'a> Add> for Cow<'a, str> { type Output = Cow<'a, str>; @@ -451,6 +456,7 @@ fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_add", since = "1.14.0")] impl<'a> AddAssign<&'a str> for Cow<'a, str> { fn add_assign(&mut self, rhs: &'a str) { @@ -467,6 +473,7 @@ fn add_assign(&mut self, rhs: &'a str) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_add", since = "1.14.0")] impl<'a> AddAssign> for Cow<'a, str> { fn add_assign(&mut self, rhs: Cow<'a, str>) { diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 30a69bfe982f..eb91af8c61cb 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -139,7 +139,9 @@ use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -use core::iter::{FromIterator, FusedIterator, Iterator}; +#[cfg(not(no_global_oom_handling))] +use core::iter::FromIterator; +use core::iter::{FusedIterator, Iterator}; use core::marker::{Unpin, Unsize}; use core::mem; use core::ops::{ @@ -150,10 +152,16 @@ use core::stream::Stream; use core::task::{Context, Poll}; -use crate::alloc::{handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw}; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::{handle_alloc_error, WriteCloneIntoRaw}; +use crate::alloc::{AllocError, Allocator, Global, Layout}; +#[cfg(not(no_global_oom_handling))] use crate::borrow::Cow; +#[cfg(not(no_global_oom_handling))] use crate::raw_vec::RawVec; +#[cfg(not(no_global_oom_handling))] use crate::str::from_boxed_utf8_unchecked; +#[cfg(not(no_global_oom_handling))] use crate::vec::Vec; /// A pointer type for heap allocation. @@ -177,6 +185,7 @@ impl Box { /// ``` /// let five = Box::new(5); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline(always)] #[doc(alias = "alloc")] #[doc(alias = "malloc")] @@ -203,6 +212,7 @@ pub fn new(x: T) -> Self { /// /// assert_eq!(*five, 5) /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub fn new_uninit() -> Box> { @@ -227,6 +237,7 @@ pub fn new_uninit() -> Box> { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] #[inline] #[doc(alias = "calloc")] #[unstable(feature = "new_uninit", issue = "63291")] @@ -236,6 +247,7 @@ pub fn new_zeroed() -> Box> { /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn pin(x: T) -> Pin> { @@ -329,6 +341,7 @@ impl Box { /// /// let five = Box::new_in(5, System); /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_in(x: T, alloc: A) -> Self { @@ -385,6 +398,7 @@ pub fn try_new_in(x: T, alloc: A) -> Result { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] + #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); @@ -447,6 +461,7 @@ pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocE /// /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] + #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); @@ -490,6 +505,7 @@ pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocE /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] #[inline(always)] pub fn pin_in(x: T, alloc: A) -> Pin @@ -547,6 +563,7 @@ impl Box<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity(len).into_box(len) } @@ -570,6 +587,7 @@ pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } @@ -599,6 +617,7 @@ impl Box<[T], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { @@ -625,6 +644,7 @@ pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { @@ -1013,6 +1033,7 @@ fn default() -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Box<[T]> { fn default() -> Self { @@ -1020,6 +1041,7 @@ fn default() -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "default_box_extra", since = "1.17.0")] impl Default for Box { fn default() -> Self { @@ -1027,6 +1049,7 @@ fn default() -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Box { /// Returns a new box with a `clone()` of this box's contents. @@ -1076,6 +1099,7 @@ fn clone_from(&mut self, source: &Self) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box { fn clone(&self) -> Self { @@ -1182,6 +1206,7 @@ fn write_isize(&mut self, i: isize) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Box { /// Converts a generic type `T` into a `Box` @@ -1214,6 +1239,7 @@ fn from(boxed: Box) -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_slice", since = "1.17.0")] impl From<&[T]> for Box<[T]> { /// Converts a `&[T]` into a `Box<[T]>` @@ -1239,6 +1265,7 @@ fn from(slice: &[T]) -> Box<[T]> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_cow", since = "1.45.0")] impl From> for Box<[T]> { #[inline] @@ -1250,6 +1277,7 @@ fn from(cow: Cow<'_, [T]>) -> Box<[T]> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_slice", since = "1.17.0")] impl From<&str> for Box { /// Converts a `&str` into a `Box` @@ -1268,6 +1296,7 @@ fn from(s: &str) -> Box { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_cow", since = "1.45.0")] impl From> for Box { #[inline] @@ -1567,6 +1596,7 @@ impl, U: ?Sized, A: Allocator> CoerceUnsized> fo #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U: ?Sized> DispatchFromDyn> for Box {} +#[cfg(not(no_global_oom_handling))] #[stable(feature = "boxed_slice_from_iter", since = "1.32.0")] impl FromIterator for Box<[I]> { fn from_iter>(iter: T) -> Self { @@ -1574,6 +1604,7 @@ fn from_iter>(iter: T) -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box<[T], A> { fn clone(&self) -> Self { diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 8213e904fba2..b9b3d650ea20 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -2,11 +2,16 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(no_global_oom_handling))] pub mod binary_heap; +#[cfg(not(no_global_oom_handling))] mod btree; +#[cfg(not(no_global_oom_handling))] pub mod linked_list; +#[cfg(not(no_global_oom_handling))] pub mod vec_deque; +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub mod btree_map { //! A map based on a B-Tree. @@ -14,6 +19,7 @@ pub mod btree_map { pub use super::btree::map::*; } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub mod btree_set { //! A set based on a B-Tree. @@ -21,22 +27,27 @@ pub mod btree_set { pub use super::btree::set::*; } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use binary_heap::BinaryHeap; +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use btree_map::BTreeMap; +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use btree_set::BTreeSet; +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use linked_list::LinkedList; +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use vec_deque::VecDeque; diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 3ef55f06e519..fd5ee189fbf7 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -546,6 +546,7 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{LowerHex, Pointer, UpperHex}; +#[cfg(not(no_global_oom_handling))] use crate::string; /// The `format` function takes an [`Arguments`] struct and returns the resulting @@ -574,6 +575,7 @@ /// /// [`format_args!`]: core::format_args /// [`format!`]: crate::format +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn format(args: Arguments<'_>) -> string::String { let capacity = args.estimated_capacity(); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 15308a4469bf..66b1036f2ab0 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -87,7 +87,7 @@ #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] -#![feature(const_btree_new)] +#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))] #![cfg_attr(bootstrap, feature(const_fn))] #![cfg_attr(not(bootstrap), feature(const_fn_trait_bound))] #![feature(cow_is_borrowed)] @@ -183,7 +183,7 @@ mod boxed { pub mod string; #[cfg(target_has_atomic = "ptr")] pub mod sync; -#[cfg(target_has_atomic = "ptr")] +#[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))] pub mod task; #[cfg(test)] mod tests; diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index fe87a97bac12..2e2c9b76bd4b 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -9,13 +9,16 @@ use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{handle_alloc_error, Allocator, Global, Layout}; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::handle_alloc_error; +use crate::alloc::{Allocator, Global, Layout}; use crate::boxed::Box; use crate::collections::TryReserveError::{self, *}; #[cfg(test)] mod tests; +#[cfg(not(no_global_oom_handling))] enum AllocInit { /// The contents of the new memory are uninitialized. Uninitialized, @@ -82,12 +85,14 @@ pub const fn new() -> Self { /// # Aborts /// /// Aborts on OOM. + #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) } /// Like `with_capacity`, but guarantees the buffer is zeroed. + #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity_zeroed(capacity: usize) -> Self { Self::with_capacity_zeroed_in(capacity, Global) @@ -131,6 +136,7 @@ pub const fn new_in(alloc: A) -> Self { /// Like `with_capacity`, but parameterized over the choice of /// allocator for the returned `RawVec`. + #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { Self::allocate_in(capacity, AllocInit::Uninitialized, alloc) @@ -138,6 +144,7 @@ pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { /// Like `with_capacity_zeroed`, but parameterized over the choice /// of allocator for the returned `RawVec`. + #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { Self::allocate_in(capacity, AllocInit::Zeroed, alloc) @@ -177,6 +184,7 @@ pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit], A> { } } + #[cfg(not(no_global_oom_handling))] fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { if mem::size_of::() == 0 { Self::new_in(alloc) @@ -309,6 +317,7 @@ fn current_memory(&self) -> Option<(NonNull, Layout)> { /// # vector.push_all(&[1, 3, 5, 7, 9]); /// # } /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] pub fn reserve(&mut self, len: usize, additional: usize) { // Callers expect this function to be very cheap when there is already sufficient capacity. @@ -355,6 +364,7 @@ pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryRe /// # Aborts /// /// Aborts on OOM. + #[cfg(not(no_global_oom_handling))] pub fn reserve_exact(&mut self, len: usize, additional: usize) { handle_reserve(self.try_reserve_exact(len, additional)); } @@ -378,6 +388,7 @@ pub fn try_reserve_exact( /// # Aborts /// /// Aborts on OOM. + #[cfg(not(no_global_oom_handling))] pub fn shrink_to_fit(&mut self, amount: usize) { handle_reserve(self.shrink(amount)); } @@ -452,6 +463,7 @@ fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserve Ok(()) } + #[cfg(not(no_global_oom_handling))] fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> { assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity"); @@ -512,6 +524,7 @@ fn drop(&mut self) { } // Central function for reserve error handling. +#[cfg(not(no_global_oom_handling))] #[inline] fn handle_reserve(result: Result<(), TryReserveError>) { match result { @@ -542,6 +555,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { // One central function responsible for reporting capacity overflows. This'll // ensure that the code generation related to these panics is minimal as there's // only one location which panics rather than a bunch throughout the module. +#[cfg(not(no_global_oom_handling))] fn capacity_overflow() -> ! { panic!("capacity overflow"); } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index cb4af7c5cd15..964169a227f6 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -255,19 +255,27 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; +#[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{self, PhantomData, Unpin, Unsize}; -use core::mem::{self, align_of_val_raw, forget, size_of_val}; +#[cfg(not(no_global_oom_handling))] +use core::mem::size_of_val; +use core::mem::{self, align_of_val_raw, forget}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use core::pin::Pin; use core::ptr::{self, NonNull}; +#[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; -use crate::alloc::{ - box_free, handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw, -}; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::handle_alloc_error; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::{box_free, WriteCloneIntoRaw}; +use crate::alloc::{AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; +#[cfg(not(no_global_oom_handling))] use crate::string::String; +#[cfg(not(no_global_oom_handling))] use crate::vec::Vec; #[cfg(test)] @@ -434,6 +442,7 @@ pub fn new_cyclic(data_fn: impl FnOnce(&Weak) -> T) -> Rc { /// /// assert_eq!(*five, 5) /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Rc> { unsafe { @@ -465,6 +474,7 @@ pub fn new_uninit() -> Rc> { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed() -> Rc> { unsafe { @@ -637,6 +647,7 @@ impl Rc<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } @@ -662,6 +673,7 @@ pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { /// ``` /// /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { @@ -1122,6 +1134,7 @@ impl Rc { /// assert!(76 == *data); /// assert!(weak.upgrade().is_none()); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { @@ -1195,6 +1208,7 @@ impl Rc { /// /// The function `mem_to_rcbox` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcBox`. + #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_layout( value_layout: Layout, allocate: impl FnOnce(Layout) -> Result, AllocError>, @@ -1245,6 +1259,7 @@ unsafe fn try_allocate_for_layout( } /// Allocates an `RcBox` with sufficient space for an unsized inner value + #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { // Allocate for the `RcBox` using the given value. unsafe { @@ -1256,6 +1271,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { } } + #[cfg(not(no_global_oom_handling))] fn from_box(v: Box) -> Rc { unsafe { let (box_unique, alloc) = Box::into_unique(v); @@ -1281,6 +1297,7 @@ fn from_box(v: Box) -> Rc { impl Rc<[T]> { /// Allocates an `RcBox<[T]>` with the given length. + #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { unsafe { Self::allocate_for_layout( @@ -1294,6 +1311,7 @@ unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { /// Copy elements from slice into newly allocated Rc<\[T\]> /// /// Unsafe because the caller must either take ownership or bind `T: Copy` + #[cfg(not(no_global_oom_handling))] unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { unsafe { let ptr = Self::allocate_for_slice(v.len()); @@ -1305,6 +1323,7 @@ unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size. /// /// Behavior is undefined should the size be wrong. + #[cfg(not(no_global_oom_handling))] unsafe fn from_iter_exact(iter: impl iter::Iterator, len: usize) -> Rc<[T]> { // Panic guard while cloning T elements. // In the event of a panic, elements that have been written @@ -1356,6 +1375,7 @@ trait RcFromSlice { fn from_slice(slice: &[T]) -> Self; } +#[cfg(not(no_global_oom_handling))] impl RcFromSlice for Rc<[T]> { #[inline] default fn from_slice(v: &[T]) -> Self { @@ -1363,6 +1383,7 @@ impl RcFromSlice for Rc<[T]> { } } +#[cfg(not(no_global_oom_handling))] impl RcFromSlice for Rc<[T]> { #[inline] fn from_slice(v: &[T]) -> Self { @@ -1717,6 +1738,7 @@ fn from(t: T) -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&[T]> for Rc<[T]> { /// Allocate a reference-counted slice and fill it by cloning `v`'s items. @@ -1735,6 +1757,7 @@ fn from(v: &[T]) -> Rc<[T]> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&str> for Rc { /// Allocate a reference-counted string slice and copy `v` into it. @@ -1753,6 +1776,7 @@ fn from(v: &str) -> Rc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From for Rc { /// Allocate a reference-counted string slice and copy `v` into it. @@ -1771,6 +1795,7 @@ fn from(v: String) -> Rc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From> for Rc { /// Move a boxed object to a new, reference counted, allocation. @@ -1789,6 +1814,7 @@ fn from(v: Box) -> Rc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From> for Rc<[T]> { /// Allocate a reference-counted slice and move `v`'s items into it. @@ -1842,6 +1868,7 @@ fn try_from(boxed_slice: Rc<[T]>) -> Result { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_iter", since = "1.37.0")] impl iter::FromIterator for Rc<[T]> { /// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`. @@ -1888,16 +1915,19 @@ fn from_iter>(iter: I) -> Self { } /// Specialization trait used for collecting into `Rc<[T]>`. +#[cfg(not(no_global_oom_handling))] trait ToRcSlice: Iterator + Sized { fn to_rc_slice(self) -> Rc<[T]>; } +#[cfg(not(no_global_oom_handling))] impl> ToRcSlice for I { default fn to_rc_slice(self) -> Rc<[T]> { self.collect::>().into() } } +#[cfg(not(no_global_oom_handling))] impl> ToRcSlice for I { fn to_rc_slice(self) -> Rc<[T]> { // This is the case for a `TrustedLen` iterator. diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index f5d0e911b601..dcd648992049 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -83,11 +83,19 @@ #![cfg_attr(test, allow(unused_imports, dead_code))] use core::borrow::{Borrow, BorrowMut}; +#[cfg(not(no_global_oom_handling))] use core::cmp::Ordering::{self, Less}; -use core::mem::{self, size_of}; +#[cfg(not(no_global_oom_handling))] +use core::mem; +#[cfg(not(no_global_oom_handling))] +use core::mem::size_of; +#[cfg(not(no_global_oom_handling))] use core::ptr; -use crate::alloc::{Allocator, Global}; +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::Global; +#[cfg(not(no_global_oom_handling))] use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; @@ -158,17 +166,20 @@ pub fn into_vec(b: Box<[T], A>) -> Vec { } } + #[cfg(not(no_global_oom_handling))] #[inline] pub fn to_vec(s: &[T], alloc: A) -> Vec { T::to_vec(s, alloc) } + #[cfg(not(no_global_oom_handling))] pub trait ConvertVec { fn to_vec(s: &[Self], alloc: A) -> Vec where Self: Sized; } + #[cfg(not(no_global_oom_handling))] impl ConvertVec for T { #[inline] default fn to_vec(s: &[Self], alloc: A) -> Vec { @@ -205,6 +216,7 @@ fn drop(&mut self) { } } + #[cfg(not(no_global_oom_handling))] impl ConvertVec for T { #[inline] fn to_vec(s: &[Self], alloc: A) -> Vec { @@ -250,6 +262,7 @@ impl [T] { /// v.sort(); /// assert!(v == [-5, -3, 1, 2, 4]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort(&mut self) @@ -304,6 +317,7 @@ pub fn sort(&mut self) /// v.sort_by(|a, b| b.cmp(a)); /// assert!(v == [5, 4, 3, 2, 1]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort_by(&mut self, mut compare: F) @@ -344,6 +358,7 @@ pub fn sort_by(&mut self, mut compare: F) /// v.sort_by_key(|k| k.abs()); /// assert!(v == [1, 2, -3, 4, -5]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[inline] pub fn sort_by_key(&mut self, mut f: F) @@ -386,6 +401,7 @@ pub fn sort_by_key(&mut self, mut f: F) /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort + #[cfg(not(no_global_oom_handling))] #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")] #[inline] pub fn sort_by_cached_key(&mut self, f: F) @@ -443,6 +459,7 @@ macro_rules! sort_by_key { /// let x = s.to_vec(); /// // Here, `s` and `x` can be modified independently. /// ``` + #[cfg(not(no_global_oom_handling))] #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -466,6 +483,7 @@ pub fn to_vec(&self) -> Vec /// let x = s.to_vec_in(System); /// // Here, `s` and `x` can be modified independently. /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn to_vec_in(&self, alloc: A) -> Vec @@ -517,6 +535,7 @@ pub fn into_vec(self: Box) -> Vec { /// // this will panic at runtime /// b"0123456789abcdef".repeat(usize::MAX); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "repeat_generic_slice", since = "1.40.0")] pub fn repeat(&self, n: usize) -> Vec where @@ -642,6 +661,7 @@ impl [u8] { /// To uppercase the value in-place, use [`make_ascii_uppercase`]. /// /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase + #[cfg(not(no_global_oom_handling))] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> Vec { @@ -659,6 +679,7 @@ pub fn to_ascii_uppercase(&self) -> Vec { /// To lowercase the value in-place, use [`make_ascii_lowercase`]. /// /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase + #[cfg(not(no_global_oom_handling))] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> Vec { @@ -724,6 +745,7 @@ pub trait Join { fn join(slice: &Self, sep: Separator) -> Self::Output; } +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Concat for [V] { type Output = Vec; @@ -738,6 +760,7 @@ fn concat(slice: &Self) -> Vec { } } +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Join<&T> for [V] { type Output = Vec; @@ -760,6 +783,7 @@ fn join(slice: &Self, sep: &T) -> Vec { } } +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Join<&[T]> for [V] { type Output = Vec; @@ -801,6 +825,7 @@ fn borrow_mut(&mut self) -> &mut [T] { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for [T] { type Owned = Vec; @@ -835,6 +860,7 @@ fn clone_into(&self, target: &mut Vec) { /// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted. /// /// This is the integral subroutine of insertion sort. +#[cfg(not(no_global_oom_handling))] fn insert_head(v: &mut [T], is_less: &mut F) where F: FnMut(&T, &T) -> bool, @@ -906,6 +932,7 @@ fn drop(&mut self) { /// /// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough /// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type. +#[cfg(not(no_global_oom_handling))] unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) where F: FnMut(&T, &T) -> bool, @@ -1026,6 +1053,7 @@ fn drop(&mut self) { /// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len` /// /// The invariants ensure that the total running time is *O*(*n* \* log(*n*)) worst-case. +#[cfg(not(no_global_oom_handling))] fn merge_sort(v: &mut [T], mut is_less: F) where F: FnMut(&T, &T) -> bool, diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 879af7cf4dd4..57279e81a957 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -74,6 +74,7 @@ /// Note: `str` in `Concat` is not meaningful here. /// This type parameter of the trait only exists to enable another impl. +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Concat for [S] { type Output = String; @@ -83,6 +84,7 @@ fn concat(slice: &Self) -> String { } } +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Join<&str> for [S] { type Output = String; @@ -92,6 +94,7 @@ fn join(slice: &Self, sep: &str) -> String { } } +#[cfg(not(no_global_oom_handling))] macro_rules! specialize_for_lengths { ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {{ let mut target = $target; @@ -122,6 +125,7 @@ macro_rules! specialize_for_lengths { }} } +#[cfg(not(no_global_oom_handling))] macro_rules! copy_slice_and_advance { ($target:expr, $bytes:expr) => { let len = $bytes.len(); @@ -139,6 +143,7 @@ macro_rules! copy_slice_and_advance { // the bounds for String-join are S: Borrow and for Vec-join Borrow<[T]> // [T] and str both impl AsRef<[T]> for some T // => s.borrow().as_ref() and we always have slices +#[cfg(not(no_global_oom_handling))] fn join_generic_copy(slice: &[S], sep: &[T]) -> Vec where T: Copy, @@ -205,6 +210,7 @@ fn borrow_mut(&mut self) -> &mut str { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for str { type Owned = String; @@ -264,6 +270,7 @@ pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { /// let s = "this is old"; /// assert_eq!(s, s.replace("cookie monster", "little lamb")); /// ``` + #[cfg(not(no_global_oom_handling))] #[must_use = "this returns the replaced string as a new allocation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] @@ -303,6 +310,7 @@ pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { /// let s = "this is old"; /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); /// ``` + #[cfg(not(no_global_oom_handling))] #[must_use = "this returns the replaced string as a new allocation, \ without modifying the original"] #[stable(feature = "str_replacen", since = "1.16.0")] @@ -358,6 +366,7 @@ pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> /// /// assert_eq!(new_year, new_year.to_lowercase()); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_lowercase(&self) -> String { let mut s = String::with_capacity(self.len()); @@ -437,6 +446,7 @@ fn case_ignoreable_then_cased>(iter: I) -> bool { /// /// assert_eq!("TSCHÜSS", s.to_uppercase()); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_uppercase(&self) -> String { let mut s = String::with_capacity(self.len()); @@ -496,6 +506,7 @@ pub fn into_string(self: Box) -> String { /// // this will panic at runtime /// "0123456789abcdef".repeat(usize::MAX); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } @@ -522,6 +533,7 @@ pub fn repeat(&self, n: usize) -> String { /// /// [`make_ascii_uppercase`]: str::make_ascii_uppercase /// [`to_uppercase`]: #method.to_uppercase + #[cfg(not(no_global_oom_handling))] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> String { @@ -552,6 +564,7 @@ pub fn to_ascii_uppercase(&self) -> String { /// /// [`make_ascii_lowercase`]: str::make_ascii_lowercase /// [`to_lowercase`]: #method.to_lowercase + #[cfg(not(no_global_oom_handling))] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> String { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 4aeb3de65928..e62524524708 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -42,20 +42,33 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(no_global_oom_handling))] use core::char::{decode_utf16, REPLACEMENT_CHARACTER}; use core::fmt; use core::hash; -use core::iter::{FromIterator, FusedIterator}; +#[cfg(not(no_global_oom_handling))] +use core::iter::FromIterator; +use core::iter::FusedIterator; +#[cfg(not(no_global_oom_handling))] +use core::ops::Add; +#[cfg(not(no_global_oom_handling))] +use core::ops::AddAssign; +#[cfg(not(no_global_oom_handling))] use core::ops::Bound::{Excluded, Included, Unbounded}; -use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds}; +use core::ops::{self, Index, IndexMut, Range, RangeBounds}; use core::ptr; use core::slice; -use core::str::{lossy, pattern::Pattern}; +#[cfg(not(no_global_oom_handling))] +use core::str::lossy; +use core::str::pattern::Pattern; +#[cfg(not(no_global_oom_handling))] use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::collections::TryReserveError; -use crate::str::{self, from_boxed_utf8_unchecked, Chars, FromStr, Utf8Error}; +use crate::str::{self, Chars, Utf8Error}; +#[cfg(not(no_global_oom_handling))] +use crate::str::{from_boxed_utf8_unchecked, FromStr}; use crate::vec::Vec; /// A UTF-8–encoded, growable string. @@ -314,7 +327,8 @@ pub struct String { /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(not(no_global_oom_handling), derive(Clone))] +#[derive(Debug, PartialEq, Eq)] pub struct FromUtf8Error { bytes: Vec, error: Utf8Error, @@ -403,6 +417,7 @@ pub const fn new() -> String { /// // ...but this may make the string reallocate /// s.push('a'); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[doc(alias = "alloc")] #[doc(alias = "malloc")] @@ -535,6 +550,7 @@ pub fn from_utf8(vec: Vec) -> Result { /// /// assert_eq!("Hello �World", output); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); @@ -587,6 +603,7 @@ pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { /// 0xD800, 0x0069, 0x0063]; /// assert!(String::from_utf16(v).is_err()); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf16(v: &[u16]) -> Result { // This isn't done via collect::>() for performance reasons. @@ -626,6 +643,7 @@ pub fn from_utf16(v: &[u16]) -> Result { /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), /// String::from_utf16_lossy(v)); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf16_lossy(v: &[u16]) -> String { @@ -818,6 +836,7 @@ pub fn as_mut_str(&mut self) -> &mut str { /// /// assert_eq!("foobar", s); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn push_str(&mut self, string: &str) { @@ -885,6 +904,7 @@ pub fn capacity(&self) -> usize { /// // ... doesn't actually increase. /// assert_eq!(10, s.capacity()); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { @@ -932,6 +952,7 @@ pub fn reserve(&mut self, additional: usize) { /// // ... doesn't actually increase. /// assert_eq!(10, s.capacity()); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve_exact(&mut self, additional: usize) { @@ -1026,6 +1047,7 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE /// s.shrink_to_fit(); /// assert_eq!(3, s.capacity()); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn shrink_to_fit(&mut self) { @@ -1053,6 +1075,7 @@ pub fn shrink_to_fit(&mut self) { /// s.shrink_to(0); /// assert!(s.capacity() >= 3); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] pub fn shrink_to(&mut self, min_capacity: usize) { @@ -1074,6 +1097,7 @@ pub fn shrink_to(&mut self, min_capacity: usize) { /// /// assert_eq!("abc123", s); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, ch: char) { @@ -1222,6 +1246,7 @@ pub fn remove(&mut self, idx: usize) -> char { /// s.remove_matches("ana"); /// assert_eq!("bna", s); /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")] pub fn remove_matches<'a, P>(&'a mut self, pat: P) where @@ -1352,6 +1377,7 @@ fn drop(&mut self) { /// /// assert_eq!("foo", s); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, idx: usize, ch: char) { @@ -1364,6 +1390,7 @@ pub fn insert(&mut self, idx: usize, ch: char) { } } + #[cfg(not(no_global_oom_handling))] unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { let len = self.len(); let amt = bytes.len(); @@ -1397,6 +1424,7 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { /// /// assert_eq!("foobar", s); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "insert_str", since = "1.16.0")] pub fn insert_str(&mut self, idx: usize, string: &str) { @@ -1502,6 +1530,7 @@ pub fn is_empty(&self) -> bool { /// assert_eq!(world, "World!"); /// # } /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "string_split_off", since = "1.16.0")] #[must_use = "use `.truncate()` if you don't need the other half"] @@ -1608,6 +1637,7 @@ pub fn drain(&mut self, range: R) -> Drain<'_> /// s.replace_range(..beta_offset, "Α is capital alpha; "); /// assert_eq!(s, "Α is capital alpha; β is beta"); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "splice", since = "1.27.0")] pub fn replace_range(&mut self, range: R, replace_with: &str) where @@ -1654,6 +1684,7 @@ pub fn replace_range(&mut self, range: R, replace_with: &str) /// /// let b = s.into_boxed_str(); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_str", since = "1.4.0")] #[inline] pub fn into_boxed_str(self) -> Box { @@ -1748,6 +1779,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Clone for String { fn clone(&self) -> Self { @@ -1759,6 +1791,7 @@ fn clone_from(&mut self, source: &Self) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for String { fn from_iter>(iter: I) -> String { @@ -1768,6 +1801,7 @@ fn from_iter>(iter: I) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "string_from_iter_by_ref", since = "1.17.0")] impl<'a> FromIterator<&'a char> for String { fn from_iter>(iter: I) -> String { @@ -1777,6 +1811,7 @@ fn from_iter>(iter: I) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<'a> FromIterator<&'a str> for String { fn from_iter>(iter: I) -> String { @@ -1786,6 +1821,7 @@ fn from_iter>(iter: I) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "extend_string", since = "1.4.0")] impl FromIterator for String { fn from_iter>(iter: I) -> String { @@ -1804,6 +1840,7 @@ fn from_iter>(iter: I) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_str2", since = "1.45.0")] impl FromIterator> for String { fn from_iter>>(iter: I) -> String { @@ -1813,6 +1850,7 @@ fn from_iter>>(iter: I) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "herd_cows", since = "1.19.0")] impl<'a> FromIterator> for String { fn from_iter>>(iter: I) -> String { @@ -1832,6 +1870,7 @@ fn from_iter>>(iter: I) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Extend for String { fn extend>(&mut self, iter: I) { @@ -1852,6 +1891,7 @@ fn extend_reserve(&mut self, additional: usize) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a> Extend<&'a char> for String { fn extend>(&mut self, iter: I) { @@ -1869,6 +1909,7 @@ fn extend_reserve(&mut self, additional: usize) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Extend<&'a str> for String { fn extend>(&mut self, iter: I) { @@ -1881,6 +1922,7 @@ fn extend_one(&mut self, s: &'a str) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_str2", since = "1.45.0")] impl Extend> for String { fn extend>>(&mut self, iter: I) { @@ -1888,6 +1930,7 @@ fn extend>>(&mut self, iter: I) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "extend_string", since = "1.4.0")] impl Extend for String { fn extend>(&mut self, iter: I) { @@ -1900,6 +1943,7 @@ fn extend_one(&mut self, s: String) { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "herd_cows", since = "1.19.0")] impl<'a> Extend> for String { fn extend>>(&mut self, iter: I) { @@ -2001,8 +2045,11 @@ fn ne(&self, other: &$lhs) -> bool { impl_eq! { String, str } impl_eq! { String, &'a str } +#[cfg(not(no_global_oom_handling))] impl_eq! { Cow<'a, str>, str } +#[cfg(not(no_global_oom_handling))] impl_eq! { Cow<'a, str>, &'b str } +#[cfg(not(no_global_oom_handling))] impl_eq! { Cow<'a, str>, String } #[stable(feature = "rust1", since = "1.0.0")] @@ -2075,6 +2122,7 @@ fn hash(&self, hasher: &mut H) { /// let b = " world"; /// let c = a.to_string() + b; /// ``` +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Add<&str> for String { type Output = String; @@ -2089,6 +2137,7 @@ fn add(mut self, other: &str) -> String { /// Implements the `+=` operator for appending to a `String`. /// /// This has the same behavior as the [`push_str`][String::push_str] method. +#[cfg(not(no_global_oom_handling))] #[stable(feature = "stringaddassign", since = "1.12.0")] impl AddAssign<&str> for String { #[inline] @@ -2221,6 +2270,7 @@ fn deref_mut(&mut self) -> &mut str { #[stable(feature = "str_parse_error", since = "1.5.0")] pub type ParseError = core::convert::Infallible; +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl FromStr for String { type Err = core::convert::Infallible; @@ -2264,6 +2314,7 @@ pub trait ToString { /// if the `Display` implementation returns an error. /// This indicates an incorrect `Display` implementation /// since `fmt::Write for String` never returns an error itself. +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl ToString for T { // A common guideline is to not inline generic functions. However, @@ -2280,6 +2331,7 @@ impl ToString for T { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "char_to_string_specialization", since = "1.46.0")] impl ToString for char { #[inline] @@ -2288,6 +2340,7 @@ fn to_string(&self) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "u8_to_string_specialization", since = "1.54.0")] impl ToString for u8 { #[inline] @@ -2307,6 +2360,7 @@ fn to_string(&self) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "i8_to_string_specialization", since = "1.54.0")] impl ToString for i8 { #[inline] @@ -2329,6 +2383,7 @@ fn to_string(&self) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "str_to_string_specialization", since = "1.9.0")] impl ToString for str { #[inline] @@ -2337,6 +2392,7 @@ fn to_string(&self) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")] impl ToString for Cow<'_, str> { #[inline] @@ -2345,6 +2401,7 @@ fn to_string(&self) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "string_to_string_specialization", since = "1.17.0")] impl ToString for String { #[inline] @@ -2377,6 +2434,7 @@ fn as_ref(&self) -> &[u8] { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl From<&str> for String { #[inline] @@ -2385,6 +2443,7 @@ fn from(s: &str) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_mut_str_for_string", since = "1.44.0")] impl From<&mut str> for String { /// Converts a `&mut str` into a `String`. @@ -2396,6 +2455,7 @@ fn from(s: &mut str) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_ref_string", since = "1.35.0")] impl From<&String> for String { #[inline] @@ -2427,6 +2487,7 @@ fn from(s: Box) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_str", since = "1.20.0")] impl From for Box { /// Converts the given `String` to a boxed `str` slice that is owned. @@ -2447,6 +2508,7 @@ fn from(s: String) -> Box { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "string_from_cow_str", since = "1.14.0")] impl<'a> From> for String { fn from(s: Cow<'a, str>) -> String { @@ -2454,6 +2516,7 @@ fn from(s: Cow<'a, str>) -> String { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&'a str> for Cow<'a, str> { /// Converts a string slice into a Borrowed variant. @@ -2472,6 +2535,7 @@ fn from(s: &'a str) -> Cow<'a, str> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From for Cow<'a, str> { /// Converts a String into an Owned variant. @@ -2492,6 +2556,7 @@ fn from(s: String) -> Cow<'a, str> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_from_string_ref", since = "1.28.0")] impl<'a> From<&'a String> for Cow<'a, str> { /// Converts a String reference into a Borrowed variant. @@ -2511,6 +2576,7 @@ fn from(s: &'a String) -> Cow<'a, str> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_str_from_iter", since = "1.12.0")] impl<'a> FromIterator for Cow<'a, str> { fn from_iter>(it: I) -> Cow<'a, str> { @@ -2518,6 +2584,7 @@ fn from_iter>(it: I) -> Cow<'a, str> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_str_from_iter", since = "1.12.0")] impl<'a, 'b> FromIterator<&'b str> for Cow<'a, str> { fn from_iter>(it: I) -> Cow<'a, str> { @@ -2525,6 +2592,7 @@ fn from_iter>(it: I) -> Cow<'a, str> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_str_from_iter", since = "1.12.0")] impl<'a> FromIterator for Cow<'a, str> { fn from_iter>(it: I) -> Cow<'a, str> { @@ -2553,6 +2621,7 @@ fn from(string: String) -> Vec { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Write for String { #[inline] @@ -2676,6 +2745,7 @@ fn next_back(&mut self) -> Option { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Drain<'_> {} +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_char_for_string", since = "1.46.0")] impl From for String { #[inline] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 1b7e656cefd9..17927f5f5fdc 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -12,23 +12,31 @@ use core::hash::{Hash, Hasher}; use core::hint; use core::intrinsics::abort; +#[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{PhantomData, Unpin, Unsize}; -use core::mem::{self, align_of_val_raw, size_of_val}; +#[cfg(not(no_global_oom_handling))] +use core::mem::size_of_val; +use core::mem::{self, align_of_val_raw}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use core::pin::Pin; use core::ptr::{self, NonNull}; +#[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; -use crate::alloc::{ - box_free, handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw, -}; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::handle_alloc_error; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::{box_free, WriteCloneIntoRaw}; +use crate::alloc::{AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::rc::is_dangling; +#[cfg(not(no_global_oom_handling))] use crate::string::String; +#[cfg(not(no_global_oom_handling))] use crate::vec::Vec; #[cfg(test)] @@ -431,6 +439,7 @@ pub fn new_cyclic(data_fn: impl FnOnce(&Weak) -> T) -> Arc { /// /// assert_eq!(*five, 5) /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Arc> { unsafe { @@ -462,6 +471,7 @@ pub fn new_uninit() -> Arc> { /// ``` /// /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed() -> Arc> { unsafe { @@ -635,6 +645,7 @@ impl Arc<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } @@ -660,6 +671,7 @@ pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { /// ``` /// /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { @@ -1072,6 +1084,7 @@ impl Arc { /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. + #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_layout( value_layout: Layout, allocate: impl FnOnce(Layout) -> Result, AllocError>, @@ -1120,6 +1133,7 @@ unsafe fn try_allocate_for_layout( } /// Allocates an `ArcInner` with sufficient space for an unsized inner value. + #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. unsafe { @@ -1131,6 +1145,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { } } + #[cfg(not(no_global_oom_handling))] fn from_box(v: Box) -> Arc { unsafe { let (box_unique, alloc) = Box::into_unique(v); @@ -1156,6 +1171,7 @@ fn from_box(v: Box) -> Arc { impl Arc<[T]> { /// Allocates an `ArcInner<[T]>` with the given length. + #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { unsafe { Self::allocate_for_layout( @@ -1169,6 +1185,7 @@ unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { /// Copy elements from slice into newly allocated Arc<\[T\]> /// /// Unsafe because the caller must either take ownership or bind `T: Copy`. + #[cfg(not(no_global_oom_handling))] unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { unsafe { let ptr = Self::allocate_for_slice(v.len()); @@ -1182,6 +1199,7 @@ unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. /// /// Behavior is undefined should the size be wrong. + #[cfg(not(no_global_oom_handling))] unsafe fn from_iter_exact(iter: impl iter::Iterator, len: usize) -> Arc<[T]> { // Panic guard while cloning T elements. // In the event of a panic, elements that have been written @@ -1229,10 +1247,12 @@ fn drop(&mut self) { } /// Specialization trait used for `From<&[T]>`. +#[cfg(not(no_global_oom_handling))] trait ArcFromSlice { fn from_slice(slice: &[T]) -> Self; } +#[cfg(not(no_global_oom_handling))] impl ArcFromSlice for Arc<[T]> { #[inline] default fn from_slice(v: &[T]) -> Self { @@ -1240,6 +1260,7 @@ impl ArcFromSlice for Arc<[T]> { } } +#[cfg(not(no_global_oom_handling))] impl ArcFromSlice for Arc<[T]> { #[inline] fn from_slice(v: &[T]) -> Self { @@ -1341,6 +1362,7 @@ impl Arc { /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "arc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { @@ -2283,6 +2305,7 @@ fn from(t: T) -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&[T]> for Arc<[T]> { /// Allocate a reference-counted slice and fill it by cloning `v`'s items. @@ -2301,6 +2324,7 @@ fn from(v: &[T]) -> Arc<[T]> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&str> for Arc { /// Allocate a reference-counted `str` and copy `v` into it. @@ -2319,6 +2343,7 @@ fn from(v: &str) -> Arc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From for Arc { /// Allocate a reference-counted `str` and copy `v` into it. @@ -2337,6 +2362,7 @@ fn from(v: String) -> Arc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From> for Arc { /// Move a boxed object to a new, reference-counted allocation. @@ -2355,6 +2381,7 @@ fn from(v: Box) -> Arc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From> for Arc<[T]> { /// Allocate a reference-counted slice and move `v`'s items into it. @@ -2408,6 +2435,7 @@ fn try_from(boxed_slice: Arc<[T]>) -> Result { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_iter", since = "1.37.0")] impl iter::FromIterator for Arc<[T]> { /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. @@ -2458,12 +2486,14 @@ trait ToArcSlice: Iterator + Sized { fn to_arc_slice(self) -> Arc<[T]>; } +#[cfg(not(no_global_oom_handling))] impl> ToArcSlice for I { default fn to_arc_slice(self) -> Arc<[T]> { self.collect::>().into() } } +#[cfg(not(no_global_oom_handling))] impl> ToArcSlice for I { fn to_arc_slice(self) -> Arc<[T]> { // This is the case for a `TrustedLen` iterator. diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 324e894bafd2..2e68161d260b 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -94,6 +94,7 @@ fn as_raw_mut_slice(&mut self) -> *mut [T] { /// (&mut into_iter).for_each(core::mem::drop); /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); } /// ``` + #[cfg(not(no_global_oom_handling))] pub(super) fn forget_allocation_drop_remaining(&mut self) { let remaining = self.as_raw_mut_slice(); @@ -224,6 +225,7 @@ unsafe impl TrustedRandomAccess for IntoIter const MAY_HAVE_SIDE_EFFECT: bool = false; } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] impl Clone for IntoIter { #[cfg(not(test))] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 85c9446689e6..1c33ff555d62 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -53,12 +53,16 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::cmp::{self, Ordering}; +#[cfg(not(no_global_oom_handling))] +use core::cmp; +use core::cmp::Ordering; use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; -use core::iter::{self, FromIterator}; +use core::iter; +#[cfg(not(no_global_oom_handling))] +use core::iter::FromIterator; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; @@ -76,9 +80,11 @@ mod drain_filter; +#[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_splice", since = "1.21.0")] pub use self::splice::Splice; +#[cfg(not(no_global_oom_handling))] mod splice; #[stable(feature = "drain", since = "1.6.0")] @@ -86,44 +92,60 @@ mod drain; +#[cfg(not(no_global_oom_handling))] mod cow; +#[cfg(not(no_global_oom_handling))] pub(crate) use self::into_iter::AsIntoIter; #[stable(feature = "rust1", since = "1.0.0")] pub use self::into_iter::IntoIter; mod into_iter; +#[cfg(not(no_global_oom_handling))] use self::is_zero::IsZero; mod is_zero; +#[cfg(not(no_global_oom_handling))] mod source_iter_marker; mod partial_eq; +#[cfg(not(no_global_oom_handling))] use self::spec_from_elem::SpecFromElem; +#[cfg(not(no_global_oom_handling))] mod spec_from_elem; +#[cfg(not(no_global_oom_handling))] use self::set_len_on_drop::SetLenOnDrop; +#[cfg(not(no_global_oom_handling))] mod set_len_on_drop; +#[cfg(not(no_global_oom_handling))] use self::in_place_drop::InPlaceDrop; +#[cfg(not(no_global_oom_handling))] mod in_place_drop; +#[cfg(not(no_global_oom_handling))] use self::spec_from_iter_nested::SpecFromIterNested; +#[cfg(not(no_global_oom_handling))] mod spec_from_iter_nested; +#[cfg(not(no_global_oom_handling))] use self::spec_from_iter::SpecFromIter; +#[cfg(not(no_global_oom_handling))] mod spec_from_iter; +#[cfg(not(no_global_oom_handling))] use self::spec_extend::SpecExtend; +#[cfg(not(no_global_oom_handling))] mod spec_extend; /// A contiguous growable array type, written as `Vec` and pronounced 'vector'. @@ -435,6 +457,7 @@ pub const fn new() -> Self { /// assert_eq!(vec.len(), 11); /// assert!(vec.capacity() >= 11); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[doc(alias = "malloc")] #[stable(feature = "rust1", since = "1.0.0")] @@ -574,6 +597,7 @@ pub const fn new_in(alloc: A) -> Self { /// assert_eq!(vec.len(), 11); /// assert!(vec.capacity() >= 11); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { @@ -774,6 +798,7 @@ pub fn capacity(&self) -> usize { /// vec.reserve(10); /// assert!(vec.capacity() >= 11); /// ``` + #[cfg(not(no_global_oom_handling))] #[doc(alias = "realloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { @@ -800,6 +825,7 @@ pub fn reserve(&mut self, additional: usize) { /// vec.reserve_exact(10); /// assert!(vec.capacity() >= 11); /// ``` + #[cfg(not(no_global_oom_handling))] #[doc(alias = "realloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve_exact(&mut self, additional: usize) { @@ -900,6 +926,7 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE /// vec.shrink_to_fit(); /// assert!(vec.capacity() >= 3); /// ``` + #[cfg(not(no_global_oom_handling))] #[doc(alias = "realloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn shrink_to_fit(&mut self) { @@ -930,6 +957,7 @@ pub fn shrink_to_fit(&mut self) { /// vec.shrink_to(0); /// assert!(vec.capacity() >= 3); /// ``` + #[cfg(not(no_global_oom_handling))] #[doc(alias = "realloc")] #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] pub fn shrink_to(&mut self, min_capacity: usize) { @@ -962,6 +990,7 @@ pub fn shrink_to(&mut self, min_capacity: usize) { /// let slice = vec.into_boxed_slice(); /// assert_eq!(slice.into_vec().capacity(), 3); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn into_boxed_slice(mut self) -> Box<[T], A> { unsafe { @@ -1299,6 +1328,7 @@ fn assert_failed(index: usize, len: usize) -> ! { /// vec.insert(4, 5); /// assert_eq!(vec, [1, 4, 2, 3, 5]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, index: usize, element: T) { #[cold] @@ -1627,6 +1657,7 @@ fn drop(&mut self) { /// vec.push(3); /// assert_eq!(vec, [1, 2, 3]); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, value: T) { @@ -1680,6 +1711,7 @@ pub fn pop(&mut self) -> Option { /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); /// assert_eq!(vec2, []); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { @@ -1690,6 +1722,7 @@ pub fn append(&mut self, other: &mut Self) { } /// Appends elements to `Self` from other buffer. + #[cfg(not(no_global_oom_handling))] #[inline] unsafe fn append_elements(&mut self, other: *const [T]) { let count = unsafe { (*other).len() }; @@ -1827,6 +1860,7 @@ pub fn is_empty(&self) -> bool { /// assert_eq!(vec, [1]); /// assert_eq!(vec2, [2, 3]); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[must_use = "use `.truncate()` if you don't need the other half"] #[stable(feature = "split_off", since = "1.4.0")] @@ -1891,6 +1925,7 @@ fn assert_failed(at: usize, len: usize) -> ! { /// vec.resize_with(4, || { p *= 2; p }); /// assert_eq!(vec, [2, 4, 8, 16]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_resize_with", since = "1.33.0")] pub fn resize_with(&mut self, new_len: usize, f: F) where @@ -1926,6 +1961,7 @@ pub fn resize_with(&mut self, new_len: usize, f: F) /// static_ref[0] += 1; /// assert_eq!(static_ref, &[2, 2, 3]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_leak", since = "1.47.0")] #[inline] pub fn leak<'a>(self) -> &'a mut [T] @@ -2084,6 +2120,7 @@ impl Vec { /// vec.resize(2, 0); /// assert_eq!(vec, [1, 2]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_resize", since = "1.5.0")] pub fn resize(&mut self, new_len: usize, value: T) { let len = self.len(); @@ -2114,6 +2151,7 @@ pub fn resize(&mut self, new_len: usize, value: T) { /// ``` /// /// [`extend`]: Vec::extend + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] pub fn extend_from_slice(&mut self, other: &[T]) { self.spec_extend(other.iter()) @@ -2135,6 +2173,7 @@ pub fn extend_from_slice(&mut self, other: &[T]) { /// vec.extend_from_within(4..8); /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_extend_from_within", since = "1.53.0")] pub fn extend_from_within(&mut self, src: R) where @@ -2188,6 +2227,7 @@ fn last(mut self) -> T { } impl Vec { + #[cfg(not(no_global_oom_handling))] /// Extend the vector by `n` values, using the given generator. fn extend_with>(&mut self, n: usize, mut value: E) { self.reserve(n); @@ -2245,12 +2285,14 @@ pub fn dedup(&mut self) { //////////////////////////////////////////////////////////////////////////////// #[doc(hidden)] +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_elem(elem: T, n: usize) -> Vec { ::from_elem(elem, n, Global) } #[doc(hidden)] +#[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { ::from_elem(elem, n, alloc) @@ -2331,6 +2373,7 @@ fn deref_mut(&mut self) -> &mut [T] { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Vec { #[cfg(not(test))] @@ -2397,6 +2440,7 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { #[inline] @@ -2467,6 +2511,7 @@ fn into_iter(self) -> slice::IterMut<'a, T> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Extend for Vec { #[inline] @@ -2488,6 +2533,7 @@ fn extend_reserve(&mut self, additional: usize) { impl Vec { // leaf method to which various SpecFrom/SpecExtend implementations delegate when // they have no further optimizations to apply + #[cfg(not(no_global_oom_handling))] fn extend_desugared>(&mut self, mut iterator: I) { // This is the case for a general iterator. // @@ -2543,6 +2589,7 @@ fn extend_desugared>(&mut self, mut iterator: I) { /// assert_eq!(v, &[7, 8, 3]); /// assert_eq!(u, &[1, 2]); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "vec_splice", since = "1.21.0")] pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> @@ -2619,6 +2666,7 @@ pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> /// append the entire slice at once. /// /// [`copy_from_slice`]: slice::copy_from_slice +#[cfg(not(no_global_oom_handling))] #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { fn extend>(&mut self, iter: I) { @@ -2713,6 +2761,7 @@ fn as_mut(&mut self) -> &mut [T] { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl From<&[T]> for Vec { /// Allocate a `Vec` and fill it by cloning `s`'s items. @@ -2732,6 +2781,7 @@ fn from(s: &[T]) -> Vec { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_from_mut", since = "1.19.0")] impl From<&mut [T]> for Vec { /// Allocate a `Vec` and fill it by cloning `s`'s items. @@ -2813,6 +2863,7 @@ fn from(s: Box<[T], A>) -> Self { } // note: test pulls in libstd, which causes errors here +#[cfg(not(no_global_oom_handling))] #[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] impl From> for Box<[T], A> { @@ -2831,6 +2882,7 @@ fn from(v: Vec) -> Self { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl From<&str> for Vec { /// Allocate a `Vec` and fill it with a UTF-8 string. diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs index ff90b6caf460..50e140961050 100644 --- a/library/alloc/src/vec/partial_eq.rs +++ b/library/alloc/src/vec/partial_eq.rs @@ -1,4 +1,5 @@ use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] use crate::borrow::Cow; use super::Vec; @@ -26,8 +27,11 @@ fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } __impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } __impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } __impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +#[cfg(not(no_global_oom_handling))] __impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +#[cfg(not(no_global_oom_handling))] __impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +#[cfg(not(no_global_oom_handling))] __impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } __impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } __impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } diff --git a/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile b/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile new file mode 100644 index 000000000000..c68ae40eb94e --- /dev/null +++ b/src/test/run-make-fulldeps/alloc-no-oom-handling/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) --edition=2018 --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg feature=\"external_crate\" --cfg no_global_oom_handling