Skip to content

Commit 56e6e74

Browse files
CoAlloc (big squash)
1 parent 84a554c commit 56e6e74

File tree

87 files changed

+2755
-461
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+2755
-461
lines changed

compiler/rustc_arena/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#![feature(dropck_eyepatch)]
1818
#![feature(new_uninit)]
1919
#![feature(maybe_uninit_slice)]
20+
#![feature(min_specialization)]
21+
// FIXME CoAlloc needs min_specialization at all!?
2022
#![feature(decl_macro)]
2123
#![feature(rustc_attrs)]
2224
#![cfg_attr(test, feature(test))]

compiler/rustc_ast/src/ast.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub use rustc_type_ir::{Movability, Mutability};
3838
use std::fmt;
3939
use std::mem;
4040
use thin_vec::{thin_vec, ThinVec};
41-
4241
/// A "Label" is an identifier of some point in sources,
4342
/// e.g. in the following code:
4443
///
@@ -3171,30 +3170,31 @@ pub type ForeignItem = Item<ForeignItemKind>;
31713170
mod size_asserts {
31723171
use super::*;
31733172
use rustc_data_structures::static_assert_size;
3173+
use std::alloc::{Allocator, Global};
31743174
// tidy-alphabetical-start
31753175
static_assert_size!(AssocItem, 88);
31763176
static_assert_size!(AssocItemKind, 16);
31773177
static_assert_size!(Attribute, 32);
3178-
static_assert_size!(Block, 32);
3179-
static_assert_size!(Expr, 72);
3180-
static_assert_size!(ExprKind, 40);
3181-
static_assert_size!(Fn, 160);
3178+
static_assert_size!(Block, 32 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3179+
static_assert_size!(Expr, 72 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3180+
static_assert_size!(ExprKind, 40 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3181+
static_assert_size!(Fn, 160 + 2 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31823182
static_assert_size!(ForeignItem, 96);
31833183
static_assert_size!(ForeignItemKind, 24);
31843184
static_assert_size!(GenericArg, 24);
3185-
static_assert_size!(GenericBound, 64);
3186-
static_assert_size!(Generics, 40);
3187-
static_assert_size!(Impl, 136);
3188-
static_assert_size!(Item, 136);
3189-
static_assert_size!(ItemKind, 64);
3185+
static_assert_size!(GenericBound, 64 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3186+
static_assert_size!(Generics, 40 + 2 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3187+
static_assert_size!(Impl, 136 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3188+
static_assert_size!(Item, 136 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3189+
static_assert_size!(ItemKind, 64 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31903190
static_assert_size!(LitKind, 24);
31913191
static_assert_size!(Local, 72);
31923192
static_assert_size!(MetaItemLit, 40);
31933193
static_assert_size!(Param, 40);
3194-
static_assert_size!(Pat, 72);
3194+
static_assert_size!(Pat, 72 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31953195
static_assert_size!(Path, 24);
31963196
static_assert_size!(PathSegment, 24);
3197-
static_assert_size!(PatKind, 48);
3197+
static_assert_size!(PatKind, 48 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31983198
static_assert_size!(Stmt, 32);
31993199
static_assert_size!(StmtKind, 16);
32003200
static_assert_size!(Ty, 64);

compiler/rustc_ast/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
#![doc(rust_logo)]
1212
#![allow(internal_features)]
1313
#![feature(rustdoc_internals)]
14+
#![feature(allocator_api)]
1415
#![feature(associated_type_bounds)]
1516
#![feature(box_patterns)]
1617
#![feature(const_trait_impl)]
18+
#![feature(global_co_alloc_meta)]
1719
#![feature(if_let_guard)]
1820
#![feature(let_chains)]
1921
#![feature(min_specialization)]

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
383383
return None; // do not suggest code that is already there (#53348)
384384
}
385385

386-
let method_call_list = [sym::to_vec, sym::to_string];
386+
let method_call_list = [sym::to_vec, sym::to_vec_co, sym::to_string];
387387
let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = expr.kind
388388
&& receiver_method.ident.name == sym::clone
389389
&& method_call_list.contains(&conversion_method.name)

compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#![feature(exhaustive_patterns)]
3535
#![feature(coroutines)]
3636
#![feature(get_mut_unchecked)]
37+
#![feature(global_co_alloc_meta)]
3738
#![feature(if_let_guard)]
3839
#![feature(inline_const)]
3940
#![feature(iter_from_coroutine)]

compiler/rustc_middle/src/mir/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,10 @@ mod size_asserts {
16511651
use super::*;
16521652
use rustc_data_structures::static_assert_size;
16531653
// tidy-alphabetical-start
1654-
static_assert_size!(BasicBlockData<'_>, 136);
1654+
static_assert_size!(
1655+
BasicBlockData<'_>,
1656+
136 + mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
1657+
);
16551658
static_assert_size!(LocalDecl<'_>, 40);
16561659
static_assert_size!(SourceScopeData<'_>, 72);
16571660
static_assert_size!(Statement<'_>, 32);

compiler/rustc_middle/src/mir/syntax.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,9 @@ mod size_asserts {
14421442
static_assert_size!(Operand<'_>, 24);
14431443
static_assert_size!(Place<'_>, 16);
14441444
static_assert_size!(PlaceElem<'_>, 24);
1445-
static_assert_size!(Rvalue<'_>, 40);
1445+
static_assert_size!(
1446+
Rvalue<'_>,
1447+
40 + std::mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
1448+
);
14461449
// tidy-alphabetical-end
14471450
}

compiler/rustc_parse/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! The main parser interface.
22
3+
#![feature(allocator_api)]
34
#![feature(array_windows)]
45
#![feature(box_patterns)]
6+
#![feature(global_co_alloc_meta)]
57
#![feature(if_let_guard)]
68
#![feature(iter_intersperse)]
79
#![feature(let_chains)]

compiler/rustc_parse/src/parser/attr_wrapper.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,12 @@ fn make_token_stream(
457457
mod size_asserts {
458458
use super::*;
459459
use rustc_data_structures::static_assert_size;
460+
use std::alloc::{Allocator, Global};
460461
// tidy-alphabetical-start
461462
static_assert_size!(AttrWrapper, 16);
462-
static_assert_size!(LazyAttrTokenStreamImpl, 104);
463+
static_assert_size!(
464+
LazyAttrTokenStreamImpl,
465+
104 + std::mem::size_of::<<Global as Allocator>::CoAllocMeta>()
466+
);
463467
// tidy-alphabetical-end
464468
}

compiler/rustc_parse/src/parser/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ pub struct Parser<'a> {
179179
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
180180
// it doesn't unintentionally get bigger.
181181
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
182-
rustc_data_structures::static_assert_size!(Parser<'_>, 264);
182+
rustc_data_structures::static_assert_size!(
183+
Parser<'_>,
184+
264 + 4 * mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
185+
);
183186

184187
/// Stores span information about a closure.
185188
#[derive(Clone)]

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1643,6 +1643,7 @@ symbols! {
16431643
to_string,
16441644
to_string_method,
16451645
to_vec,
1646+
to_vec_co,
16461647
todo_macro,
16471648
tool_attributes,
16481649
tool_lints,

compiler/rustc_trait_selection/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
#![doc(rust_logo)]
1515
#![feature(rustdoc_internals)]
1616
#![allow(internal_features)]
17+
#![feature(allocator_api)]
1718
#![feature(associated_type_bounds)]
1819
#![feature(box_patterns)]
1920
#![feature(control_flow_enum)]
2021
#![feature(extract_if)]
22+
#![feature(global_co_alloc_meta)]
23+
// FIXME CoAlloc #![feature(hash_drain_filter)] ???
2124
#![feature(let_chains)]
2225
#![feature(if_let_guard)]
2326
#![feature(never_type)]

compiler/rustc_trait_selection/src/traits/fulfill.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ pub struct PendingPredicateObligation<'tcx> {
7575

7676
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
7777
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
78-
static_assert_size!(PendingPredicateObligation<'_>, 72);
78+
static_assert_size!(
79+
PendingPredicateObligation<'_>,
80+
72 + std::mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
81+
);
7982

8083
impl<'tcx> FulfillmentContext<'tcx> {
8184
/// Creates a new fulfillment context.

library/alloc/src/boxed.rs

+58-14
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@
146146
147147
#![stable(feature = "rust1", since = "1.0.0")]
148148

149+
#[cfg(not(no_global_oom_handling))]
150+
use crate::co_alloc::CoAllocPref;
149151
use core::any::Any;
150152
use core::async_iter::AsyncIterator;
151153
use core::borrow;
@@ -632,7 +634,10 @@ impl<T> Box<[T]> {
632634
#[unstable(feature = "new_uninit", issue = "63291")]
633635
#[must_use]
634636
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
635-
unsafe { RawVec::with_capacity(len).into_box(len) }
637+
// false = no need for co-alloc metadata, since it would get lost once converted to Box.
638+
unsafe {
639+
RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity(len).into_box(len)
640+
}
636641
}
637642

638643
/// Constructs a new boxed slice with uninitialized contents, with the memory
@@ -657,7 +662,11 @@ impl<T> Box<[T]> {
657662
#[unstable(feature = "new_uninit", issue = "63291")]
658663
#[must_use]
659664
pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
660-
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
665+
// false = no need for co-alloc metadata, since it would get lost once converted to Box.
666+
unsafe {
667+
RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity_zeroed(len)
668+
.into_box(len)
669+
}
661670
}
662671

663672
/// Constructs a new boxed slice with uninitialized contents. Returns an error if
@@ -692,7 +701,14 @@ impl<T> Box<[T]> {
692701
};
693702
Global.allocate(layout)?.cast()
694703
};
695-
unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) }
704+
unsafe {
705+
Ok(RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::from_raw_parts_in(
706+
ptr.as_ptr(),
707+
len,
708+
Global,
709+
)
710+
.into_box(len))
711+
}
696712
}
697713

698714
/// Constructs a new boxed slice with uninitialized contents, with the memory
@@ -726,11 +742,22 @@ impl<T> Box<[T]> {
726742
};
727743
Global.allocate_zeroed(layout)?.cast()
728744
};
729-
unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) }
745+
unsafe {
746+
Ok(RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::from_raw_parts_in(
747+
ptr.as_ptr(),
748+
len,
749+
Global,
750+
)
751+
.into_box(len))
752+
}
730753
}
731754
}
732755

733-
impl<T, A: Allocator> Box<[T], A> {
756+
#[allow(unused_braces)]
757+
impl<T, A: Allocator> Box<[T], A>
758+
where
759+
[(); { crate::meta_num_slots!(A, crate::CO_ALLOC_PREF_META_NO!()) }]:,
760+
{
734761
/// Constructs a new boxed slice with uninitialized contents in the provided allocator.
735762
///
736763
/// # Examples
@@ -757,8 +784,11 @@ impl<T, A: Allocator> Box<[T], A> {
757784
#[unstable(feature = "allocator_api", issue = "32838")]
758785
// #[unstable(feature = "new_uninit", issue = "63291")]
759786
#[must_use]
787+
#[allow(unused_braces)]
760788
pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
761-
unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) }
789+
unsafe {
790+
RawVec::<T, A, { CO_ALLOC_PREF_META_NO!() }>::with_capacity_in(len, alloc).into_box(len)
791+
}
762792
}
763793

764794
/// Constructs a new boxed slice with uninitialized contents in the provided allocator,
@@ -785,8 +815,12 @@ impl<T, A: Allocator> Box<[T], A> {
785815
#[unstable(feature = "allocator_api", issue = "32838")]
786816
// #[unstable(feature = "new_uninit", issue = "63291")]
787817
#[must_use]
818+
#[allow(unused_braces)]
788819
pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
789-
unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) }
820+
unsafe {
821+
RawVec::<T, A, { CO_ALLOC_PREF_META_NO!() }>::with_capacity_zeroed_in(len, alloc)
822+
.into_box(len)
823+
}
790824
}
791825
}
792826

@@ -1487,7 +1521,7 @@ trait BoxFromSlice<T> {
14871521
impl<T: Clone> BoxFromSlice<T> for Box<[T]> {
14881522
#[inline]
14891523
default fn from_slice(slice: &[T]) -> Self {
1490-
slice.to_vec().into_boxed_slice()
1524+
slice.to_vec_co::<{ CO_ALLOC_PREF_META_NO!() }>().into_boxed_slice()
14911525
}
14921526
}
14931527

@@ -1496,7 +1530,7 @@ impl<T: Copy> BoxFromSlice<T> for Box<[T]> {
14961530
#[inline]
14971531
fn from_slice(slice: &[T]) -> Self {
14981532
let len = slice.len();
1499-
let buf = RawVec::with_capacity(len);
1533+
let buf = RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity(len);
15001534
unsafe {
15011535
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
15021536
buf.into_box(slice.len()).assume_init()
@@ -1682,8 +1716,13 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
16821716

16831717
#[cfg(not(no_global_oom_handling))]
16841718
#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")]
1685-
impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
1686-
type Error = Vec<T>;
1719+
#[allow(unused_braces)]
1720+
impl<T, const N: usize, const CO_ALLOC_PREF: CoAllocPref> TryFrom<Vec<T, Global, CO_ALLOC_PREF>>
1721+
for Box<[T; N]>
1722+
where
1723+
[(); { meta_num_slots_global!(CO_ALLOC_PREF) }]:,
1724+
{
1725+
type Error = Vec<T, Global, CO_ALLOC_PREF>;
16871726

16881727
/// Attempts to convert a `Vec<T>` into a `Box<[T; N]>`.
16891728
///
@@ -1703,7 +1742,7 @@ impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
17031742
/// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap();
17041743
/// assert_eq!(state.len(), 100);
17051744
/// ```
1706-
fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
1745+
fn try_from(vec: Vec<T, Global, CO_ALLOC_PREF>) -> Result<Self, Self::Error> {
17071746
if vec.len() == N {
17081747
let boxed_slice = vec.into_boxed_slice();
17091748
Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
@@ -2038,10 +2077,15 @@ impl<I> FromIterator<I> for Box<[I]> {
20382077

20392078
#[cfg(not(no_global_oom_handling))]
20402079
#[stable(feature = "box_slice_clone", since = "1.3.0")]
2041-
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
2080+
#[allow(unused_braces)]
2081+
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A>
2082+
where
2083+
[(); { crate::meta_num_slots!(A, crate::CO_ALLOC_PREF_META_NO!()) }]:,
2084+
{
20422085
fn clone(&self) -> Self {
20432086
let alloc = Box::allocator(self).clone();
2044-
self.to_vec_in(alloc).into_boxed_slice()
2087+
// false = no need for co-alloc metadata, since it would get lost once converted to the boxed slice.
2088+
self.to_vec_in_co::<A, { CO_ALLOC_PREF_META_NO!() }>(alloc).into_boxed_slice()
20452089
}
20462090

20472091
fn clone_from(&mut self, other: &Self) {

library/alloc/src/co_alloc.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//! CoAlloction-specific types that only apply in heap-based applications (hence not a part of
2+
//! [::core]).
3+
//!
4+
//! Types here have names with `CoAlloc` prefix. Yes, when using a qualified path (like
5+
//! ::alloc::co_alloc::CoAllocPref), that involves "stuttering", which is not recommended.
6+
//!
7+
//! However, as per Rust Book the common practice is to import type names fully and access them just
8+
//! with their name (except for cases of conflict). And we don't want the type names any shorter
9+
//! (such `Pref`), because thoe would be vague/confusing.
10+
11+
/// `CoAllocPref` values indicate a type's preference for coallocation (in either user space, or
12+
/// `std` space). Used as a `const` generic parameter type (usually called `CO_ALLOC_PREF`).
13+
///
14+
/// The actual value may be overriden by the allocator. See also `CoAllocMetaNumSlotsPref` and
15+
/// `co_alloc_pref` macro .
16+
///
17+
/// This type WILL CHANGE (once ``#![feature(generic_const_exprs)]` and
18+
/// `#![feature(adt_const_params)]` are stable) to a dedicated struct/enum. Hence:
19+
/// - DO NOT construct instances, but use `co_alloc_pref` macro together with constants
20+
/// `CO_ALLOC_PREF_META_YES` and `CO_ALLOC_PREF_META_NO`;
21+
/// - DO NOT hard code any values; and
22+
/// - DO NOT mix this/cast this with/to `u8`, `u16`, `usize` (nor any other integer).
23+
#[unstable(feature = "global_co_alloc_meta", issue = "none")]
24+
pub type CoAllocPref = usize; //u8;
25+
26+
/// `CoAllocMetaNumSlotsPref` values indicate that a type (but not necessarily an allocator) prefers
27+
/// to coallocate by carrying metadata, or not. (In either user space, or `std` or `alloc` space).
28+
/// Used as an argument to macro call of `co_alloc_pref`, which generates a `CoAllocPref` value.
29+
///
30+
/// Currently this indicates only the (preferred) number of `CoAllocMetaBase` slots being used
31+
/// (either 1 = coallocation, or 0 = no coallocation). However, in the future this type may have
32+
/// other properties (serving as extra hints to the allocator).
33+
///
34+
/// The actual value may be overriden by the allocator. For example, if the allocator doesn't
35+
/// support coallocation, then whether this value prefers to coallocate or not makes no difference.
36+
///
37+
/// This type WILL CHANGE (once ``#![feature(generic_const_exprs)]` and
38+
/// `#![feature(adt_const_params)]` are stable) to a dedicated struct/enum. Hence:
39+
/// - DO NOT mix this/cast this with/to `u8`, `u16`, (nor any other integer); and
40+
/// - DO NOT hard code any values, but use `CO_ALLOC_PREF_META_YES` and `CO_ALLOC_PREF_META_NO`.
41+
///
42+
/// This type is intentionally not `u16`, `u32`, nor `usize`. Why? This helps to prevent mistakes
43+
/// when one would use `CO_ALLOC_PREF_META_YES` or `CO_ALLOC_PREF_META_NO` in place of `CoAllocPref`
44+
/// vales, or in place of a result of `meta_num_slots` macro. That also prevents mixing up with
45+
/// [core::alloc::CoAllocatorMetaNumSlots].
46+
#[unstable(feature = "global_co_alloc_meta", issue = "none")]
47+
pub type CoAllocMetaNumSlotsPref = u16;

0 commit comments

Comments
 (0)