Auto merge of #84266 - QuiltOS:statically-disallow-global-oom-handling, r=Mark-Simulacrum

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/
This commit is contained in:
bors
2021-05-06 04:41:20 +00:00
18 changed files with 326 additions and 57 deletions
+5 -4
View File
@@ -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<T: ?Sized, A: Allocator>(ptr: Unique<T>, 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<T: ?Sized, A: Allocator>(ptr: Unique<T>, 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")]
+8 -1
View File
@@ -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<Cow<'a, str>> 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<Cow<'a, str>> for Cow<'a, str> {
fn add_assign(&mut self, rhs: Cow<'a, str>) {
+33 -2
View File
@@ -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<T> Box<T> {
/// ```
/// 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<mem::MaybeUninit<T>> {
@@ -227,6 +237,7 @@ pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
/// ```
///
/// [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<mem::MaybeUninit<T>> {
/// Constructs a new `Pin<Box<T>>`. 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<Box<T>> {
@@ -329,6 +341,7 @@ impl<T, A: Allocator> Box<T, A> {
///
/// 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<Self, AllocError> {
/// 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<mem::MaybeUninit<T>, A> {
let layout = Layout::new::<mem::MaybeUninit<T>>();
@@ -447,6 +461,7 @@ pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, 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<mem::MaybeUninit<T>, A> {
let layout = Layout::new::<mem::MaybeUninit<T>>();
@@ -490,6 +505,7 @@ pub fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocE
/// Constructs a new `Pin<Box<T, A>>`. 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<Self>
@@ -547,6 +563,7 @@ impl<T> 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<T>]> {
unsafe { RawVec::with_capacity(len).into_box(len) }
@@ -570,6 +587,7 @@ pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
/// ```
///
/// [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<T>]> {
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
@@ -599,6 +617,7 @@ impl<T, A: Allocator> 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<T>], A> {
@@ -625,6 +644,7 @@ pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], 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<T>], A> {
@@ -1013,6 +1033,7 @@ fn default() -> Self {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> 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<str> {
fn default() -> Self {
@@ -1027,6 +1049,7 @@ fn default() -> Self {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
/// 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<str> {
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<T> From<T> for Box<T> {
/// Converts a generic type `T` into a `Box<T>`
@@ -1214,6 +1239,7 @@ fn from(boxed: Box<T, A>) -> Self {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_from_slice", since = "1.17.0")]
impl<T: Copy> 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<T: Copy> From<Cow<'_, [T]>> 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<str> {
/// Converts a `&str` into a `Box<str>`
@@ -1268,6 +1296,7 @@ fn from(s: &str) -> Box<str> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_from_cow", since = "1.45.0")]
impl From<Cow<'_, str>> for Box<str> {
#[inline]
@@ -1567,6 +1596,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> fo
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T, Global> {}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
impl<I> FromIterator<I> for Box<[I]> {
fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
@@ -1574,6 +1604,7 @@ fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
fn clone(&self) -> Self {
+11
View File
@@ -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;
+2
View File
@@ -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();
+2 -2
View File
@@ -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;
+15 -1
View File
@@ -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<T>], A> {
}
}
#[cfg(not(no_global_oom_handling))]
fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self {
if mem::size_of::<T>() == 0 {
Self::new_in(alloc)
@@ -309,6 +317,7 @@ fn current_memory(&self) -> Option<(NonNull<u8>, 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");
}
+34 -4
View File
@@ -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>) -> T) -> Rc<T> {
///
/// assert_eq!(*five, 5)
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
unsafe {
@@ -465,6 +474,7 @@ pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
/// ```
///
/// [zeroed]: mem::MaybeUninit::zeroed
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed() -> Rc<mem::MaybeUninit<T>> {
unsafe {
@@ -637,6 +647,7 @@ impl<T> 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<T>]> {
unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) }
@@ -662,6 +673,7 @@ pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
/// ```
///
/// [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<T>]> {
unsafe {
@@ -1122,6 +1134,7 @@ impl<T: Clone> Rc<T> {
/// 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<T: ?Sized> Rc<T> {
///
/// The function `mem_to_rcbox` is called with the data pointer
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_layout(
value_layout: Layout,
allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
@@ -1245,6 +1259,7 @@ unsafe fn try_allocate_for_layout(
}
/// Allocates an `RcBox<T>` with sufficient space for an unsized inner value
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
// Allocate for the `RcBox<T>` using the given value.
unsafe {
@@ -1256,6 +1271,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
}
}
#[cfg(not(no_global_oom_handling))]
fn from_box(v: Box<T>) -> Rc<T> {
unsafe {
let (box_unique, alloc) = Box::into_unique(v);
@@ -1281,6 +1297,7 @@ fn from_box(v: Box<T>) -> Rc<T> {
impl<T> 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<Item = T>, 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<T> {
fn from_slice(slice: &[T]) -> Self;
}
#[cfg(not(no_global_oom_handling))]
impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
#[inline]
default fn from_slice(v: &[T]) -> Self {
@@ -1363,6 +1383,7 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: Copy> RcFromSlice<T> 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<T: Clone> 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<str> {
/// Allocate a reference-counted string slice and copy `v` into it.
@@ -1753,6 +1776,7 @@ fn from(v: &str) -> Rc<str> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl From<String> for Rc<str> {
/// Allocate a reference-counted string slice and copy `v` into it.
@@ -1771,6 +1795,7 @@ fn from(v: String) -> Rc<str> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T: ?Sized> From<Box<T>> for Rc<T> {
/// Move a boxed object to a new, reference counted, allocation.
@@ -1789,6 +1814,7 @@ fn from(v: Box<T>) -> Rc<T> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T> From<Vec<T>> 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<Self, Self::Error> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_iter", since = "1.37.0")]
impl<T> iter::FromIterator<T> for Rc<[T]> {
/// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`.
@@ -1888,16 +1915,19 @@ fn from_iter<I: iter::IntoIterator<Item = T>>(iter: I) -> Self {
}
/// Specialization trait used for collecting into `Rc<[T]>`.
#[cfg(not(no_global_oom_handling))]
trait ToRcSlice<T>: Iterator<Item = T> + Sized {
fn to_rc_slice(self) -> Rc<[T]>;
}
#[cfg(not(no_global_oom_handling))]
impl<T, I: Iterator<Item = T>> ToRcSlice<T> for I {
default fn to_rc_slice(self) -> Rc<[T]> {
self.collect::<Vec<T>>().into()
}
}
#[cfg(not(no_global_oom_handling))]
impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
fn to_rc_slice(self) -> Rc<[T]> {
// This is the case for a `TrustedLen` iterator.
+30 -2
View File
@@ -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<T, A: Allocator>(b: Box<[T], A>) -> Vec<T, A> {
}
}
#[cfg(not(no_global_oom_handling))]
#[inline]
pub fn to_vec<T: ConvertVec, A: Allocator>(s: &[T], alloc: A) -> Vec<T, A> {
T::to_vec(s, alloc)
}
#[cfg(not(no_global_oom_handling))]
pub trait ConvertVec {
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A>
where
Self: Sized;
}
#[cfg(not(no_global_oom_handling))]
impl<T: Clone> ConvertVec for T {
#[inline]
default fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
@@ -205,6 +216,7 @@ fn drop(&mut self) {
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: Copy> ConvertVec for T {
#[inline]
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
@@ -250,6 +262,7 @@ impl<T> [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<F>(&mut self, mut compare: F)
@@ -344,6 +358,7 @@ pub fn sort_by<F>(&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<K, F>(&mut self, mut f: F)
@@ -386,6 +401,7 @@ pub fn sort_by_key<K, F>(&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<K, F>(&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<T>
/// 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<A: Allocator>(&self, alloc: A) -> Vec<T, A>
@@ -517,6 +535,7 @@ pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
/// // 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<T>
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<u8> {
@@ -659,6 +679,7 @@ pub fn to_ascii_uppercase(&self) -> Vec<u8> {
/// 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<u8> {
@@ -724,6 +745,7 @@ pub trait Join<Separator> {
fn join(slice: &Self, sep: Separator) -> Self::Output;
}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "slice_concat_ext", issue = "27747")]
impl<T: Clone, V: Borrow<[T]>> Concat<T> for [V] {
type Output = Vec<T>;
@@ -738,6 +760,7 @@ fn concat(slice: &Self) -> Vec<T> {
}
}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "slice_concat_ext", issue = "27747")]
impl<T: Clone, V: Borrow<[T]>> Join<&T> for [V] {
type Output = Vec<T>;
@@ -760,6 +783,7 @@ fn join(slice: &Self, sep: &T) -> Vec<T> {
}
}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "slice_concat_ext", issue = "27747")]
impl<T: Clone, V: Borrow<[T]>> Join<&[T]> for [V] {
type Output = Vec<T>;
@@ -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<T: Clone> ToOwned for [T] {
type Owned = Vec<T>;
@@ -835,6 +860,7 @@ fn clone_into(&self, target: &mut Vec<T>) {
/// 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<T, F>(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<T, F>(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<T, F>(v: &mut [T], mut is_less: F)
where
F: FnMut(&T, &T) -> bool,
+13
View File
@@ -74,6 +74,7 @@
/// Note: `str` in `Concat<str>` 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<S: Borrow<str>> Concat<str> 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<S: Borrow<str>> 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<str> 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<B, T, S>(slice: &[S], sep: &[T]) -> Vec<T>
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<str>) -> 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<I: Iterator<Item = char>>(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<str>) -> 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 {
+75 -5
View File
@@ -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-8encoded, 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<u8>,
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<u8>) -> Result<String, FromUtf8Error> {
///
/// 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<String, FromUtf16Error> {
// This isn't done via collect::<Result<_, _>>() for performance reasons.
@@ -626,6 +643,7 @@ pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
/// 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<R>(&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<R>(&mut self, range: R, replace_with: &str)
where
@@ -1654,6 +1684,7 @@ pub fn replace_range<R>(&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<str> {
@@ -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<char> for String {
fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> String {
@@ -1768,6 +1801,7 @@ fn from_iter<I: IntoIterator<Item = char>>(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<I: IntoIterator<Item = &'a char>>(iter: I) -> String {
@@ -1777,6 +1811,7 @@ fn from_iter<I: IntoIterator<Item = &'a char>>(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<I: IntoIterator<Item = &'a str>>(iter: I) -> String {
@@ -1786,6 +1821,7 @@ fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> String {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "extend_string", since = "1.4.0")]
impl FromIterator<String> for String {
fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String {
@@ -1804,6 +1840,7 @@ fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_str2", since = "1.45.0")]
impl FromIterator<Box<str>> for String {
fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> String {
@@ -1813,6 +1850,7 @@ fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> String {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "herd_cows", since = "1.19.0")]
impl<'a> FromIterator<Cow<'a, str>> for String {
fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String {
@@ -1832,6 +1870,7 @@ fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Extend<char> for String {
fn extend<I: IntoIterator<Item = char>>(&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<I: IntoIterator<Item = &'a char>>(&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<I: IntoIterator<Item = &'a str>>(&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<Box<str>> for String {
fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) {
@@ -1888,6 +1930,7 @@ fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "extend_string", since = "1.4.0")]
impl Extend<String> for String {
fn extend<I: IntoIterator<Item = String>>(&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<Cow<'a, str>> for String {
fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&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<H: hash::Hasher>(&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<T: fmt::Display + ?Sized> ToString for T {
// A common guideline is to not inline generic functions. However,
@@ -2280,6 +2331,7 @@ impl<T: fmt::Display + ?Sized> 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<str>) -> String {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_from_str", since = "1.20.0")]
impl From<String> for Box<str> {
/// Converts the given `String` to a boxed `str` slice that is owned.
@@ -2447,6 +2508,7 @@ fn from(s: String) -> Box<str> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "string_from_cow_str", since = "1.14.0")]
impl<'a> From<Cow<'a, str>> 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<String> 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<char> for Cow<'a, str> {
fn from_iter<I: IntoIterator<Item = char>>(it: I) -> Cow<'a, str> {
@@ -2518,6 +2584,7 @@ fn from_iter<I: IntoIterator<Item = char>>(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<I: IntoIterator<Item = &'b str>>(it: I) -> Cow<'a, str> {
@@ -2525,6 +2592,7 @@ fn from_iter<I: IntoIterator<Item = &'b str>>(it: I) -> Cow<'a, str> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "cow_str_from_iter", since = "1.12.0")]
impl<'a> FromIterator<String> for Cow<'a, str> {
fn from_iter<I: IntoIterator<Item = String>>(it: I) -> Cow<'a, str> {
@@ -2553,6 +2621,7 @@ fn from(string: String) -> Vec<u8> {
}
}
#[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<char> {
#[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<char> for String {
#[inline]
+34 -4
View File
@@ -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>) -> T) -> Arc<T> {
///
/// assert_eq!(*five, 5)
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
unsafe {
@@ -462,6 +471,7 @@ pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
/// ```
///
/// [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<mem::MaybeUninit<T>> {
unsafe {
@@ -635,6 +645,7 @@ impl<T> 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<T>]> {
unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) }
@@ -660,6 +671,7 @@ pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
/// ```
///
/// [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<T>]> {
unsafe {
@@ -1072,6 +1084,7 @@ impl<T: ?Sized> Arc<T> {
///
/// The function `mem_to_arcinner` is called with the data pointer
/// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_layout(
value_layout: Layout,
allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
@@ -1120,6 +1133,7 @@ unsafe fn try_allocate_for_layout(
}
/// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
// Allocate for the `ArcInner<T>` using the given value.
unsafe {
@@ -1131,6 +1145,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
}
}
#[cfg(not(no_global_oom_handling))]
fn from_box(v: Box<T>) -> Arc<T> {
unsafe {
let (box_unique, alloc) = Box::into_unique(v);
@@ -1156,6 +1171,7 @@ fn from_box(v: Box<T>) -> Arc<T> {
impl<T> 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<Item = T>, 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<T> {
fn from_slice(slice: &[T]) -> Self;
}
#[cfg(not(no_global_oom_handling))]
impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
#[inline]
default fn from_slice(v: &[T]) -> Self {
@@ -1240,6 +1260,7 @@ impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: Copy> ArcFromSlice<T> for Arc<[T]> {
#[inline]
fn from_slice(v: &[T]) -> Self {
@@ -1341,6 +1362,7 @@ impl<T: Clone> Arc<T> {
/// 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<T: Clone> 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<str> {
/// Allocate a reference-counted `str` and copy `v` into it.
@@ -2319,6 +2343,7 @@ fn from(v: &str) -> Arc<str> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl From<String> for Arc<str> {
/// Allocate a reference-counted `str` and copy `v` into it.
@@ -2337,6 +2362,7 @@ fn from(v: String) -> Arc<str> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T: ?Sized> From<Box<T>> for Arc<T> {
/// Move a boxed object to a new, reference-counted allocation.
@@ -2355,6 +2381,7 @@ fn from(v: Box<T>) -> Arc<T> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T> From<Vec<T>> 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<Self, Self::Error> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_iter", since = "1.37.0")]
impl<T> iter::FromIterator<T> for Arc<[T]> {
/// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`.
@@ -2458,12 +2486,14 @@ trait ToArcSlice<T>: Iterator<Item = T> + Sized {
fn to_arc_slice(self) -> Arc<[T]>;
}
#[cfg(not(no_global_oom_handling))]
impl<T, I: Iterator<Item = T>> ToArcSlice<T> for I {
default fn to_arc_slice(self) -> Arc<[T]> {
self.collect::<Vec<T>>().into()
}
}
#[cfg(not(no_global_oom_handling))]
impl<T, I: iter::TrustedLen<Item = T>> ToArcSlice<T> for I {
fn to_arc_slice(self) -> Arc<[T]> {
// This is the case for a `TrustedLen` iterator.
+2
View File
@@ -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<T, A: Allocator> TrustedRandomAccess for IntoIter<T, A>
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
#[cfg(not(test))]
+54 -2
View File
@@ -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<T>` 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<T> {
/// 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<F>(&mut self, new_len: usize, f: F)
where
@@ -1926,6 +1961,7 @@ pub fn resize_with<F>(&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<T: Clone, A: Allocator> Vec<T, A> {
/// 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<R>(&mut self, src: R)
where
@@ -2188,6 +2227,7 @@ fn last(mut self) -> T {
}
impl<T, A: Allocator> Vec<T, A> {
#[cfg(not(no_global_oom_handling))]
/// Extend the vector by `n` values, using the given generator.
fn extend_with<E: ExtendWith<T>>(&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<T: Clone>(elem: T, n: usize) -> Vec<T> {
<T as SpecFromElem>::from_elem(elem, n, Global)
}
#[doc(hidden)]
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn from_elem_in<T: Clone, A: Allocator>(elem: T, n: usize, alloc: A) -> Vec<T, A> {
<T as SpecFromElem>::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<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
#[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<T> FromIterator<T> for Vec<T> {
#[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<T, A: Allocator> Extend<T> for Vec<T, A> {
#[inline]
@@ -2488,6 +2533,7 @@ fn extend_reserve(&mut self, additional: usize) {
impl<T, A: Allocator> Vec<T, A> {
// 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<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
// This is the case for a general iterator.
//
@@ -2543,6 +2589,7 @@ fn extend_desugared<I: Iterator<Item = T>>(&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<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A>
@@ -2619,6 +2666,7 @@ pub fn drain_filter<F>(&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<T, A> {
fn extend<I: IntoIterator<Item = &'a T>>(&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<T: Clone> From<&[T]> for Vec<T> {
/// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
@@ -2732,6 +2781,7 @@ fn from(s: &[T]) -> Vec<T> {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_mut", since = "1.19.0")]
impl<T: Clone> From<&mut [T]> for Vec<T> {
/// Allocate a `Vec<T>` 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<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
@@ -2831,6 +2882,7 @@ fn from(v: Vec<T, A>) -> Self {
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl From<&str> for Vec<u8> {
/// Allocate a `Vec<u8>` and fill it with a UTF-8 string.
+4
View File
@@ -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<U, A>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] }
__impl_slice_eq1! { [A: Allocator] Vec<T, A>, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] }
__impl_slice_eq1! { [A: Allocator] [T], Vec<U, A>, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] }
#[cfg(not(no_global_oom_handling))]
__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec<U, A> 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<T, A>, [U; N], #[stable(feature = "rust1", since = "1.0.0")] }
__impl_slice_eq1! { [A: Allocator, const N: usize] Vec<T, A>, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] }
@@ -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)
@@ -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() { }
@@ -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