diff --git a/Cargo.lock b/Cargo.lock index 9581099c210ea..fbead7e807b6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,7 +303,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.69.0" +version = "0.68.0" dependencies = [ "anyhow", "bytesize", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9cc81f391672e..c380ed1eca8b7 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -25,6 +25,7 @@ pub use UnsafeSource::*; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream}; +use core::alloc::GlobalCoAllocMeta; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; @@ -36,7 +37,6 @@ use rustc_span::{Span, DUMMY_SP}; use std::fmt; use std::mem; use thin_vec::{thin_vec, ThinVec}; - /// A "Label" is an identifier of some point in sources, /// e.g. in the following code: /// @@ -3083,26 +3083,26 @@ mod size_asserts { static_assert_size!(AssocItem, 104); static_assert_size!(AssocItemKind, 32); static_assert_size!(Attribute, 32); - static_assert_size!(Block, 48); - static_assert_size!(Expr, 72); - static_assert_size!(ExprKind, 40); - static_assert_size!(Fn, 184); + static_assert_size!(Block, 48 + mem::size_of::()); + static_assert_size!(Expr, 72 + mem::size_of::()); + static_assert_size!(ExprKind, 40 + mem::size_of::()); + static_assert_size!(Fn, 184 + 2 * mem::size_of::()); static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); - static_assert_size!(GenericBound, 72); - static_assert_size!(Generics, 72); - static_assert_size!(Impl, 184); - static_assert_size!(Item, 184); - static_assert_size!(ItemKind, 112); + static_assert_size!(GenericBound, 72 + mem::size_of::()); + static_assert_size!(Generics, 72 + 2 * mem::size_of::()); + static_assert_size!(Impl, 184 + 3 * mem::size_of::()); + static_assert_size!(Item, 184 + 3 * mem::size_of::()); + static_assert_size!(ItemKind, 112 + 3 * mem::size_of::()); static_assert_size!(LitKind, 24); static_assert_size!(Local, 72); static_assert_size!(MetaItemLit, 40); static_assert_size!(Param, 40); - static_assert_size!(Pat, 88); + static_assert_size!(Pat, 88 + mem::size_of::()); static_assert_size!(Path, 24); static_assert_size!(PathSegment, 24); - static_assert_size!(PatKind, 64); + static_assert_size!(PatKind, 64 + mem::size_of::()); static_assert_size!(Stmt, 32); static_assert_size!(StmtKind, 16); static_assert_size!(Ty, 64); diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 9c1dfeb1a6142..cd7242449a72d 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -12,6 +12,7 @@ #![feature(box_patterns)] #![feature(const_default_impls)] #![feature(const_trait_impl)] +#![feature(global_co_alloc_meta)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(min_specialization)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 7e4063c2ffd78..7e05e4702d55d 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -32,6 +32,7 @@ #![feature(exhaustive_patterns)] #![feature(generators)] #![feature(get_mut_unchecked)] +#![feature(global_co_alloc_meta)] #![feature(if_let_guard)] #![feature(iter_from_generator)] #![feature(negative_impls)] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index a89e6566d56af..f3b4eb0b58cb1 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -13,6 +13,7 @@ use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, DefIdTree, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; +use core::alloc::GlobalCoAllocMeta; use rustc_data_structures::captures::Captures; use rustc_errors::ErrorGuaranteed; @@ -3060,7 +3061,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(BasicBlockData<'_>, 144); + static_assert_size!(BasicBlockData<'_>, 144 + mem::size_of::()); static_assert_size!(LocalDecl<'_>, 56); static_assert_size!(Statement<'_>, 32); static_assert_size!(StatementKind<'_>, 16); diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 6b4489026d3d3..58d6b1499f257 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -4,6 +4,8 @@ //! The intention is that this file only contains datatype declarations, no code. use super::{BasicBlock, Constant, Field, Local, SwitchTargets, UserTypeProjection}; +use core::alloc::GlobalCoAllocMeta; +use core::mem; use crate::mir::coverage::{CodeRegion, CoverageKind}; use crate::traits::Reveal; @@ -1268,6 +1270,6 @@ mod size_asserts { static_assert_size!(Operand<'_>, 24); static_assert_size!(Place<'_>, 16); static_assert_size!(PlaceElem<'_>, 24); - static_assert_size!(Rvalue<'_>, 40); + static_assert_size!(Rvalue<'_>, 40 + mem::size_of::()); // tidy-alphabetical-end } diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index b49a01d75ed54..1ba1049b0bc80 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -2,6 +2,7 @@ #![feature(array_windows)] #![feature(box_patterns)] +#![feature(global_co_alloc_meta)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index b97f22417cb7b..df02751005ce8 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -1,4 +1,6 @@ use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken}; +use core::alloc::GlobalCoAllocMeta; +use core::mem; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{AttrTokenStream, AttributesData, ToAttrTokenStream}; use rustc_ast::tokenstream::{AttrTokenTree, DelimSpan, LazyAttrTokenStream, Spacing}; @@ -469,6 +471,6 @@ mod size_asserts { use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(AttrWrapper, 16); - static_assert_size!(LazyAttrTokenStreamImpl, 144); + static_assert_size!(LazyAttrTokenStreamImpl, 144 + mem::size_of::()); // tidy-alphabetical-end } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 49d3198153953..542b504f9b34a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -12,6 +12,7 @@ mod ty; use crate::lexer::UnmatchedBrace; pub use attr_wrapper::AttrWrapper; +use core::alloc::GlobalCoAllocMeta; pub use diagnostics::AttemptLocalParseRecovery; pub(crate) use item::FnParseMode; pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; @@ -168,7 +169,10 @@ pub struct Parser<'a> { // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure // it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Parser<'_>, 336); +rustc_data_structures::static_assert_size!( + Parser<'_>, + 336 + 4 * mem::size_of::() +); /// Stores span information about a closure. #[derive(Clone)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index a30d1df4ede52..bf9b80b75d613 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -15,6 +15,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(drain_filter)] +#![feature(global_co_alloc_meta)] #![feature(hash_drain_filter)] #![feature(let_chains)] #![feature(if_let_guard)] diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 76a755ed9e09d..378419868c427 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -1,4 +1,6 @@ use crate::infer::{InferCtxt, TyOrConstInferVar}; +use core::alloc::GlobalCoAllocMeta; +use core::mem; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; @@ -80,7 +82,7 @@ pub struct PendingPredicateObligation<'tcx> { // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PendingPredicateObligation<'_>, 72); +static_assert_size!(PendingPredicateObligation<'_>, 72 + mem::size_of::()); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index a563b2587236c..615744a2d60a3 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -146,6 +146,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use core::alloc; use core::any::Any; use core::async_iter::AsyncIterator; use core::borrow; @@ -698,7 +699,12 @@ impl Box<[T]> { Err(_) => return Err(AllocError), }; let ptr = Global.allocate(layout)?; - Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len)) + Ok(RawVec::::from_raw_parts_in( + ptr.as_mut_ptr() as *mut _, + len, + Global, + ) + .into_box(len)) } } @@ -730,12 +736,20 @@ impl Box<[T]> { Err(_) => return Err(AllocError), }; let ptr = Global.allocate_zeroed(layout)?; - Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len)) + Ok(RawVec::::from_raw_parts_in( + ptr.as_mut_ptr() as *mut _, + len, + Global, + ) + .into_box(len)) } } } -impl Box<[T], A> { +impl Box<[T], A> +where + [(); core::alloc::co_alloc_metadata_num_slots::()]:, +{ /// Constructs a new boxed slice with uninitialized contents in the provided allocator. /// /// # Examples @@ -763,7 +777,10 @@ impl Box<[T], A> { // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { - unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } + unsafe { + RawVec::::with_capacity_in(len, alloc) + .into_box(len) + } } /// Constructs a new boxed slice with uninitialized contents in the provided allocator, @@ -791,7 +808,12 @@ impl Box<[T], A> { // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { - unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } + unsafe { + RawVec::::with_capacity_zeroed_in( + len, alloc, + ) + .into_box(len) + } } } @@ -1661,8 +1683,12 @@ impl TryFrom> for Box<[T; N]> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")] -impl TryFrom> for Box<[T; N]> { - type Error = Vec; +impl TryFrom> + for Box<[T; N]> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + type Error = Vec; /// Attempts to convert a `Vec` into a `Box<[T; N]>`. /// @@ -1682,7 +1708,7 @@ impl TryFrom> for Box<[T; N]> { /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap(); /// assert_eq!(state.len(), 100); /// ``` - fn try_from(vec: Vec) -> Result { + fn try_from(vec: Vec) -> Result { if vec.len() == N { let boxed_slice = vec.into_boxed_slice(); Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) @@ -2019,7 +2045,10 @@ impl FromIterator for Box<[I]> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_slice_clone", since = "1.3.0")] -impl Clone for Box<[T], A> { +impl Clone for Box<[T], A> +where + [(); core::alloc::co_alloc_metadata_num_slots::()]:, +{ fn clone(&self) -> Self { let alloc = Box::allocator(self).clone(); self.to_vec_in(alloc).into_boxed_slice() diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 4583bc9a158ef..33cfb7ad9341b 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -143,11 +143,13 @@ #![allow(missing_docs)] #![stable(feature = "rust1", since = "1.0.0")] -use core::fmt; use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; use core::mem::{self, swap, ManuallyDrop}; use core::ops::{Deref, DerefMut}; use core::ptr; +use core::{alloc, fmt}; + +use crate::alloc::Global; use crate::collections::TryReserveError; use crate::slice; @@ -1196,7 +1198,7 @@ impl BinaryHeap { /// ``` #[inline] #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self) -> Drain<'_, T> { + pub fn drain(&mut self) -> Drain<'_, T, { alloc::SHORT_TERM_VEC_PREFERS_COOP }> { Drain { iter: self.data.drain(..) } } @@ -1476,12 +1478,18 @@ unsafe impl TrustedLen for IntoIterSorted {} /// [`drain`]: BinaryHeap::drain #[stable(feature = "drain", since = "1.6.0")] #[derive(Debug)] -pub struct Drain<'a, T: 'a> { - iter: vec::Drain<'a, T>, +pub struct Drain<'a, T: 'a, const COOP_PREFERRED: bool> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + iter: vec::Drain<'a, T, Global, COOP_PREFERRED>, } #[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T> { +impl Iterator for Drain<'_, T, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Item = T; #[inline] @@ -1496,7 +1504,7 @@ impl Iterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T> { +impl DoubleEndedIterator for Drain<'_, T, COOP_PREFERRED> { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back() @@ -1504,14 +1512,14 @@ impl DoubleEndedIterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T> { +impl ExactSizeIterator for Drain<'_, T, COOP_PREFERRED> { fn is_empty(&self) -> bool { self.iter.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T> {} +impl FusedIterator for Drain<'_, T, COOP_PREFERRED> {} /// A draining iterator over the elements of a `BinaryHeap`. /// diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 89feb361ddc11..2004060c4bb96 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -2,7 +2,7 @@ use core::iter::FusedIterator; use core::marker::PhantomData; use core::mem::{self, SizedTypeProperties}; use core::ptr::NonNull; -use core::{fmt, ptr}; +use core::{alloc, fmt, ptr}; use crate::alloc::{Allocator, Global}; @@ -19,10 +19,13 @@ pub struct Drain< 'a, T: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> { + const COOP_PREFERRED: bool = { alloc::SHORT_TERM_VEC_PREFERS_COOP }, +> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ // We can't just use a &mut VecDeque, as that would make Drain invariant over T // and we want it to be covariant instead - deque: NonNull>, + deque: NonNull>, // drain_start is stored in deque.len drain_len: usize, // index into the logical array, not the physical one (always lies in [0..deque.len)) @@ -34,9 +37,12 @@ pub struct Drain< _marker: PhantomData<&'a T>, } -impl<'a, T, A: Allocator> Drain<'a, T, A> { +impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> Drain<'a, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ pub(super) unsafe fn new( - deque: &'a mut VecDeque, + deque: &'a mut VecDeque, drain_start: usize, drain_len: usize, ) -> Self { @@ -88,7 +94,11 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T, A> { +impl fmt::Debug + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain") .field(&self.drain_len) @@ -100,16 +110,37 @@ impl fmt::Debug for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T, A> {} +unsafe impl Sync + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T, A> {} +unsafe impl Send + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T, A> { +impl Drop for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn drop(&mut self) { - struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + struct DropGuard<'r, 'a, T, A: Allocator, const COOP_PREFERRED: bool>( + &'r mut Drain<'a, T, A, COOP_PREFERRED>, + ) + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:; - impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + impl<'r, 'a, T, A: Allocator, const COOP_PREFERRED: bool> Drop + for DropGuard<'r, 'a, T, A, COOP_PREFERRED> + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { fn drop(&mut self) { if self.0.remaining != 0 { unsafe { @@ -190,7 +221,10 @@ impl Drop for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T, A> { +impl Iterator for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = T; #[inline] @@ -212,7 +246,11 @@ impl Iterator for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T, A> { +impl DoubleEndedIterator + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn next_back(&mut self) -> Option { if self.remaining == 0 { @@ -225,7 +263,15 @@ impl DoubleEndedIterator for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T, A> {} +impl ExactSizeIterator + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T, A> {} +impl FusedIterator for Drain<'_, T, A, COOP_PREFERRED> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: +{ +} diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index e54880e865230..1c3bedd21e7e2 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -1,5 +1,5 @@ -use core::fmt; use core::iter::{FusedIterator, TrustedLen}; +use core::{alloc, fmt}; use crate::alloc::{Allocator, Global}; @@ -17,29 +17,41 @@ use super::VecDeque; pub struct IntoIter< T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> { - inner: VecDeque, + const COOP_PREFERRED: bool = true, +> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ + inner: VecDeque, } -impl IntoIter { - pub(super) fn new(inner: VecDeque) -> Self { +impl IntoIter +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ + pub(super) fn new(inner: VecDeque) -> Self { IntoIter { inner } } - pub(super) fn into_vecdeque(self) -> VecDeque { + pub(super) fn into_vecdeque(self) -> VecDeque { self.inner } } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for IntoIter { +impl fmt::Debug for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.inner).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +impl Iterator for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ type Item = T; #[inline] @@ -55,7 +67,10 @@ impl Iterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ #[inline] fn next_back(&mut self) -> Option { self.inner.pop_back() @@ -63,14 +78,23 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { +impl ExactSizeIterator for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ fn is_empty(&self) -> bool { self.inner.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter where + [(); alloc::co_alloc_metadata_num_slots::()]: +{ +} #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for IntoIter {} +unsafe impl TrustedLen for IntoIter where + [(); alloc::co_alloc_metadata_num_slots::()]: +{ +} diff --git a/library/alloc/src/collections/vec_deque/macros.rs b/library/alloc/src/collections/vec_deque/macros.rs index 5c7913073fe87..77885e6811a3b 100644 --- a/library/alloc/src/collections/vec_deque/macros.rs +++ b/library/alloc/src/collections/vec_deque/macros.rs @@ -1,9 +1,10 @@ macro_rules! __impl_slice_eq1 { ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] - impl PartialEq<$rhs> for $lhs + impl PartialEq<$rhs> for $lhs where T: PartialEq, + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, $($constraints)* { fn eq(&self, other: &$rhs) -> bool { diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c955db46d29fe..0b1b7b1138969 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -5,8 +5,10 @@ //! are not required to be copyable, and the queue will be sendable if the //! contained type is sendable. +#![feature(global_co_alloc)] #![stable(feature = "rust1", since = "1.0.0")] - +use crate::vec::DEFAULT_COOP_PREFERRED; +use core::alloc; use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{Hash, Hasher}; @@ -94,7 +96,10 @@ mod tests; pub struct VecDeque< T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> { + const COOP_PREFERRED: bool = DEFAULT_COOP_PREFERRED, +> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ // `self[0]`, if it exists, is `buf[head]`. // `head < buf.capacity()`, unless `buf.capacity() == 0` when `head == 0`. head: usize, @@ -102,11 +107,15 @@ pub struct VecDeque< // if `len == 0`, the exact value of `head` is unimportant. // if `T` is zero-Sized, then `self.len <= usize::MAX`, otherwise `self.len <= isize::MAX as usize`. len: usize, - buf: RawVec, + buf: RawVec, } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for VecDeque { +impl Clone + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn clone(&self) -> Self { let mut deq = Self::with_capacity_in(self.len(), self.allocator().clone()); deq.extend(self.iter().cloned()); @@ -120,7 +129,11 @@ impl Clone for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque { +unsafe impl<#[may_dangle] T, A: Allocator, const COOP_PREFERRED: bool> Drop + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn drop(&mut self) { /// Runs the destructor for all items in the slice when it gets dropped (normally or /// during unwinding). @@ -145,15 +158,21 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for VecDeque { +impl Default for VecDeque +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Creates an empty deque. #[inline] - fn default() -> VecDeque { + fn default() -> VecDeque { VecDeque::new() } } -impl VecDeque { +impl VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Marginally more convenient #[inline] fn ptr(&self) -> *mut T { @@ -442,12 +461,18 @@ impl VecDeque { mut iter: impl Iterator, len: usize, ) -> usize { - struct Guard<'a, T, A: Allocator> { - deque: &'a mut VecDeque, + struct Guard<'a, T, A: Allocator, const COOP_PREFERRED: bool> + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { + deque: &'a mut VecDeque, written: usize, } - impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> { + impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> Drop for Guard<'a, T, A, COOP_PREFERRED> + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { fn drop(&mut self) { self.deque.len += self.written; } @@ -525,7 +550,10 @@ impl VecDeque { } } -impl VecDeque { +impl VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Creates an empty deque. /// /// # Examples @@ -539,7 +567,7 @@ impl VecDeque { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_vec_deque_new", since = "CURRENT_RUSTC_VERSION")] #[must_use] - pub const fn new() -> VecDeque { + pub const fn new() -> VecDeque { // FIXME: This should just be `VecDeque::new_in(Global)` once that hits stable. VecDeque { head: 0, len: 0, buf: RawVec::NEW } } @@ -556,12 +584,15 @@ impl VecDeque { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] - pub fn with_capacity(capacity: usize) -> VecDeque { + pub fn with_capacity(capacity: usize) -> VecDeque { Self::with_capacity_in(capacity, Global) } } -impl VecDeque { +impl VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Creates an empty deque. /// /// # Examples @@ -573,7 +604,7 @@ impl VecDeque { /// ``` #[inline] #[unstable(feature = "allocator_api", issue = "32838")] - pub const fn new_in(alloc: A) -> VecDeque { + pub const fn new_in(alloc: A) -> VecDeque { VecDeque { head: 0, len: 0, buf: RawVec::new_in(alloc) } } @@ -587,7 +618,7 @@ impl VecDeque { /// let deque: VecDeque = VecDeque::with_capacity(10); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { + pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) } } @@ -2594,7 +2625,10 @@ impl VecDeque { } } -impl VecDeque { +impl VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Modifies the deque in-place so that `len()` is equal to new_len, /// either by removing excess elements from the back or by appending clones of `value` /// to the back. @@ -2639,7 +2673,11 @@ fn wrap_index(logical_index: usize, capacity: usize) -> usize { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for VecDeque { +impl PartialEq + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn eq(&self, other: &Self) -> bool { if self.len != other.len() { return false; @@ -2678,24 +2716,34 @@ impl PartialEq for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for VecDeque {} +impl Eq for VecDeque where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: +{ +} -__impl_slice_eq1! { [] VecDeque, Vec, } -__impl_slice_eq1! { [] VecDeque, &[U], } -__impl_slice_eq1! { [] VecDeque, &mut [U], } -__impl_slice_eq1! { [const N: usize] VecDeque, [U; N], } -__impl_slice_eq1! { [const N: usize] VecDeque, &[U; N], } -__impl_slice_eq1! { [const N: usize] VecDeque, &mut [U; N], } +__impl_slice_eq1! { [] VecDeque, Vec, } +__impl_slice_eq1! { [] VecDeque, &[U], } +__impl_slice_eq1! { [] VecDeque, &mut [U], } +__impl_slice_eq1! { [const N: usize] VecDeque, [U; N], } +__impl_slice_eq1! { [const N: usize] VecDeque, &[U; N], } +__impl_slice_eq1! { [const N: usize] VecDeque, &mut [U; N], } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for VecDeque { +impl PartialOrd + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn partial_cmp(&self, other: &Self) -> Option { self.iter().partial_cmp(other.iter()) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for VecDeque { +impl Ord for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other.iter()) @@ -2703,7 +2751,10 @@ impl Ord for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Hash for VecDeque { +impl Hash for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn hash(&self, state: &mut H) { state.write_length_prefix(self.len); // It's not possible to use Hash::hash_slice on slices @@ -2717,7 +2768,10 @@ impl Hash for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Index for VecDeque { +impl Index for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Output = T; #[inline] @@ -2727,7 +2781,10 @@ impl Index for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for VecDeque { +impl IndexMut for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, index: usize) -> &mut T { self.get_mut(index).expect("Out of bounds access") @@ -2735,14 +2792,20 @@ impl IndexMut for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for VecDeque { - fn from_iter>(iter: I) -> VecDeque { +impl FromIterator for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ + fn from_iter>(iter: I) -> VecDeque { SpecFromIter::spec_from_iter(iter.into_iter()) } } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for VecDeque { +impl IntoIterator for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = T; type IntoIter = IntoIter; @@ -2754,7 +2817,11 @@ impl IntoIterator for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a VecDeque { +impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> IntoIterator + for &'a VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -2764,7 +2831,11 @@ impl<'a, T, A: Allocator> IntoIterator for &'a VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a mut VecDeque { +impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> IntoIterator + for &'a mut VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = &'a mut T; type IntoIter = IterMut<'a, T>; @@ -2774,7 +2845,10 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for VecDeque { +impl Extend for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn extend>(&mut self, iter: I) { >::spec_extend(self, iter.into_iter()); } @@ -2791,7 +2865,11 @@ impl Extend for VecDeque { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque { +impl<'a, T: 'a + Copy, A: Allocator, const COOP_PREFERRED: bool> Extend<&'a T> + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn extend>(&mut self, iter: I) { self.spec_extend(iter.into_iter()); } @@ -2808,14 +2886,22 @@ impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for VecDeque { +impl fmt::Debug + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } } #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] -impl From> for VecDeque { +impl From> + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Turn a [`Vec`] into a [`VecDeque`]. /// /// [`Vec`]: crate::vec::Vec @@ -2825,14 +2911,23 @@ impl From> for VecDeque { /// conversion. This isn't yet a guarantee though, and /// shouldn't be relied on. #[inline] - fn from(other: Vec) -> Self { + fn from(other: Vec) -> Self + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::( + OTHER_COOP_PREFERRED, + )]:, + { let (ptr, len, cap, alloc) = other.into_raw_parts_with_alloc(); Self { head: 0, len, buf: unsafe { RawVec::from_raw_parts_in(ptr, cap, alloc) } } } } #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] -impl From> for Vec { +impl From> + for Vec +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Turn a [`VecDeque`] into a [`Vec`]. /// /// [`Vec`]: crate::vec::Vec @@ -2862,7 +2957,9 @@ impl From> for Vec { /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]); /// assert_eq!(vec.as_ptr(), ptr); /// ``` - fn from(mut other: VecDeque) -> Self { + fn from( + mut other: VecDeque, + ) -> Self { other.make_contiguous(); unsafe { @@ -2875,13 +2972,18 @@ impl From> for Vec { if other.head != 0 { ptr::copy(buf.add(other.head), buf, len); } + // @FIXME: COOP Vec::from_raw_parts_in(buf, len, cap, alloc) } } } #[stable(feature = "std_collections_from_array", since = "1.56.0")] -impl From<[T; N]> for VecDeque { +impl From<[T; N]> + for VecDeque +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts a `[T; N]` into a `VecDeque`. /// /// ``` @@ -2897,6 +2999,7 @@ impl From<[T; N]> for VecDeque { if !::IS_ZST { // SAFETY: VecDeque::with_capacity ensures that there is enough capacity. unsafe { + // @FIXME for COOP_PREFERRED: ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N); } } diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs index dccf40ccb38aa..973de88ffb172 100644 --- a/library/alloc/src/collections/vec_deque/spec_extend.rs +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -1,5 +1,8 @@ +#![feature(min_specialization)] + use crate::alloc::Allocator; use crate::vec; +use core::alloc; use core::iter::TrustedLen; use core::slice; @@ -10,9 +13,11 @@ pub(super) trait SpecExtend { fn spec_extend(&mut self, iter: I); } -impl SpecExtend for VecDeque +impl SpecExtend + for VecDeque where I: Iterator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { default fn spec_extend(&mut self, mut iter: I) { // This function should be the moral equivalent of: @@ -22,7 +27,12 @@ where // } // May only be called if `deque.len() < deque.capacity()` - unsafe fn push_unchecked(deque: &mut VecDeque, element: T) { + unsafe fn push_unchecked( + deque: &mut VecDeque, + element: T, + ) where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { // SAFETY: Because of the precondition, it's guaranteed that there is space // in the logical array after the last element. unsafe { deque.buffer_write(deque.to_physical_idx(deque.len), element) }; @@ -49,9 +59,11 @@ where } } -impl SpecExtend for VecDeque +impl SpecExtend + for VecDeque where I: TrustedLen, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { default fn spec_extend(&mut self, iter: I) { // This is the case for a TrustedLen iterator. @@ -84,7 +96,11 @@ where } } -impl SpecExtend> for VecDeque { +impl SpecExtend> + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn spec_extend(&mut self, mut iterator: vec::IntoIter) { let slice = iterator.as_slice(); self.reserve(slice.len()); @@ -97,19 +113,23 @@ impl SpecExtend> for VecDeque { } } -impl<'a, T: 'a, I, A: Allocator> SpecExtend<&'a T, I> for VecDeque +impl<'a, T: 'a, I, A: Allocator, const COOP_PREFERRED: bool> SpecExtend<&'a T, I> + for VecDeque where I: Iterator, T: Copy, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { default fn spec_extend(&mut self, iterator: I) { self.spec_extend(iterator.copied()) } } -impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for VecDeque +impl<'a, T: 'a, A: Allocator, const COOP_PREFERRED: bool> SpecExtend<&'a T, slice::Iter<'a, T>> + for VecDeque where T: Copy, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { let slice = iterator.as_slice(); diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs index 7650492ebdad1..086a1fa74566c 100644 --- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -1,13 +1,17 @@ use super::{IntoIter, VecDeque}; +use crate::alloc::Allocator; +use core::alloc; /// Specialization trait used for `VecDeque::from_iter` pub(super) trait SpecFromIter { fn spec_from_iter(iter: I) -> Self; } -impl SpecFromIter for VecDeque +impl SpecFromIter + for VecDeque where I: Iterator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { default fn spec_from_iter(iterator: I) -> Self { // Since converting is O(1) now, just re-use the `Vec` logic for @@ -18,14 +22,22 @@ where } } -impl SpecFromIter> for VecDeque { +impl SpecFromIter> + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn spec_from_iter(iterator: crate::vec::IntoIter) -> Self { iterator.into_vecdeque() } } -impl SpecFromIter> for VecDeque { +impl SpecFromIter> + for VecDeque +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn spec_from_iter(iterator: IntoIter) -> Self { iterator.into_vecdeque() diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f6cbac005ff39..708af80ac8a1d 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -86,6 +86,7 @@ #![warn(deprecated_in_future)] #![warn(missing_debug_implementations)] #![warn(missing_docs)] +#![allow(incomplete_features)] #![allow(explicit_outlives_requirements)] #![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))] // @@ -122,6 +123,8 @@ #![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] +#![feature(generic_const_exprs)] +#![feature(global_co_alloc_meta)] #![feature(hasher_prefixfree_extras)] #![feature(inline_const)] #![feature(inplace_iteration)] @@ -176,9 +179,16 @@ #![feature(exclusive_range_pattern)] #![feature(fundamental)] #![cfg_attr(not(test), feature(generator_trait))] +#![feature(global_co_alloc)] +#![feature(global_co_alloc_short_term_pref)] #![feature(hashmap_internals)] #![feature(lang_items)] -#![feature(min_specialization)] +// When we used min_specialization instead of specialization, library/alloc/src/vec/mod.rs was failing with: +// - cannot specialize on predicate `the constant `core::alloc::co_alloc_metadata_num_slots::()` can be evaluated` +// - cannot specialize on predicate `[(); _] well-formed` +// - cannot specialize on predicate `the constant `core::alloc::co_alloc_metadata_num_slots::()` can be evaluated` +//#![feature(min_specialization)] +#![feature(specialization)] #![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_allow_const_fn_unstable)] @@ -256,3 +266,11 @@ pub mod vec; pub mod __export { pub use core::format_args; } + +use crate::alloc::Global; + +/// See also `core::alloc::co_alloc_metadata_num_slots_with_preference`. +#[unstable(feature = "global_co_alloc", issue = "none")] +pub const fn co_alloc_metadata_num_slots_with_preference_global(coop_preferred: bool) -> usize { + if Global::IS_CO_ALLOCATOR && coop_preferred { 1 } else { 0 } +} diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 5a10121bbbe4b..f74e876b6cb9c 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -1,6 +1,6 @@ #![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] -use core::alloc::LayoutError; +use core::alloc::{self, GlobalCoAllocMeta, LayoutError, PtrAndMeta}; use core::cmp; use core::intrinsics; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; @@ -14,6 +14,7 @@ use crate::alloc::{Allocator, Global, Layout}; use crate::boxed::Box; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind::*; +use crate::vec::DEFAULT_COOP_PREFERRED; #[cfg(test)] mod tests; @@ -49,13 +50,27 @@ enum AllocInit { /// `usize::MAX`. This means that you need to be careful when round-tripping this type with a /// `Box<[T]>`, since `capacity()` won't yield the length. #[allow(missing_debug_implementations)] -pub(crate) struct RawVec { +pub(crate) struct RawVec< + T, + A: Allocator = Global, + const COOP_PREFERRED: bool = DEFAULT_COOP_PREFERRED, +> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ ptr: Unique, cap: usize, alloc: A, + // As of v1.67.0, `cmp` for `TypeId` is not `const`, unfortunately: + //pub(crate) meta: [GlobalCoAllocMeta; {if core::any::TypeId::of::()==core::any::TypeId::of::() {1} else {0}}], + //pub(crate) meta: [GlobalCoAllocMeta; mem::size_of::()], + pub(crate) metas: [GlobalCoAllocMeta; + alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)], } -impl RawVec { +impl RawVec +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// HACK(Centril): This exists because stable `const fn` can only call stable `const fn`, so /// they cannot call `Self::new()`. /// @@ -102,7 +117,10 @@ impl RawVec { } } -impl RawVec { +impl RawVec +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ // Tiny Vecs are dumb. Skip to: // - 8 if the element size is 1, because any heap allocators is likely // to round up a request of less than 8 bytes to at least 8 bytes. @@ -120,7 +138,13 @@ impl RawVec { /// the returned `RawVec`. pub const fn new_in(alloc: A) -> Self { // `cap: 0` means "unallocated". zero-sized types are ignored. - Self { ptr: Unique::dangling(), cap: 0, alloc } + Self { + ptr: Unique::dangling(), + cap: 0, + alloc, + metas: [GlobalCoAllocMeta {/*one: 1*/ /* , two: 2, three: 3, four: 4*/}; + alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)], + } } /// Like `with_capacity`, but parameterized over the choice of @@ -197,6 +221,10 @@ impl RawVec { ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, cap: capacity, alloc, + metas: [GlobalCoAllocMeta {/*one: 1*/ /*, two: 2, three: 3, four: 4*/}; + alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )], } } } @@ -213,7 +241,13 @@ impl RawVec { /// guaranteed. #[inline] pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self { - Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap: capacity, alloc } + Self { + ptr: unsafe { Unique::new_unchecked(ptr) }, + cap: capacity, + alloc, + metas: [GlobalCoAllocMeta {/*one: 1*/ /*, two: 2, three: 3, four: 4*/}; + alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)], + } } /// Gets a raw pointer to the start of the allocation. Note that this is @@ -277,11 +311,13 @@ impl RawVec { // handle_reserve behind a call, while making sure that this function is likely to be // inlined as just a comparison and a call if the comparison fails. #[cold] - fn do_reserve_and_handle( - slf: &mut RawVec, + fn do_reserve_and_handle( + slf: &mut RawVec, len: usize, additional: usize, - ) { + ) where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { handle_reserve(slf.grow_amortized(len, additional)); } @@ -354,7 +390,10 @@ impl RawVec { } } -impl RawVec { +impl RawVec +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Returns if the buffer needs to grow to fulfill the needed extra capacity. /// Mainly used to make inlining reserve-calls possible without inlining `grow`. fn needs_to_grow(&self, len: usize, additional: usize) -> bool { @@ -472,11 +511,20 @@ where memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }.into()) } -unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { +unsafe impl<#[may_dangle] T, A: Allocator, const COOP_PREFERRED: bool> Drop + for RawVec +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. - fn drop(&mut self) { + default fn drop(&mut self) { if let Some((ptr, layout)) = self.current_memory() { - unsafe { self.alloc.deallocate(ptr, layout) } + if A::IS_CO_ALLOCATOR && COOP_PREFERRED { + let meta = self.metas[0]; + unsafe { self.alloc.co_deallocate(PtrAndMeta { ptr, meta }, layout) } + } else { + unsafe { self.alloc.deallocate(ptr, layout) } + } } } } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 80a5913daa6e0..ac0f50f68d9db 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1987,7 +1987,10 @@ impl From> for Rc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Rc<[T]> { +impl From> for Rc<[T]> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Allocate a reference-counted slice and move `v`'s items into it. /// /// # Example @@ -1999,7 +2002,10 @@ impl From> for Rc<[T]> { /// assert_eq!(vec![1, 2, 3], *shared); /// ``` #[inline] - fn from(mut v: Vec) -> Rc<[T]> { + fn from(mut v: Vec) -> Rc<[T]> + where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, + { unsafe { let rc = Rc::copy_from_slice(&v); // Allow the Vec to free its memory, but not destroy its contents @@ -2120,6 +2126,7 @@ trait ToRcSlice: Iterator + Sized { fn to_rc_slice(self) -> Rc<[T]>; } +// COOP_NOT_POSSIBLE #[cfg(not(no_global_oom_handling))] impl> ToRcSlice for I { default fn to_rc_slice(self) -> Rc<[T]> { diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 4cfb2def09804..7515f71e57217 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -92,7 +92,14 @@ pub(crate) mod hack { // We shouldn't add inline attribute to this since this is used in // `vec!` macro mostly and causes perf regression. See #71204 for // discussion and perf results. - pub fn into_vec(b: Box<[T], A>) -> Vec { + pub fn into_vec( + b: Box<[T], A>, + ) -> Vec + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { unsafe { let len = b.len(); let (b, alloc) = Box::into_raw_with_allocator(b); @@ -102,26 +109,58 @@ pub(crate) mod hack { #[cfg(not(no_global_oom_handling))] #[inline] - pub fn to_vec(s: &[T], alloc: A) -> Vec { + pub fn to_vec( + s: &[T], + alloc: A, + ) -> Vec + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { T::to_vec(s, alloc) } #[cfg(not(no_global_oom_handling))] pub trait ConvertVec { - fn to_vec(s: &[Self], alloc: A) -> Vec + fn to_vec( + s: &[Self], + alloc: A, + ) -> Vec where - Self: Sized; + Self: Sized, + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:; } #[cfg(not(no_global_oom_handling))] impl ConvertVec for T { #[inline] - default fn to_vec(s: &[Self], alloc: A) -> Vec { - struct DropGuard<'a, T, A: Allocator> { - vec: &'a mut Vec, + default fn to_vec( + s: &[Self], + alloc: A, + ) -> Vec + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { + struct DropGuard<'a, T, A: Allocator, const COOP_PREFERRED: bool> + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { + vec: &'a mut Vec, num_init: usize, } - impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { + impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> Drop for DropGuard<'a, T, A, COOP_PREFERRED> + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { #[inline] fn drop(&mut self) { // SAFETY: @@ -153,7 +192,15 @@ pub(crate) mod hack { #[cfg(not(no_global_oom_handling))] impl ConvertVec for T { #[inline] - fn to_vec(s: &[Self], alloc: A) -> Vec { + fn to_vec( + s: &[Self], + alloc: A, + ) -> Vec + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { let mut v = Vec::with_capacity_in(s.len(), alloc); // SAFETY: // allocated above with the capacity of `s`, and initialize to `s.len()` in @@ -428,9 +475,15 @@ impl [T] { #[rustc_allow_incoherent_impl] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] - pub fn to_vec_in(&self, alloc: A) -> Vec + pub fn to_vec_in( + &self, + alloc: A, + ) -> Vec where T: Clone, + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, { // N.B., see the `hack` module in this file for more details. hack::to_vec(self, alloc) @@ -453,7 +506,14 @@ impl [T] { #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn into_vec(self: Box) -> Vec { + pub fn into_vec( + self: Box, + ) -> Vec + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { // N.B., see the `hack` module in this file for more details. hack::into_vec(self) } @@ -697,6 +757,7 @@ pub trait Join { fn join(slice: &Self, sep: Separator) -> Self::Output; } +// COOP_NOT_POSSIBLE #[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Concat for [V] { @@ -712,6 +773,7 @@ impl> Concat for [V] { } } +// COOP_NOT_POSSIBLE #[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Join<&T> for [V] { @@ -735,10 +797,11 @@ impl> Join<&T> for [V] { } } +// COOP_NOT_POSSIBLE #[cfg(not(no_global_oom_handling))] #[unstable(feature = "slice_concat_ext", issue = "27747")] impl> Join<&[T]> for [V] { - type Output = Vec; + type Output = Vec; fn join(slice: &Self, sep: &[T]) -> Vec { let mut iter = slice.iter(); @@ -764,19 +827,26 @@ impl> Join<&[T]> for [V] { //////////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -impl Borrow<[T]> for Vec { +impl Borrow<[T]> for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn borrow(&self) -> &[T] { &self[..] } } #[stable(feature = "rust1", since = "1.0.0")] -impl BorrowMut<[T]> for Vec { +impl BorrowMut<[T]> for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn borrow_mut(&mut self) -> &mut [T] { &mut self[..] } } +// COOP_NOT_POSSIBLE #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for [T] { diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index b28d20cda179e..ccb53aa01f46a 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -14,6 +14,8 @@ use core::ptr; use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher}; use core::unicode::conversions; +use crate::alloc; +use crate::alloc::Global; use crate::borrow::ToOwned; use crate::boxed::Box; use crate::slice::{Concat, Join, SliceIndex}; @@ -126,11 +128,15 @@ macro_rules! copy_slice_and_advance { // [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 +fn join_generic_copy( + slice: &[S], + sep: &[T], +) -> Vec where T: Copy, B: AsRef<[T]> + ?Sized, S: Borrow, + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, { let sep_len = sep.len(); let mut iter = slice.iter(); diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 24f1b3a1c8750..78d40306cd90a 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -41,7 +41,11 @@ //! ``` #![stable(feature = "rust1", since = "1.0.0")] +#![feature(global_co_alloc_plvec)] +use crate::alloc::Global; + +use crate::vec::PlVec; #[cfg(not(no_global_oom_handling))] use core::char::{decode_utf16, REPLACEMENT_CHARACTER}; use core::error::Error; @@ -71,6 +75,7 @@ use crate::str::{self, from_utf8_unchecked_mut, Chars, Utf8Error}; #[cfg(not(no_global_oom_handling))] use crate::str::{from_boxed_utf8_unchecked, FromStr}; use crate::vec::Vec; +use crate::vec::DEFAULT_COOP_PREFERRED; /// A UTF-8–encoded, growable string. /// @@ -364,8 +369,11 @@ use crate::vec::Vec; #[derive(PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), lang = "String")] -pub struct String { - vec: Vec, +pub struct String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + vec: Vec, } /// A possible error value when converting a `String` from a UTF-8 byte vector. @@ -405,7 +413,7 @@ pub struct String { #[cfg_attr(not(no_global_oom_handling), derive(Clone))] #[derive(Debug, PartialEq, Eq)] pub struct FromUtf8Error { - bytes: Vec, + bytes: PlVec, error: Utf8Error, } @@ -429,7 +437,10 @@ pub struct FromUtf8Error { #[derive(Debug)] pub struct FromUtf16Error(()); -impl String { +impl String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Creates a new empty `String`. /// /// Given that the `String` is empty, this will not allocate any initial @@ -452,7 +463,7 @@ impl String { #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] - pub const fn new() -> String { + pub const fn new() -> String { String { vec: Vec::new() } } @@ -497,7 +508,7 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] - pub fn with_capacity(capacity: usize) -> String { + pub fn with_capacity(capacity: usize) -> String { String { vec: Vec::with_capacity(capacity) } } @@ -507,7 +518,10 @@ impl String { // NB see the slice::hack module in slice.rs for more information #[inline] #[cfg(test)] - pub fn from_str(_: &str) -> String { + pub fn from_str(_: &str) -> String + where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, + { panic!("not available with cfg(test)"); } @@ -569,7 +583,7 @@ impl String { /// [`into_bytes`]: String::into_bytes #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf8(vec: Vec) -> Result { + pub fn from_utf8(vec: Vec) -> Result { match str::from_utf8(&vec) { Ok(..) => Ok(String { vec }), Err(e) => Err(FromUtf8Error { bytes: vec, error: e }), @@ -679,7 +693,7 @@ impl String { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf16(v: &[u16]) -> Result { + pub fn from_utf16(v: &[u16]) -> Result, FromUtf16Error> { // This isn't done via collect::>() for performance reasons. // FIXME: the function can be simplified again when #48994 is closed. let mut ret = String::with_capacity(v.len()); @@ -721,7 +735,7 @@ impl String { #[must_use] #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf16_lossy(v: &[u16]) -> String { + pub fn from_utf16_lossy(v: &[u16]) -> String { decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect() } @@ -807,7 +821,11 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { + pub unsafe fn from_raw_parts( + buf: *mut u8, + length: usize, + capacity: usize, + ) -> String { unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } } @@ -842,7 +860,9 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_utf8_unchecked(bytes: Vec) -> String { + pub unsafe fn from_utf8_unchecked( + bytes: Vec, + ) -> String { String { vec: bytes } } @@ -863,7 +883,10 @@ impl String { #[inline] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_bytes(self) -> Vec { + pub fn into_bytes(self) -> Vec + where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, + { self.vec } @@ -1610,7 +1633,10 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { + pub unsafe fn as_mut_vec(&mut self) -> &mut Vec + where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, + { &mut self.vec } @@ -1684,7 +1710,10 @@ impl String { #[inline] #[stable(feature = "string_split_off", since = "1.16.0")] #[must_use = "use `.truncate()` if you don't need the other half"] - pub fn split_off(&mut self, at: usize) -> String { + pub fn split_off(&mut self, at: usize) -> String + where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, + { assert!(self.is_char_boundary(at)); let other = self.vec.split_off(at); unsafe { String::from_utf8_unchecked(other) } @@ -1921,7 +1950,10 @@ impl FromUtf8Error { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_bytes(self) -> Vec { + pub fn into_bytes(self) -> Vec + where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, + { self.bytes } @@ -1987,7 +2019,10 @@ impl Error for FromUtf16Error { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for String { +impl Clone for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn clone(&self) -> Self { String { vec: self.vec.clone() } } @@ -1999,8 +2034,11 @@ impl Clone for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for String { - fn from_iter>(iter: I) -> String { +impl FromIterator for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + fn from_iter>(iter: I) -> String { let mut buf = String::new(); buf.extend(iter); buf @@ -2009,8 +2047,11 @@ impl FromIterator for 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 { +impl<'a, const COOP_PREFERRED: bool> FromIterator<&'a char> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + fn from_iter>(iter: I) -> String { let mut buf = String::new(); buf.extend(iter); buf @@ -2019,8 +2060,11 @@ impl<'a> FromIterator<&'a char> for 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 { +impl<'a, const COOP_PREFERRED: bool> FromIterator<&'a str> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + fn from_iter>(iter: I) -> String { let mut buf = String::new(); buf.extend(iter); buf @@ -2029,8 +2073,13 @@ impl<'a> FromIterator<&'a str> for 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 { +impl FromIterator> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + fn from_iter>>( + iter: I, + ) -> String { let mut iterator = iter.into_iter(); // Because we're iterating over `String`s, we can avoid at least @@ -2048,8 +2097,11 @@ impl FromIterator for 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 { +impl FromIterator> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + fn from_iter>>(iter: I) -> String { let mut buf = String::new(); buf.extend(iter); buf @@ -2058,8 +2110,11 @@ impl FromIterator> for 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 { +impl<'a, const COOP_PREFERRED: bool> FromIterator> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + fn from_iter>>(iter: I) -> String { let mut iterator = iter.into_iter(); // Because we're iterating over CoWs, we can (potentially) avoid at least @@ -2078,7 +2133,10 @@ impl<'a> FromIterator> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for String { +impl Extend for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn extend>(&mut self, iter: I) { let iterator = iter.into_iter(); let (lower_bound, _) = iterator.size_hint(); @@ -2099,7 +2157,10 @@ impl Extend for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a> Extend<&'a char> for String { +impl<'a, const COOP_PREFERRED: bool> Extend<&'a char> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } @@ -2117,7 +2178,10 @@ impl<'a> Extend<&'a char> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Extend<&'a str> for String { +impl<'a, const COOP_PREFERRED: bool> Extend<&'a str> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(s)); } @@ -2138,7 +2202,10 @@ impl Extend> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "extend_string", since = "1.4.0")] -impl Extend for String { +impl Extend for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } @@ -2151,7 +2218,10 @@ impl Extend for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "herd_cows", since = "1.19.0")] -impl<'a> Extend> for String { +impl<'a, const COOP_PREFERRED: bool> Extend> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn extend>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } @@ -2174,7 +2244,10 @@ impl<'a> Extend> for String { reason = "API not fully fleshed out and ready to be stabilized", issue = "27721" )] -impl<'a, 'b> Pattern<'a> for &'b String { +impl<'a, 'b, const COOP_PREFERRED: bool> Pattern<'a> for &'b String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Searcher = <&'b str as Pattern<'a>>::Searcher; fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher { @@ -2208,13 +2281,16 @@ impl<'a, 'b> Pattern<'a> for &'b String { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for String { +impl PartialEq for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] - fn eq(&self, other: &String) -> bool { + fn eq(&self, other: &String) -> bool { PartialEq::eq(&self[..], &other[..]) } #[inline] - fn ne(&self, other: &String) -> bool { + fn ne(&self, other: &String) -> bool { PartialEq::ne(&self[..], &other[..]) } } @@ -2249,6 +2325,7 @@ macro_rules! impl_eq { }; } +// @FIXME for COOP_PREFERRED impl_eq! { String, str } impl_eq! { String, &'a str } #[cfg(not(no_global_oom_handling))] @@ -2260,16 +2337,22 @@ impl_eq! { Cow<'a, str>, String } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl const Default for String { +impl const Default for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Creates an empty `String`. #[inline] - fn default() -> String { + fn default() -> String { String::new() } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for String { +impl fmt::Display for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) @@ -2277,7 +2360,10 @@ impl fmt::Display for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for String { +impl fmt::Debug for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) @@ -2285,7 +2371,10 @@ impl fmt::Debug for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for String { +impl hash::Hash for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn hash(&self, hasher: &mut H) { (**self).hash(hasher) @@ -2331,11 +2420,14 @@ impl hash::Hash for String { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl Add<&str> for String { - type Output = String; +impl Add<&str> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + type Output = String; #[inline] - fn add(mut self, other: &str) -> String { + fn add(mut self, other: &str) -> String { self.push_str(other); self } @@ -2346,7 +2438,10 @@ impl Add<&str> for 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 { +impl AddAssign<&str> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn add_assign(&mut self, other: &str) { self.push_str(other); @@ -2354,7 +2449,10 @@ impl AddAssign<&str> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { +impl ops::Index> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Output = str; #[inline] @@ -2363,7 +2461,10 @@ impl ops::Index> for String { } } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { +impl ops::Index> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Output = str; #[inline] @@ -2372,7 +2473,10 @@ impl ops::Index> for String { } } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { +impl ops::Index> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Output = str; #[inline] @@ -2381,7 +2485,10 @@ impl ops::Index> for String { } } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for String { +impl ops::Index for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Output = str; #[inline] @@ -2390,7 +2497,10 @@ impl ops::Index for String { } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::Index> for String { +impl ops::Index> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Output = str; #[inline] @@ -2399,7 +2509,10 @@ impl ops::Index> for String { } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::Index> for String { +impl ops::Index> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Output = str; #[inline] @@ -2409,42 +2522,62 @@ impl ops::Index> for String { } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, index: ops::Range) -> &mut str { &mut self[..][index] } } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { &mut self[..][index] } } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { &mut self[..][index] } } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut for String { +impl ops::IndexMut for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str { unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> + for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { IndexMut::index_mut(&mut **self, index) } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> + for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { IndexMut::index_mut(&mut **self, index) @@ -2452,7 +2585,10 @@ impl ops::IndexMut> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Deref for String { +impl ops::Deref for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Target = str; #[inline] @@ -2462,7 +2598,10 @@ impl ops::Deref for String { } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::DerefMut for String { +impl ops::DerefMut for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } @@ -2479,10 +2618,13 @@ pub type ParseError = core::convert::Infallible; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl FromStr for String { +impl FromStr for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Err = core::convert::Infallible; #[inline] - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result, Self::Err> { Ok(String::from(s)) } } @@ -2497,7 +2639,10 @@ impl FromStr for String { /// [`Display`]: fmt::Display #[cfg_attr(not(test), rustc_diagnostic_item = "ToString")] #[stable(feature = "rust1", since = "1.0.0")] -pub trait ToString { +pub trait ToString +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts the given value to a `String`. /// /// # Examples @@ -2512,7 +2657,7 @@ pub trait ToString { /// ``` #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] - fn to_string(&self) -> String; + fn to_string(&self) -> String; } /// # Panics @@ -2523,13 +2668,16 @@ pub trait ToString { /// 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 { +impl ToString for T +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ // A common guideline is to not inline generic functions. However, // removing `#[inline]` from this method causes non-negligible regressions. // See , the last attempt // to try to remove it. #[inline] - default fn to_string(&self) -> String { + default fn to_string(&self) -> String { let mut buf = String::new(); let mut formatter = core::fmt::Formatter::new(&mut buf); // Bypass format_args!() to avoid write_str with zero-length strs @@ -2550,9 +2698,12 @@ impl ToString for char { #[cfg(not(no_global_oom_handling))] #[stable(feature = "u8_to_string_specialization", since = "1.54.0")] -impl ToString for u8 { +impl ToString for u8 +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] - fn to_string(&self) -> String { + fn to_string(&self) -> String { let mut buf = String::with_capacity(3); let mut n = *self; if n >= 10 { @@ -2570,9 +2721,12 @@ impl ToString for u8 { #[cfg(not(no_global_oom_handling))] #[stable(feature = "i8_to_string_specialization", since = "1.54.0")] -impl ToString for i8 { +impl ToString for i8 +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] - fn to_string(&self) -> String { + fn to_string(&self) -> String { let mut buf = String::with_capacity(4); if self.is_negative() { buf.push('-'); @@ -2593,33 +2747,42 @@ impl ToString for i8 { #[cfg(not(no_global_oom_handling))] #[stable(feature = "str_to_string_specialization", since = "1.9.0")] -impl ToString for str { +impl ToString for str +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] - fn to_string(&self) -> String { + fn to_string(&self) -> String { String::from(self) } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")] -impl ToString for Cow<'_, str> { +impl ToString for Cow<'_, str> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] - fn to_string(&self) -> String { + fn to_string(&self) -> String { self[..].to_owned() } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_to_string_specialization", since = "1.17.0")] -impl ToString for String { +impl ToString for String { #[inline] - fn to_string(&self) -> String { + fn to_string(&self) -> String { self.to_owned() } } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef for String { +impl AsRef for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn as_ref(&self) -> &str { self @@ -2627,7 +2790,10 @@ impl AsRef for String { } #[stable(feature = "string_as_mut", since = "1.43.0")] -impl AsMut for String { +impl AsMut for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn as_mut(&mut self) -> &mut str { self @@ -2635,7 +2801,10 @@ impl AsMut for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[u8]> for String { +impl AsRef<[u8]> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() @@ -2644,36 +2813,45 @@ impl AsRef<[u8]> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl From<&str> for String { +impl From<&str> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts a `&str` into a [`String`]. /// /// The result is allocated on the heap. #[inline] - fn from(s: &str) -> String { + fn from(s: &str) -> String { s.to_owned() } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "from_mut_str_for_string", since = "1.44.0")] -impl From<&mut str> for String { +impl From<&mut str> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts a `&mut str` into a [`String`]. /// /// The result is allocated on the heap. #[inline] - fn from(s: &mut str) -> String { + fn from(s: &mut str) -> String { s.to_owned() } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "from_ref_string", since = "1.35.0")] -impl From<&String> for String { +impl From<&String> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts a `&String` into a [`String`]. /// /// This clones `s` and returns the clone. #[inline] - fn from(s: &String) -> String { + fn from(s: &String) -> String { s.clone() } } @@ -2703,7 +2881,10 @@ impl From> for String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_str", since = "1.20.0")] -impl From for Box { +impl From> for Box +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts the given [`String`] to a boxed `str` slice that is owned. /// /// # Examples @@ -2717,14 +2898,17 @@ impl From for Box { /// /// assert_eq!("hello world", s3) /// ``` - fn from(s: String) -> Box { + fn from(s: String) -> Box { s.into_boxed_str() } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_from_cow_str", since = "1.14.0")] -impl<'a> From> for String { +impl<'a, const COOP_PREFERRED: bool> From> for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts a clone-on-write string to an owned /// instance of [`String`]. /// @@ -2741,7 +2925,7 @@ impl<'a> From> for String { /// let owned: String = String::from(cow); /// assert_eq!(&owned[..], "eggplant"); /// ``` - fn from(s: Cow<'a, str>) -> String { + fn from(s: Cow<'a, str>) -> String { s.into_owned() } } @@ -2769,7 +2953,10 @@ impl<'a> From<&'a str> for Cow<'a, str> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From for Cow<'a, str> { +impl<'a, const COOP_PREFERRED: bool> From> for Cow<'a, str> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts a [`String`] into an [`Owned`] variant. /// No heap allocation is performed, and the string /// is not copied. @@ -2785,14 +2972,17 @@ impl<'a> From for Cow<'a, str> { /// /// [`Owned`]: crate::borrow::Cow::Owned "borrow::Cow::Owned" #[inline] - fn from(s: String) -> Cow<'a, str> { + fn from(s: String) -> Cow<'a, str> { Cow::Owned(s) } } #[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> { +impl<'a, const COOP_PREFERRED: bool> From<&'a String> for Cow<'a, str> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts a [`String`] reference into a [`Borrowed`] variant. /// No heap allocation is performed, and the string /// is not copied. @@ -2807,7 +2997,7 @@ impl<'a> From<&'a String> for Cow<'a, str> { /// /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" #[inline] - fn from(s: &'a String) -> Cow<'a, str> { + fn from(s: &'a String) -> Cow<'a, str> { Cow::Borrowed(s.as_str()) } } @@ -2830,14 +3020,20 @@ impl<'a, 'b> FromIterator<&'b str> for 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> { +impl<'a, const COOP_PREFERRED: bool> FromIterator> for Cow<'a, str> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ + fn from_iter>>(it: I) -> Cow<'a, str> { Cow::Owned(FromIterator::from_iter(it)) } } #[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] -impl From for Vec { +impl From> for Vec +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Converts the given [`String`] to a vector [`Vec`] that holds values of type [`u8`]. /// /// # Examples @@ -2852,14 +3048,17 @@ impl From for Vec { /// println!("{b}"); /// } /// ``` - fn from(string: String) -> Vec { + fn from(string: String) -> Vec { string.into_bytes() } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Write for String { +impl fmt::Write for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn write_str(&mut self, s: &str) -> fmt::Result { self.push_str(s); @@ -2880,9 +3079,12 @@ impl fmt::Write for String { /// /// [`drain`]: String::drain #[stable(feature = "drain", since = "1.6.0")] -pub struct Drain<'a> { +pub struct Drain<'a, const COOP_PREFERRED: bool = DEFAULT_COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Will be used as &'a mut String in the destructor - string: *mut String, + string: *mut String, /// Start of part to remove start: usize, /// End of part to remove @@ -2892,19 +3094,28 @@ pub struct Drain<'a> { } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_> { +impl fmt::Debug for Drain<'_, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain").field(&self.as_str()).finish() } } #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_> {} +unsafe impl Sync for Drain<'_, COOP_PREFERRED> where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]: +{ +} #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_> {} +unsafe impl Send for Drain<'_, COOP_PREFERRED> {} #[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_> { +impl Drop for Drain<'_, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn drop(&mut self) { unsafe { // Use Vec::drain. "Reaffirm" the bounds checks to avoid @@ -2917,7 +3128,10 @@ impl Drop for Drain<'_> { } } -impl<'a> Drain<'a> { +impl<'a, const COOP_PREFERRED: bool> Drain<'a, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Returns the remaining (sub)string of this iterator as a slice. /// /// # Examples @@ -2937,21 +3151,30 @@ impl<'a> Drain<'a> { } #[stable(feature = "string_drain_as_str", since = "1.55.0")] -impl<'a> AsRef for Drain<'a> { +impl<'a, const COOP_PREFERRED: bool> AsRef for Drain<'a, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn as_ref(&self) -> &str { self.as_str() } } #[stable(feature = "string_drain_as_str", since = "1.55.0")] -impl<'a> AsRef<[u8]> for Drain<'a> { +impl<'a, const COOP_PREFERRED: bool> AsRef<[u8]> for Drain<'a, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ fn as_ref(&self) -> &[u8] { self.as_str().as_bytes() } } #[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_> { +impl Iterator for Drain<'_, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ type Item = char; #[inline] @@ -2970,7 +3193,10 @@ impl Iterator for Drain<'_> { } #[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_> { +impl DoubleEndedIterator for Drain<'_, COOP_PREFERRED> +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ #[inline] fn next_back(&mut self) -> Option { self.iter.next_back() @@ -2978,11 +3204,17 @@ impl DoubleEndedIterator for Drain<'_> { } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_> {} +impl FusedIterator for Drain<'_, COOP_PREFERRED> where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]: +{ +} #[cfg(not(no_global_oom_handling))] #[stable(feature = "from_char_for_string", since = "1.46.0")] -impl From for String { +impl From for String +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Allocates an owned [`String`] from a single character. /// /// # Example diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index 541f99bcfaba4..88a5c1b8ce383 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -3,7 +3,7 @@ use core::fmt; use core::iter::{FusedIterator, TrustedLen}; use core::mem::{self, ManuallyDrop, SizedTypeProperties}; use core::ptr::{self, NonNull}; -use core::slice::{self}; +use core::{alloc, slice}; use super::Vec; @@ -23,24 +23,34 @@ pub struct Drain< 'a, T: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { + const COOP_PREFERRED: bool = { alloc::SHORT_TERM_VEC_PREFERS_COOP }, +> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Index of tail to preserve pub(super) tail_start: usize, /// Length of tail pub(super) tail_len: usize, /// Current remaining range to remove pub(super) iter: slice::Iter<'a, T>, - pub(super) vec: NonNull>, + pub(super) vec: NonNull>, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T, A> { +impl fmt::Debug + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() } } -impl<'a, T, A: Allocator> Drain<'a, T, A> { +impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> Drain<'a, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Returns the remaining items of this iterator as a slice. /// /// # Examples @@ -139,19 +149,35 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { } #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] -impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { +impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> AsRef<[T]> for Drain<'a, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn as_ref(&self) -> &[T] { self.as_slice() } } #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T, A> {} +unsafe impl Sync + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T, A> {} +unsafe impl Send + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T, A> { +impl Iterator for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = T; #[inline] @@ -165,7 +191,11 @@ impl Iterator for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T, A> { +impl DoubleEndedIterator + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn next_back(&mut self) -> Option { self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) @@ -173,12 +203,23 @@ impl DoubleEndedIterator for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T, A> { +impl Drop for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn drop(&mut self) { /// Moves back the un-`Drain`ed elements to restore the original `Vec`. - struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); - - impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + struct DropGuard<'r, 'a, T, A: Allocator, const COOP_PREFERRED: bool>( + &'r mut Drain<'a, T, A, COOP_PREFERRED>, + ) + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:; + + impl<'r, 'a, T, A: Allocator, const COOP_PREFERRED: bool> Drop + for DropGuard<'r, 'a, T, A, COOP_PREFERRED> + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { fn drop(&mut self) { if self.0.tail_len > 0 { unsafe { @@ -242,14 +283,26 @@ impl Drop for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T, A> { +impl ExactSizeIterator + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn is_empty(&self) -> bool { self.iter.is_empty() } } #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for Drain<'_, T, A> {} +unsafe impl TrustedLen + for Drain<'_, T, A, COOP_PREFERRED> +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T, A> {} +impl FusedIterator for Drain<'_, T, A, COOP_PREFERRED> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: +{ +} diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs index 8c03f1692d940..29cf29e2532d9 100644 --- a/library/alloc/src/vec/drain_filter.rs +++ b/library/alloc/src/vec/drain_filter.rs @@ -1,7 +1,6 @@ use crate::alloc::{Allocator, Global}; use core::mem::{self, ManuallyDrop}; -use core::ptr; -use core::slice; +use core::{alloc, ptr, slice}; use super::Vec; @@ -25,10 +24,12 @@ pub struct DrainFilter< T, F, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + const COOP_PREFERRED: bool = true, > where F: FnMut(&mut T) -> bool, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { - pub(super) vec: &'a mut Vec, + pub(super) vec: &'a mut Vec, /// The index of the item that will be inspected by the next call to `next`. pub(super) idx: usize, /// The number of items that have been drained (removed) thus far. @@ -45,9 +46,10 @@ pub struct DrainFilter< pub(super) panic_flag: bool, } -impl DrainFilter<'_, T, F, A> +impl DrainFilter<'_, T, F, A, COOP_PREFERRED> where F: FnMut(&mut T) -> bool, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { /// Returns a reference to the underlying allocator. #[unstable(feature = "allocator_api", issue = "32838")] @@ -113,9 +115,11 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Iterator for DrainFilter<'_, T, F, A> +impl Iterator + for DrainFilter<'_, T, F, A, COOP_PREFERRED> where F: FnMut(&mut T) -> bool, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { type Item = T; @@ -151,21 +155,26 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Drop for DrainFilter<'_, T, F, A> +impl Drop + for DrainFilter<'_, T, F, A, COOP_PREFERRED> where F: FnMut(&mut T) -> bool, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> + struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator, const COOP_PREFERRED: bool> where F: FnMut(&mut T) -> bool, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { - drain: &'b mut DrainFilter<'a, T, F, A>, + drain: &'b mut DrainFilter<'a, T, F, A, COOP_PREFERRED>, } - impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> + impl<'a, 'b, T, F, A: Allocator, const COOP_PREFERRED: bool> Drop + for BackshiftOnDrop<'a, 'b, T, F, A, COOP_PREFERRED> where F: FnMut(&mut T) -> bool, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { fn drop(&mut self) { unsafe { diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index b207b3210f1aa..e4d120317cfb2 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -4,8 +4,6 @@ use crate::alloc::{Allocator, Global}; #[cfg(not(no_global_oom_handling))] use crate::collections::VecDeque; use crate::raw_vec::RawVec; -use core::array; -use core::fmt; use core::iter::{ FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, }; @@ -15,6 +13,7 @@ use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::Deref; use core::ptr::{self, NonNull}; use core::slice::{self}; +use core::{alloc, array, fmt}; /// An iterator that moves out of a vector. /// @@ -32,7 +31,10 @@ use core::slice::{self}; pub struct IntoIter< T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> { + const COOP_PREFERRED: bool = { alloc::SHORT_TERM_VEC_PREFERS_COOP }, +> where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ pub(super) buf: NonNull, pub(super) phantom: PhantomData, pub(super) cap: usize, @@ -46,13 +48,20 @@ pub struct IntoIter< } #[stable(feature = "vec_intoiter_debug", since = "1.13.0")] -impl fmt::Debug for IntoIter { +impl fmt::Debug + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.as_slice()).finish() } } -impl IntoIter { +impl IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Returns the remaining items of this iterator as a slice. /// /// # Examples @@ -141,7 +150,7 @@ impl IntoIter { #[cfg(not(no_global_oom_handling))] #[inline] - pub(crate) fn into_vecdeque(self) -> VecDeque { + pub(crate) fn into_vecdeque(self) -> VecDeque { // Keep our `Drop` impl from dropping the elements and the allocator let mut this = ManuallyDrop::new(self); @@ -168,19 +177,35 @@ impl IntoIter { } #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] -impl AsRef<[T]> for IntoIter { +impl AsRef<[T]> for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn as_ref(&self) -> &[T] { self.as_slice() } } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for IntoIter {} +unsafe impl Send + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for IntoIter {} +unsafe impl Sync + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +impl Iterator for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = T; #[inline] @@ -294,7 +319,11 @@ impl Iterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn next_back(&mut self) -> Option { if self.end == self.ptr { @@ -335,17 +364,29 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { +impl ExactSizeIterator + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn is_empty(&self) -> bool { self.ptr == self.end } } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: +{ +} #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for IntoIter {} +unsafe impl TrustedLen + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[doc(hidden)] #[unstable(issue = "none", feature = "std_internals")] @@ -361,16 +402,22 @@ impl NonDrop for T {} #[unstable(issue = "none", feature = "std_internals")] // TrustedRandomAccess (without NoCoerce) must not be implemented because // subtypes/supertypes of `T` might not be `NonDrop` -unsafe impl TrustedRandomAccessNoCoerce for IntoIter +unsafe impl TrustedRandomAccessNoCoerce + for IntoIter where T: NonDrop, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { 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 { +impl Clone + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[cfg(not(test))] fn clone(&self) -> Self { self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter() @@ -382,17 +429,32 @@ impl Clone for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { +unsafe impl<#[may_dangle] T, A: Allocator, const COOP_PREFERRED: bool> Drop + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn drop(&mut self) { - struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); - - impl Drop for DropGuard<'_, T, A> { + struct DropGuard<'a, T, A: Allocator, const COOP_PREFERRED: bool>( + &'a mut IntoIter, + ) + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:; + + impl Drop for DropGuard<'_, T, A, COOP_PREFERRED> + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { fn drop(&mut self) { unsafe { // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec let alloc = ManuallyDrop::take(&mut self.0.alloc); // RawVec handles deallocation - let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); + let _ = RawVec::::from_raw_parts_in( + self.0.buf.as_ptr(), + self.0.cap, + alloc, + ); } } } @@ -410,11 +472,20 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { // also refer to the vec::in_place_collect module documentation to get an overview #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] -unsafe impl InPlaceIterable for IntoIter {} +unsafe impl InPlaceIterable + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ +} #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] -unsafe impl SourceIter for IntoIter { +unsafe impl SourceIter + for IntoIter +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Source = Self; #[inline] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1da73862d4a92..00d98099576bb 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -397,16 +397,52 @@ mod spec_extend; #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Vec")] #[rustc_insignificant_dtor] -pub struct Vec { - buf: RawVec, +pub struct Vec< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + //@FIXME: #[unstable(feature ="global_co_alloc_vec", issue="none")] + const COOP_PREFERRED: bool = DEFAULT_COOP_PREFERRED, +> where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ + buf: RawVec, len: usize, } +/// Default `Vec`, `DefVec`, `DecVeque`, `DefDecVeq` "cooperation" (`COOP_PREFERRED`) generic parameter. +#[unstable(feature = "global_co_alloc_def", issue = "none")] +pub const DEFAULT_COOP_PREFERRED: bool = true; + +#[unstable(feature = "global_co_alloc_covec", issue = "none")] +pub type CoVec = + Vec; + +/// "Plain" Vec. Not "cooperative" - not carrying extra data to assist the allocator. +#[unstable(feature = "global_co_alloc_plvec", issue = "none")] +pub type PlVec = + Vec; + +/// "Default" Vec. Either "cooperative" or not - as specified by `DEFAULT_COOP_PREFERRED`. The +/// difference to `Vec` (used without specifying `COOP_PREFERRED`): `DefVec` indicates that the +/// author considered using `CoVec` or `PlVec`, but left it to default instead. +#[unstable(feature = "global_co_alloc_defvec", issue = "none")] +pub type DefVec = + Vec; + +/// "Weighted cooperative" Vec. Weight means how much it wants to cooperate (with the allocator). 0 +/// = always pack; u8::MAX = always cooperate (if `Global` supports it). +/// @FIXME A `pub const` threshold. +#[unstable(feature = "global_co_alloc_vec", issue = "none")] +pub type WeVec = Vec 127 }>; + //////////////////////////////////////////////////////////////////////////////// // Inherent methods //////////////////////////////////////////////////////////////////////////////// -impl Vec { +impl Vec +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Constructs a new, empty `Vec`. /// /// The vector will not allocate until elements are pushed onto it. @@ -590,7 +626,10 @@ impl Vec { } } -impl Vec { +impl Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Constructs a new, empty `Vec`. /// /// The vector will not allocate until elements are pushed onto it. @@ -1601,14 +1640,24 @@ impl Vec { // This drop guard will be invoked when predicate or `drop` of element panicked. // It shifts unchecked elements to cover holes and `set_len` to the correct length. // In cases when predicate and `drop` never panick, it will be optimized out. - struct BackshiftOnDrop<'a, T, A: Allocator> { - v: &'a mut Vec, + struct BackshiftOnDrop<'a, T, A: Allocator, const VEC_IS_COOP: bool = true> + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + VEC_IS_COOP, + )]:, + { + v: &'a mut Vec, processed_len: usize, deleted_cnt: usize, original_len: usize, } - impl Drop for BackshiftOnDrop<'_, T, A> { + impl Drop for BackshiftOnDrop<'_, T, A, VEC_IS_COOP> + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + VEC_IS_COOP, + )]:, + { fn drop(&mut self) { if self.deleted_cnt > 0 { // SAFETY: Trailing unchecked items must be valid since we never touch them. @@ -1627,14 +1676,22 @@ impl Vec { } } - let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; + let mut g = BackshiftOnDrop:: { + v: self, + processed_len: 0, + deleted_cnt: 0, + original_len, + }; - fn process_loop( + fn process_loop( original_len: usize, f: &mut F, - g: &mut BackshiftOnDrop<'_, T, A>, + g: &mut BackshiftOnDrop<'_, T, A, VEC_IS_COOP>, ) where F: FnMut(&mut T) -> bool, + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + VEC_IS_COOP, + )]:, { while g.processed_len != original_len { // SAFETY: Unchecked element must be valid. @@ -1665,10 +1722,10 @@ impl Vec { } // Stage 1: Nothing was deleted. - process_loop::(original_len, &mut f, &mut g); + process_loop::(original_len, &mut f, &mut g); // Stage 2: Some elements were deleted. - process_loop::(original_len, &mut f, &mut g); + process_loop::(original_len, &mut f, &mut g); // All item are processed. This can be optimized to `set_len` by LLVM. drop(g); @@ -1727,7 +1784,12 @@ impl Vec { } /* INVARIANT: vec.len() > read >= write > write-1 >= 0 */ - struct FillGapOnDrop<'a, T, A: core::alloc::Allocator> { + struct FillGapOnDrop<'a, T, A: core::alloc::Allocator, const COOP_PREFERRED: bool> + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { /* Offset of the element we want to check if it is duplicate */ read: usize, @@ -1736,10 +1798,16 @@ impl Vec { write: usize, /* The Vec that would need correction if `same_bucket` panicked */ - vec: &'a mut Vec, + vec: &'a mut Vec, } - impl<'a, T, A: core::alloc::Allocator> Drop for FillGapOnDrop<'a, T, A> { + impl<'a, T, A: core::alloc::Allocator, const COOP_PREFERRED: bool> Drop + for FillGapOnDrop<'a, T, A, COOP_PREFERRED> + where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::( + COOP_PREFERRED, + )]:, + { fn drop(&mut self) { /* This code gets executed when `same_bucket` panics */ @@ -2332,7 +2400,10 @@ impl Vec { } } -impl Vec { +impl Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// /// If `new_len` is greater than `len`, the `Vec` is extended by the @@ -2431,7 +2502,10 @@ impl Vec { } } -impl Vec<[T; N], A> { +impl Vec<[T; N], A, COOP_PREFERRED> +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Takes a `Vec<[T; N]>` and flattens it into a `Vec`. /// /// # Panics @@ -2454,7 +2528,7 @@ impl Vec<[T; N], A> { /// assert_eq!(flattened.pop(), Some(6)); /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] - pub fn into_flattened(self) -> Vec { + pub fn into_flattened(self) -> Vec { let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); let (new_len, new_cap) = if T::IS_ZST { (len.checked_mul(N).expect("vec len overflow"), usize::MAX) @@ -2492,7 +2566,10 @@ impl ExtendWith for ExtendElement { } } -impl Vec { +impl Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[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) { @@ -2524,7 +2601,10 @@ impl Vec { } } -impl Vec { +impl Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Removes consecutive repeated elements in the vector according to the /// [`PartialEq`] trait implementation. /// @@ -2560,7 +2640,14 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[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 { +pub fn from_elem_in( + elem: T, + n: usize, + alloc: A, +) -> Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ ::from_elem(elem, n, alloc) } @@ -2572,7 +2659,11 @@ trait ExtendFromWithinSpec { unsafe fn spec_extend_from_within(&mut self, src: Range); } -impl ExtendFromWithinSpec for Vec { +impl ExtendFromWithinSpec + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ default unsafe fn spec_extend_from_within(&mut self, src: Range) { // SAFETY: // - len is increased only after initializing elements @@ -2591,7 +2682,11 @@ impl ExtendFromWithinSpec for Vec { } } -impl ExtendFromWithinSpec for Vec { +impl ExtendFromWithinSpec + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ unsafe fn spec_extend_from_within(&mut self, src: Range) { let count = src.len(); { @@ -2624,7 +2719,10 @@ impl ExtendFromWithinSpec for Vec { //////////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Deref for Vec { +impl ops::Deref for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Target = [T]; #[inline] @@ -2634,7 +2732,10 @@ impl ops::Deref for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::DerefMut for Vec { +impl ops::DerefMut for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn deref_mut(&mut self) -> &mut [T] { unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } @@ -2647,7 +2748,10 @@ trait SpecCloneFrom { } #[cfg(not(no_global_oom_handling))] -impl SpecCloneFrom for Vec { +impl SpecCloneFrom for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ default fn clone_from(this: &mut Self, other: &Self) { // drop anything that will not be overwritten this.truncate(other.len()); @@ -2663,7 +2767,10 @@ impl SpecCloneFrom for Vec { } #[cfg(not(no_global_oom_handling))] -impl SpecCloneFrom for Vec { +impl SpecCloneFrom for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn clone_from(this: &mut Self, other: &Self) { this.clear(); this.extend_from_slice(other); @@ -2672,7 +2779,10 @@ impl SpecCloneFrom for Vec { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Vec { +impl Clone for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[cfg(not(test))] fn clone(&self) -> Self { let alloc = self.allocator().clone(); @@ -2707,7 +2817,10 @@ impl Clone for Vec { /// assert_eq!(b.hash_one(v), b.hash_one(s)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -impl Hash for Vec { +impl Hash for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn hash(&self, state: &mut H) { Hash::hash(&**self, state) @@ -2719,7 +2832,11 @@ impl Hash for Vec { message = "vector indices are of type `usize` or ranges of `usize`", label = "vector indices are of type `usize` or ranges of `usize`" )] -impl, A: Allocator> Index for Vec { +impl, A: Allocator, const COOP_PREFERRED: bool> Index + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Output = I::Output; #[inline] @@ -2733,7 +2850,11 @@ impl, A: Allocator> Index for Vec { message = "vector indices are of type `usize` or ranges of `usize`", label = "vector indices are of type `usize` or ranges of `usize`" )] -impl, A: Allocator> IndexMut for Vec { +impl, A: Allocator, const COOP_PREFERRED: bool> IndexMut + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { IndexMut::index_mut(&mut **self, index) @@ -2750,7 +2871,10 @@ impl FromIterator for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for Vec { +impl IntoIterator for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = T; type IntoIter = IntoIter; @@ -2795,7 +2919,10 @@ impl IntoIterator for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a Vec { +impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> IntoIterator for &'a Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = &'a T; type IntoIter = slice::Iter<'a, T>; @@ -2805,7 +2932,11 @@ impl<'a, T, A: Allocator> IntoIterator for &'a Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { +impl<'a, T, A: Allocator, const COOP_PREFERRED: bool> IntoIterator + for &'a mut Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; @@ -2816,7 +2947,10 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for Vec { +impl Extend for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn extend>(&mut self, iter: I) { >::spec_extend(self, iter.into_iter()) @@ -2833,7 +2967,10 @@ impl Extend for Vec { } } -impl Vec { +impl Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ // leaf method to which various SpecFrom/SpecExtend implementations delegate when // they have no further optimizations to apply #[cfg(not(no_global_oom_handling))] @@ -3007,7 +3144,11 @@ impl Vec { /// [`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 { +impl<'a, T: Copy + 'a, A: Allocator + 'a, const COOP_PREFERRED: bool> Extend<&'a T> + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn extend>(&mut self, iter: I) { self.spec_extend(iter.into_iter()) } @@ -3025,7 +3166,11 @@ impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { /// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Vec { +impl PartialOrd + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn partial_cmp(&self, other: &Self) -> Option { PartialOrd::partial_cmp(&**self, &**other) @@ -3033,11 +3178,17 @@ impl PartialOrd for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Vec {} +impl Eq for Vec where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: +{ +} /// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Vec { +impl Ord for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ #[inline] fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(&**self, &**other) @@ -3045,7 +3196,11 @@ impl Ord for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { +unsafe impl<#[may_dangle] T, A: Allocator, const COOP_PREFERRED: bool> Drop + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn drop(&mut self) { unsafe { // use drop for [T] @@ -3059,45 +3214,66 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl const Default for Vec { +impl const Default for Vec +where + [(); crate::co_alloc_metadata_num_slots_with_preference_global(COOP_PREFERRED)]:, +{ /// Creates an empty `Vec`. /// /// The vector will not allocate until elements are pushed onto it. - fn default() -> Vec { + fn default() -> Vec { Vec::new() } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Vec { +impl fmt::Debug + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef> for Vec { - fn as_ref(&self) -> &Vec { +impl AsRef> + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ + fn as_ref(&self) -> &Vec { self } } #[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut> for Vec { - fn as_mut(&mut self) -> &mut Vec { +impl AsMut> + for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ + fn as_mut(&mut self) -> &mut Vec { self } } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[T]> for Vec { +impl AsRef<[T]> for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn as_ref(&self) -> &[T] { self } } #[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut<[T]> for Vec { +impl AsMut<[T]> for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn as_mut(&mut self) -> &mut [T] { self } @@ -3194,7 +3370,10 @@ where // note: test pulls in std, which causes errors here #[cfg(not(test))] #[stable(feature = "vec_from_box", since = "1.18.0")] -impl From> for Vec { +impl From> for Vec +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Convert a boxed slice into a vector by transferring ownership of /// the existing heap allocation. /// @@ -3213,7 +3392,10 @@ impl From> for Vec { #[cfg(not(no_global_oom_handling))] #[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] -impl From> for Box<[T], A> { +impl From> for Box<[T], A> +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ /// Convert a vector into a boxed slice. /// /// If `v` has excess capacity, its items will be moved into a @@ -3232,7 +3414,7 @@ impl From> for Box<[T], A> { /// /// assert_eq!(Box::from(vec), vec![1, 2, 3].into_boxed_slice()); /// ``` - fn from(v: Vec) -> Self { + fn from(v: Vec) -> Self { v.into_boxed_slice() } } @@ -3253,8 +3435,12 @@ impl From<&str> for Vec { } #[stable(feature = "array_try_from_vec", since = "1.48.0")] -impl TryFrom> for [T; N] { - type Error = Vec; +impl TryFrom> + for [T; N] +where + [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ + type Error = Vec; /// Gets the entire contents of the `Vec` as an array, /// if its size exactly matches that of the requested array. @@ -3282,7 +3468,7 @@ impl TryFrom> for [T; N] { /// assert_eq!(a, b' '); /// assert_eq!(b, b'd'); /// ``` - fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { + fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { if vec.len() != N { return Err(vec); } diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs index b0cf72577a1be..7b364e8d4bacd 100644 --- a/library/alloc/src/vec/partial_eq.rs +++ b/library/alloc/src/vec/partial_eq.rs @@ -1,3 +1,4 @@ +//use core::alloc; use crate::alloc::Allocator; #[cfg(not(no_global_oom_handling))] use crate::borrow::Cow; @@ -5,12 +6,12 @@ use crate::borrow::Cow; use super::Vec; macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + ([$($vars:tt)*] $lhs:ty, $rhs:ty, #[$stability:meta], $($constraints:tt)*) => { #[$stability] impl PartialEq<$rhs> for $lhs where T: PartialEq, - $($ty: $bound)? + $($constraints)* { #[inline] fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } @@ -20,21 +21,21 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { [A1: Allocator, A2: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } -__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")] } +__impl_slice_eq1! { [A1: Allocator, A2: Allocator, const COOP_PREFERRED1: bool, const COOP_PREFERRED2: bool] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED1)]:, [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED2)]: } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } #[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool] Cow<'_, [T]>, Vec, #[stable(feature = "rust1", since = "1.0.0")], T: Clone, [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } #[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &[U], #[stable(feature = "rust1", since = "1.0.0")], T: Clone } #[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")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U], #[stable(feature = "rust1", since = "1.0.0")], T: Clone } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } +__impl_slice_eq1! { [A: Allocator, const COOP_PREFERRED: bool, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")], [(); core::alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]: } // NOTE: some less important impls are omitted to reduce code bloat // FIXME(Centril): Reconsider this? diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index 56065ce565bfc..ea91491f62558 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -1,4 +1,5 @@ use crate::alloc::Allocator; +use core::alloc; use core::iter::TrustedLen; use core::slice::{self}; @@ -9,25 +10,31 @@ pub(super) trait SpecExtend { fn spec_extend(&mut self, iter: I); } -impl SpecExtend for Vec +impl SpecExtend for Vec where I: Iterator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter) } } -impl SpecExtend for Vec +impl SpecExtend for Vec where I: TrustedLen, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { default fn spec_extend(&mut self, iterator: I) { self.extend_trusted(iterator) } } -impl SpecExtend> for Vec { +impl SpecExtend> + for Vec +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ fn spec_extend(&mut self, mut iterator: IntoIter) { unsafe { self.append_elements(iterator.as_slice() as _); @@ -36,19 +43,23 @@ impl SpecExtend> for Vec { } } -impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec +impl<'a, T: 'a, I, A: Allocator + 'a, const COOP_PREFERRED: bool> SpecExtend<&'a T, I> + for Vec where I: Iterator, T: Clone, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { default fn spec_extend(&mut self, iterator: I) { self.spec_extend(iterator.cloned()) } } -impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec +impl<'a, T: 'a, A: Allocator + 'a, const COOP_PREFERRED: bool> SpecExtend<&'a T, slice::Iter<'a, T>> + for Vec where T: Copy, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { let slice = iterator.as_slice(); diff --git a/library/alloc/src/vec/spec_from_elem.rs b/library/alloc/src/vec/spec_from_elem.rs index ff364c033ee98..4c29f6184c149 100644 --- a/library/alloc/src/vec/spec_from_elem.rs +++ b/library/alloc/src/vec/spec_from_elem.rs @@ -2,16 +2,30 @@ use core::ptr; use crate::alloc::Allocator; use crate::raw_vec::RawVec; +use core::alloc; use super::{ExtendElement, IsZero, Vec}; // Specialization trait used for Vec::from_elem pub(super) trait SpecFromElem: Sized { - fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; + fn from_elem( + elem: Self, + n: usize, + alloc: A, + ) -> Vec + where + [(); alloc::co_alloc_metadata_num_slots::(COOP_PREFERRED)]:; } impl SpecFromElem for T { - default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { + default fn from_elem( + elem: Self, + n: usize, + alloc: A, + ) -> Vec + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { let mut v = Vec::with_capacity_in(n, alloc); v.extend_with(n, ExtendElement(elem)); v @@ -20,7 +34,14 @@ impl SpecFromElem for T { impl SpecFromElem for T { #[inline] - default fn from_elem(elem: T, n: usize, alloc: A) -> Vec { + default fn from_elem( + elem: T, + n: usize, + alloc: A, + ) -> Vec + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { if elem.is_zero() { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } @@ -32,7 +53,14 @@ impl SpecFromElem for T { impl SpecFromElem for i8 { #[inline] - fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { + fn from_elem( + elem: i8, + n: usize, + alloc: A, + ) -> Vec + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { if elem == 0 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } @@ -47,7 +75,14 @@ impl SpecFromElem for i8 { impl SpecFromElem for u8 { #[inline] - fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { + fn from_elem( + elem: u8, + n: usize, + alloc: A, + ) -> Vec + where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, + { if elem == 0 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index bad765c7f51fa..0397995747ee5 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -1,4 +1,5 @@ use crate::alloc::{Allocator, Global}; +use core::alloc; use core::ptr::{self}; use core::slice::{self}; @@ -22,13 +23,18 @@ pub struct Splice< 'a, I: Iterator + 'a, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { +> where + [(); core::alloc::co_alloc_metadata_num_slots::()]:, +{ pub(super) drain: Drain<'a, I::Item, A>, pub(super) replace_with: I, } #[stable(feature = "vec_splice", since = "1.21.0")] -impl Iterator for Splice<'_, I, A> { +impl Iterator for Splice<'_, I, A> +where + [(); core::alloc::co_alloc_metadata_num_slots::()]:, +{ type Item = I::Item; fn next(&mut self) -> Option { @@ -41,17 +47,26 @@ impl Iterator for Splice<'_, I, A> { } #[stable(feature = "vec_splice", since = "1.21.0")] -impl DoubleEndedIterator for Splice<'_, I, A> { +impl DoubleEndedIterator for Splice<'_, I, A> +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ fn next_back(&mut self) -> Option { self.drain.next_back() } } #[stable(feature = "vec_splice", since = "1.21.0")] -impl ExactSizeIterator for Splice<'_, I, A> {} +impl ExactSizeIterator for Splice<'_, I, A> where + [(); alloc::co_alloc_metadata_num_slots::()]: +{ +} #[stable(feature = "vec_splice", since = "1.21.0")] -impl Drop for Splice<'_, I, A> { +impl Drop for Splice<'_, I, A> +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ fn drop(&mut self) { self.drain.by_ref().for_each(drop); @@ -92,7 +107,10 @@ impl Drop for Splice<'_, I, A> { } /// Private helper methods for `Splice::drop` -impl Drain<'_, T, A> { +impl Drain<'_, T, A> +where + [(); alloc::co_alloc_metadata_num_slots::()]:, +{ /// The range from `self.vec.len` to `self.tail_start` contains elements /// that have been moved out. /// Fill that range as much as possible with new elements from the `replace_with` iterator. diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index af49826ff30a3..656e079f9c61c 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -61,6 +61,7 @@ fn box_deref_lval() { pub struct ConstAllocator; +//@FIXME unsafe impl const Allocator for ConstAllocator { fn allocate(&self, layout: Layout) -> Result, AllocError> { match layout.size() { diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index 1d80b8bf9ec76..a7251328c128b 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -1,7 +1,16 @@ +use crate::alloc::GlobalCoAllocMeta; use crate::alloc::Layout; use crate::cmp; use crate::ptr; +#[unstable(feature = "global_co_alloc_meta", issue = "none")] +#[allow(missing_debug_implementations)] +/// Used for parameters and results (to/from `GlobalCoAllocator`'s functions, where applicable). +pub struct RawAndMeta { + pub ptr: *mut u8, + pub meta: GlobalCoAllocMeta, +} + /// A memory allocator that can be registered as the standard library’s default /// through the `#[global_allocator]` attribute. /// @@ -156,6 +165,11 @@ pub unsafe trait GlobalAlloc { #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn alloc(&self, layout: Layout) -> *mut u8; + #[unstable(feature = "global_co_alloc", issue = "none")] + unsafe fn co_alloc(&self, _layout: Layout, mut _result: &mut RawAndMeta) { + panic!("@FIXME") + } + /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`. /// /// # Safety @@ -171,6 +185,11 @@ pub unsafe trait GlobalAlloc { #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); + #[unstable(feature = "global_co_alloc", issue = "none")] + unsafe fn co_dealloc(&self, _ptr_and_meta: RawAndMeta, _layout: Layout) { + panic!("@FIXME") + } + /// Behaves like `alloc`, but also ensures that the contents /// are set to zero before being returned. /// @@ -198,11 +217,23 @@ pub unsafe trait GlobalAlloc { if !ptr.is_null() { // SAFETY: as allocation succeeded, the region from `ptr` // of size `size` is guaranteed to be valid for writes. - unsafe { ptr::write_bytes(ptr, 0, size) }; + unsafe { ptr::write_bytes(ptr, 0u8, size) }; } ptr } + #[unstable(feature = "global_co_alloc", issue = "none")] + unsafe fn co_alloc_zeroed(&self, layout: Layout, mut result: &mut RawAndMeta) { + let size = layout.size(); + // SAFETY: the safety contract for `alloc` must be upheld by the caller. + unsafe { self.co_alloc(layout, &mut result) }; + if !result.ptr.is_null() { + // SAFETY: as allocation succeeded, the region from `ptr_and_meta.ptr` of size `size` is + // guaranteed to be valid for writes. + unsafe { ptr::write_bytes(result.ptr, 0u8, size) }; + } + } + /// Shrink or grow a block of memory to the given `new_size`. /// The block is described by the given `ptr` pointer and `layout`. /// @@ -274,4 +305,31 @@ pub unsafe trait GlobalAlloc { } new_ptr } + + #[unstable(feature = "global_co_alloc", issue = "none")] + unsafe fn co_realloc( + &self, + ptr_and_meta: RawAndMeta, + layout: Layout, + new_size: usize, + mut result: &mut RawAndMeta, + ) { + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid. + let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + // SAFETY: the caller must ensure that `new_layout` is greater than zero. + unsafe { self.co_alloc(new_layout, &mut result) }; + if !result.ptr.is_null() { + // SAFETY: the previously allocated block cannot overlap the newly allocated block. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping( + ptr_and_meta.ptr, + result.ptr, + cmp::min(layout.size(), new_size), + ); + self.co_dealloc(ptr_and_meta, layout); + } + } + } } diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index a6082455fac8d..c268dd9368bc3 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -3,6 +3,7 @@ #![stable(feature = "alloc_module", since = "1.28.0")] mod global; +//mod global_co; mod layout; #[stable(feature = "global_alloc", since = "1.28.0")] @@ -25,6 +26,23 @@ use crate::error::Error; use crate::fmt; use crate::ptr::{self, NonNull}; +// @FIXME Make this target-specific +/// Metadata for `Vec/VecDeque/RawVec` to assist the allocator. Make sure its +/// alignment is not bigger than alignment of `usize`. Otherwise, even if (a +/// particular) `Vec/VecDeque/RawVec` generic instance doesn't use cooperation, +/// it would increase size of that `Vec/VecDeque/RawVec` because of alignment +/// rules! @FIXME compile time test that `GlobalCoAllocMeta` alignment <= +/// `usize` alignment. +#[unstable(feature = "global_co_alloc_meta", issue = "none")] +#[allow(missing_debug_implementations)] +#[derive(Clone, Copy)] +pub struct GlobalCoAllocMeta { + //pub one: usize, + /*pub two: usize, + pub three: usize, + pub four: usize,*/ +} + /// The `AllocError` error indicates an allocation failure /// that may be due to resource exhaustion or to /// something wrong when combining the given input arguments with this @@ -48,6 +66,45 @@ impl fmt::Display for AllocError { } } +#[unstable(feature = "global_co_alloc_meta", issue = "none")] +#[allow(missing_debug_implementations)] +pub struct PtrAndMeta { + pub ptr: NonNull, + pub meta: GlobalCoAllocMeta, +} + +#[unstable(feature = "global_co_alloc_meta", issue = "none")] +#[allow(missing_debug_implementations)] +/// Used for results (from `CoAllocator`'s functions, where applicable). +pub struct SliceAndMeta { + pub slice: NonNull<[u8]>, + pub meta: GlobalCoAllocMeta, +} + +#[unstable(feature = "global_co_alloc_short_term_pref", issue = "none")] +pub const SHORT_TERM_VEC_PREFERS_COOP: bool = true; + +#[unstable(feature = "global_co_alloc_meta", issue = "none")] +#[allow(missing_debug_implementations)] +pub type SliceAndMetaResult = Result; + +#[unstable(feature = "global_co_alloc", issue = "none")] +pub const fn co_alloc_metadata_num_slots() -> usize { + if true { + panic!("FIXME - consider removing co_alloc_metadata_num_slots()"); + } + if A::IS_CO_ALLOCATOR { 1 } else { 0 } +} + +#[unstable(feature = "global_co_alloc", issue = "none")] +/// Param `coop_preferred` - if false, then this returns `0`, regardless of +/// whether allocator `A` is cooperative. +pub const fn co_alloc_metadata_num_slots_with_preference_specific( + coop_preferred: bool, +) -> usize { + if A::IS_CO_ALLOCATOR && coop_preferred { 1 } else { 0 } +} + /// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of /// data described via [`Layout`][]. /// @@ -107,6 +164,14 @@ impl fmt::Display for AllocError { #[unstable(feature = "allocator_api", issue = "32838")] #[const_trait] pub unsafe trait Allocator { + //const fn is_co_allocator() -> bool {false} + // Can't have: const type Xyz; + /// If this is any type with non-zero size, then the actual `Allocator` implementation supports cooperative functions (`co_*`) as first class citizens. + //type IsCoAllocator = (); + // It applies to the global (default) allocator only. And/or System allocator?! @FIXME + // @FIXME make false by default + const IS_CO_ALLOCATOR: bool = true; + /// Attempts to allocate a block of memory. /// /// On success, returns a [`NonNull<[u8]>`][NonNull] meeting the size and alignment guarantees of `layout`. @@ -129,6 +194,10 @@ pub unsafe trait Allocator { /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html fn allocate(&self, layout: Layout) -> Result, AllocError>; + fn co_allocate(&self, _layout: Layout, _result: &mut SliceAndMetaResult) { + panic!("FIXME") + } + /// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized. /// /// # Errors @@ -151,6 +220,14 @@ pub unsafe trait Allocator { Ok(ptr) } + fn co_allocate_zeroed(&self, layout: Layout, mut result: &mut SliceAndMetaResult) { + self.co_allocate(layout, &mut result); + if let Ok(SliceAndMeta { slice, .. }) = result { + // SAFETY: `alloc` returns a valid memory block + unsafe { slice.as_non_null_ptr().as_ptr().write_bytes(0, slice.len()) } + } + } + /// Deallocates the memory referenced by `ptr`. /// /// # Safety @@ -162,6 +239,10 @@ pub unsafe trait Allocator { /// [*fit*]: #memory-fitting unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); + unsafe fn co_deallocate(&self, _ptr_and_meta: PtrAndMeta, _layout: Layout) { + panic!("FIXME") + } + /// Attempts to extend the memory block. /// /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated @@ -226,6 +307,37 @@ pub unsafe trait Allocator { Ok(new_ptr) } + unsafe fn co_grow( + &self, + ptr_and_meta: PtrAndMeta, + old_layout: Layout, + new_layout: Layout, + mut result: &mut SliceAndMetaResult, + ) { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + + self.co_allocate(new_layout, &mut result); + + if let Ok(SliceAndMeta { slice, .. }) = result { + // SAFETY: because `new_layout.size()` must be greater than or equal to + // `old_layout.size()`, both the old and new memory allocation are valid for reads and + // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet + // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is + // safe. The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping( + ptr_and_meta.ptr.as_ptr(), + slice.as_mut_ptr(), + old_layout.size(), + ); + self.co_deallocate(ptr_and_meta, old_layout); + } + } + } + /// Behaves like `grow`, but also ensures that the new contents are set to zero before being /// returned. /// @@ -289,6 +401,37 @@ pub unsafe trait Allocator { Ok(new_ptr) } + unsafe fn co_grow_zeroed( + &self, + ptr_and_meta: PtrAndMeta, + old_layout: Layout, + new_layout: Layout, + mut result: &mut SliceAndMetaResult, + ) { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + + self.co_allocate_zeroed(new_layout, &mut result); + + if let Ok(SliceAndMeta { slice, .. }) = result { + // SAFETY: because `new_layout.size()` must be greater than or equal to + // `old_layout.size()`, both the old and new memory allocation are valid for reads and + // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet + // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is + // safe. The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping( + ptr_and_meta.ptr.as_ptr(), + slice.as_mut_ptr(), + old_layout.size(), + ); + self.co_deallocate(ptr_and_meta, old_layout); + } + } + } + /// Attempts to shrink the memory block. /// /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated @@ -353,6 +496,37 @@ pub unsafe trait Allocator { Ok(new_ptr) } + unsafe fn co_shrink( + &self, + ptr_and_meta: PtrAndMeta, + old_layout: Layout, + new_layout: Layout, + mut result: &mut SliceAndMetaResult, + ) { + debug_assert!( + new_layout.size() <= old_layout.size(), + "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" + ); + + self.co_allocate(new_layout, &mut result); + + if let Ok(SliceAndMeta { slice, .. }) = result { + // SAFETY: because `new_layout.size()` must be lower than or equal to + // `old_layout.size()`, both the old and new memory allocation are valid for reads and + // writes for `new_layout.size()` bytes. Also, because the old allocation wasn't yet + // deallocated, it cannot overlap `new_slice_and_meta.slice`. Thus, the call to `copy_nonoverlapping` is + // safe. The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping( + ptr_and_meta.ptr.as_ptr(), + slice.as_mut_ptr(), + new_layout.size(), + ); + self.co_deallocate(ptr_and_meta, old_layout); + } + } + } + /// Creates a "by reference" adapter for this instance of `Allocator`. /// /// The returned adapter also implements `Allocator` and will simply borrow this. @@ -365,6 +539,7 @@ pub unsafe trait Allocator { } } +// @FIXME #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl Allocator for &A where diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 890d7df8e1796..c83b1bb4574b5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -98,6 +98,7 @@ #![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))] // // Library features: +#![feature(associated_type_defaults)] #![feature(const_align_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 61c1ff578b2ca..30906258946c1 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -197,10 +197,13 @@ impl System { } } +// @FIXME // The Allocator impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl, // which is in `std::sys::*::alloc`. #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl Allocator for System { + const IS_CO_ALLOCATOR: bool = false; + #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { self.alloc_impl(layout, false) diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index d98ab021cadb1..f8d2ca1d3e74c 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -6,6 +6,7 @@ use crate::io::prelude::*; use crate::alloc::Allocator; use crate::cmp; use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; +use core::alloc; /// A `Cursor` wraps an in-memory buffer and provides it with a /// [`Seek`] implementation. @@ -397,11 +398,14 @@ fn slice_write_vectored( } /// Reserves the required space, and pads the vec with 0s if necessary. -fn reserve_and_pad( +fn reserve_and_pad( pos_mut: &mut u64, - vec: &mut Vec, + vec: &mut Vec, buf_len: usize, -) -> io::Result { +) -> io::Result +where + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, +{ let pos: usize = (*pos_mut).try_into().map_err(|_| { io::const_io_error!( ErrorKind::InvalidInput, @@ -440,9 +444,14 @@ fn reserve_and_pad( /// Writes the slice to the vec without allocating /// # Safety: vec must have buf.len() spare capacity -unsafe fn vec_write_unchecked(pos: usize, vec: &mut Vec, buf: &[u8]) -> usize +unsafe fn vec_write_unchecked( + pos: usize, + vec: &mut Vec, + buf: &[u8], +) -> usize where A: Allocator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { debug_assert!(vec.capacity() >= pos + buf.len()); vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len()); @@ -458,9 +467,14 @@ where /// This also allows for the vec body to be empty, but with a position of N. /// This means that [`Write`] will pad the vec with 0 initially, /// before writing anything from that point -fn vec_write(pos_mut: &mut u64, vec: &mut Vec, buf: &[u8]) -> io::Result +fn vec_write( + pos_mut: &mut u64, + vec: &mut Vec, + buf: &[u8], +) -> io::Result where A: Allocator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { let buf_len = buf.len(); let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?; @@ -489,13 +503,14 @@ where /// This also allows for the vec body to be empty, but with a position of N. /// This means that [`Write`] will pad the vec with 0 initially, /// before writing anything from that point -fn vec_write_vectored( +fn vec_write_vectored( pos_mut: &mut u64, - vec: &mut Vec, + vec: &mut Vec, bufs: &[IoSlice<'_>], ) -> io::Result where A: Allocator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { // For safety reasons, we don't want this sum to overflow ever. // If this saturates, the reserve should panic to avoid any unsound writing. @@ -543,9 +558,10 @@ impl Write for Cursor<&mut [u8]> { } #[stable(feature = "cursor_mut_vec", since = "1.25.0")] -impl Write for Cursor<&mut Vec> +impl Write for Cursor<&mut Vec> where A: Allocator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { fn write(&mut self, buf: &[u8]) -> io::Result { vec_write(&mut self.pos, self.inner, buf) @@ -567,9 +583,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Write for Cursor> +impl Write for Cursor> where A: Allocator, + [(); alloc::co_alloc_metadata_num_slots_with_preference_specific::(COOP_PREFERRED)]:, { fn write(&mut self, buf: &[u8]) -> io::Result { vec_write(&mut self.pos, &mut self.inner, buf) diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index e5048dcc8acd9..8671ebf5c8141 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -378,7 +378,10 @@ impl Write for &mut [u8] { /// Write is implemented for `Vec` by appending to the vector. /// The vector will grow as needed. #[stable(feature = "rust1", since = "1.0.0")] -impl Write for Vec { +impl Write for Vec +where + [(); alloc::co_alloc_metadata_num_slots_with_preference::(COOP_PREFERRED)]:, +{ #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.extend_from_slice(buf); @@ -414,7 +417,10 @@ impl Write for Vec { /// Read is implemented for `VecDeque` by consuming bytes from the front of the `VecDeque`. #[stable(feature = "vecdeque_read_write", since = "1.63.0")] -impl Read for VecDeque { +impl Read for VecDeque +where + [(); co_alloc_metadata_num_slots_with_preference::(_COOP_PREFERRED)]:, +{ /// Fill `buf` with the contents of the "front" slice as returned by /// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are /// discontiguous, multiple calls to `read` will be needed to read the entire content. @@ -438,7 +444,10 @@ impl Read for VecDeque { /// Write is implemented for `VecDeque` by appending to the `VecDeque`, growing it as needed. #[stable(feature = "vecdeque_read_write", since = "1.63.0")] -impl Write for VecDeque { +impl Write for VecDeque +where + [(); co_alloc_metadata_num_slots_with_preference::(_COOP_PREFERRED)]:, +{ #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.extend(buf); diff --git a/library/std/src/sys/hermit/thread_local_dtor.rs b/library/std/src/sys/hermit/thread_local_dtor.rs index 9b683fce15748..7f0c2b0b180cb 100644 --- a/library/std/src/sys/hermit/thread_local_dtor.rs +++ b/library/std/src/sys/hermit/thread_local_dtor.rs @@ -1,5 +1,6 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "none")] +#![feature(global_co_alloc_plvec)] // Simplify dtor registration by using a list of destructors. // The this solution works like the implementation of macOS and @@ -7,11 +8,12 @@ use crate::cell::Cell; use crate::ptr; +use core::alloc::PlVec; #[thread_local] static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut()); -type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>; +type List = PlVec<(*mut u8, unsafe extern "C" fn(*mut u8))>; pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { if DTORS.get().is_null() { diff --git a/library/std/src/sys/solid/thread_local_dtor.rs b/library/std/src/sys/solid/thread_local_dtor.rs index 9735645705776..c7cf2f02ebbd1 100644 --- a/library/std/src/sys/solid/thread_local_dtor.rs +++ b/library/std/src/sys/solid/thread_local_dtor.rs @@ -1,16 +1,18 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "none")] +#![feature(global_co_alloc_plvec)] // Simplify dtor registration by using a list of destructors. use super::{abi, itron::task}; use crate::cell::Cell; use crate::ptr; +use core::alloc::PlVec; #[thread_local] static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut()); -type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>; +type List = PlVec<(*mut u8, unsafe extern "C" fn(*mut u8))>; pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { if DTORS.get().is_null() { diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index d7fd2130f7cce..4549f5d77742c 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -1,9 +1,12 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "none")] +#![feature(global_co_alloc_plvec)] //! Provides thread-local destructors without an associated "key", which //! can be more efficient. +use core::alloc::PlVec; + // Since what appears to be glibc 2.18 this symbol has been shipped which // GCC and clang both use to invoke destructors in thread_local globals, so // let's do the same! @@ -66,7 +69,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { REGISTERED.set(true); } - type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>; + type List = PlVec<(*mut u8, unsafe extern "C" fn(*mut u8))>; #[thread_local] static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut()); diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index e67411e16860e..c55f22775fbf1 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -204,6 +204,7 @@ where // incorrect size hints for some short paths: // https://github.com/dylni/normpath/issues/5 let mut stack_buf: [MaybeUninit; 512] = MaybeUninit::uninit_array(); + // @FIXME Use CoVec? let mut heap_buf: Vec> = Vec::new(); unsafe { let mut n = stack_buf.len(); diff --git a/library/std/src/sys/windows/thread_local_dtor.rs b/library/std/src/sys/windows/thread_local_dtor.rs index 9707a95dff21b..cbadd2dd23aea 100644 --- a/library/std/src/sys/windows/thread_local_dtor.rs +++ b/library/std/src/sys/windows/thread_local_dtor.rs @@ -3,10 +3,13 @@ #![unstable(feature = "thread_local_internals", issue = "none")] #![cfg(target_thread_local)] +#![feature(global_co_alloc_plvec)] + +use core::alloc::PlVec; // Using a per-thread list avoids the problems in synchronizing global state. #[thread_local] -static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); +static mut DESTRUCTORS: PlVec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); // Ensure this can never be inlined because otherwise this may break in dylibs. // See #44391. diff --git a/library/std/src/sys_common/thread_local_dtor.rs b/library/std/src/sys_common/thread_local_dtor.rs index 1d13a7171b035..0914dc2639cc3 100644 --- a/library/std/src/sys_common/thread_local_dtor.rs +++ b/library/std/src/sys_common/thread_local_dtor.rs @@ -12,9 +12,11 @@ #![unstable(feature = "thread_local_internals", issue = "none")] #![allow(dead_code)] +#![feature(global_co_alloc_plvec)] use crate::ptr; use crate::sys_common::thread_local_key::StaticKey; +use alloc::vec::PlVec; pub unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { // The fallback implementation uses a vanilla OS-based TLS key to track @@ -28,7 +30,7 @@ pub unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern "C" fn(*mut // flagged for destruction. static DTORS: StaticKey = StaticKey::new(Some(run_dtors)); - type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>; + type List = PlVec<(*mut u8, unsafe extern "C" fn(*mut u8))>; if DTORS.get().is_null() { let v: Box = box Vec::new(); DTORS.set(Box::into_raw(v) as *mut u8); diff --git a/src/doc/nomicon b/src/doc/nomicon index dd37e21ccee43..ae406aa5287a9 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit dd37e21ccee43918ed18a71581bb2af537ffe4fc +Subproject commit ae406aa5287a9e025abb72343aaceec98458c117 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 995df09b65c58..a9869b4a3c4ca 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 995df09b65c582eb6290ab7ea5d9485983eb4c37 +Subproject commit a9869b4a3c4cac3bc6099b41f088679e268400b8 diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 62217df8de79c..d8f70d700217c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1,6 +1,8 @@ +use std::alloc::GlobalCoAllocMeta; use std::cell::RefCell; use std::default::Default; use std::hash::Hash; +use std::mem; use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; @@ -2574,13 +2576,13 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Crate, 64); // frequently moved by-value static_assert_size!(DocFragment, 32); - static_assert_size!(GenericArg, 32); + static_assert_size!(GenericArg, 32 + mem::size_of::()); static_assert_size!(GenericArgs, 32); - static_assert_size!(GenericParamDef, 56); + static_assert_size!(GenericParamDef, 56 + mem::size_of::()); static_assert_size!(Generics, 16); static_assert_size!(Item, 56); - static_assert_size!(ItemKind, 64); + static_assert_size!(ItemKind, 64 + mem::size_of::()); static_assert_size!(PathSegment, 40); - static_assert_size!(Type, 32); + static_assert_size!(Type, 32 + mem::size_of::()); // tidy-alphabetical-end } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index d4d3e4f6ea795..b84b058bd8e7e 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -1,6 +1,8 @@ +use std::alloc::GlobalCoAllocMeta; use std::cell::RefCell; use std::collections::BTreeMap; use std::io; +use std::mem; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::mpsc::{channel, Receiver}; @@ -75,7 +77,10 @@ pub(crate) struct Context<'tcx> { // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. #[cfg(all(not(windows), target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 160); +rustc_data_structures::static_assert_size!( + Context<'_>, + 160 + 2 * mem::size_of::() +); /// Shared mutable state used in [`Context`] and elsewhere. pub(crate) struct SharedContext<'tcx> { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ef1d7da5a341c..c34792513ef54 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -8,6 +8,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(drain_filter)] +#![feature(global_co_alloc_meta)] #![feature(is_terminal)] #![feature(let_chains)] #![feature(test)] diff --git a/src/tools/cargo b/src/tools/cargo index 2381cbdb4e9b0..cc0a320879c17 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 2381cbdb4e9b07090f552d34a44a529b6e620e44 +Subproject commit cc0a320879c17207bbfb96b5d778e28a2c62030d