Skip to content

Commit 590acba

Browse files
CoAlloc: Big Squash
1 parent 439292b commit 590acba

File tree

87 files changed

+2939
-566
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

+2939
-566
lines changed

compiler/rustc_arena/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
1212
test(no_crate_inject, attr(deny(warnings)))
1313
)]
14+
#![allow(incomplete_features)]
1415
#![feature(dropck_eyepatch)]
1516
#![feature(new_uninit)]
1617
#![feature(maybe_uninit_slice)]
17-
#![feature(min_specialization)]
18+
//#![feature(min_specialization)]
19+
#![feature(specialization)]
1820
#![feature(decl_macro)]
1921
#![feature(pointer_byte_offsets)]
2022
#![feature(rustc_attrs)]

compiler/rustc_ast/src/ast.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ use rustc_span::{Span, DUMMY_SP};
3737
use std::fmt;
3838
use std::mem;
3939
use thin_vec::{thin_vec, ThinVec};
40-
4140
/// A "Label" is an identifier of some point in sources,
4241
/// e.g. in the following code:
4342
///
@@ -3113,30 +3112,31 @@ pub type ForeignItem = Item<ForeignItemKind>;
31133112
mod size_asserts {
31143113
use super::*;
31153114
use rustc_data_structures::static_assert_size;
3115+
use std::alloc::{Allocator, Global};
31163116
// tidy-alphabetical-start
31173117
static_assert_size!(AssocItem, 104);
31183118
static_assert_size!(AssocItemKind, 32);
31193119
static_assert_size!(Attribute, 32);
3120-
static_assert_size!(Block, 32);
3121-
static_assert_size!(Expr, 72);
3122-
static_assert_size!(ExprKind, 40);
3123-
static_assert_size!(Fn, 152);
3120+
static_assert_size!(Block, 32 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3121+
static_assert_size!(Expr, 72 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3122+
static_assert_size!(ExprKind, 40 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3123+
static_assert_size!(Fn, 152 + 2 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31243124
static_assert_size!(ForeignItem, 96);
31253125
static_assert_size!(ForeignItemKind, 24);
31263126
static_assert_size!(GenericArg, 24);
3127-
static_assert_size!(GenericBound, 56);
3128-
static_assert_size!(Generics, 40);
3129-
static_assert_size!(Impl, 136);
3130-
static_assert_size!(Item, 136);
3131-
static_assert_size!(ItemKind, 64);
3127+
static_assert_size!(GenericBound, 56 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3128+
static_assert_size!(Generics, 40 + 2 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3129+
static_assert_size!(Impl, 136 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3130+
static_assert_size!(Item, 136 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
3131+
static_assert_size!(ItemKind, 64 + 3 * mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31323132
static_assert_size!(LitKind, 24);
31333133
static_assert_size!(Local, 72);
31343134
static_assert_size!(MetaItemLit, 40);
31353135
static_assert_size!(Param, 40);
3136-
static_assert_size!(Pat, 72);
3136+
static_assert_size!(Pat, 72 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31373137
static_assert_size!(Path, 24);
31383138
static_assert_size!(PathSegment, 24);
3139-
static_assert_size!(PatKind, 48);
3139+
static_assert_size!(PatKind, 48 + mem::size_of::<<Global as Allocator>::CoAllocMeta>());
31403140
static_assert_size!(Stmt, 32);
31413141
static_assert_size!(StmtKind, 16);
31423142
static_assert_size!(Ty, 64);

compiler/rustc_ast/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
99
test(attr(deny(warnings)))
1010
)]
11+
#![feature(allocator_api)]
1112
#![feature(associated_type_bounds)]
1213
#![feature(box_patterns)]
1314
#![feature(const_default_impls)]
1415
#![feature(const_trait_impl)]
16+
#![feature(global_co_alloc_meta)]
1517
#![feature(if_let_guard)]
1618
#![feature(let_chains)]
1719
#![feature(min_specialization)]

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
357357
return None // do not suggest code that is already there (#53348)
358358
}
359359

360-
let method_call_list = [sym::to_vec, sym::to_string];
360+
let method_call_list = [sym::to_vec, sym::to_vec_co, sym::to_string];
361361
let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = expr.kind
362362
&& receiver_method.ident.name == sym::clone
363363
&& method_call_list.contains(&conversion_method.name)

compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![feature(exhaustive_patterns)]
3333
#![feature(generators)]
3434
#![feature(get_mut_unchecked)]
35+
#![feature(global_co_alloc_meta)]
3536
#![feature(if_let_guard)]
3637
#![feature(iter_from_generator)]
3738
#![feature(local_key_cell_methods)]

compiler/rustc_middle/src/mir/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -3081,7 +3081,10 @@ mod size_asserts {
30813081
use super::*;
30823082
use rustc_data_structures::static_assert_size;
30833083
// tidy-alphabetical-start
3084-
static_assert_size!(BasicBlockData<'_>, 144);
3084+
static_assert_size!(
3085+
BasicBlockData<'_>,
3086+
144 + mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
3087+
);
30853088
static_assert_size!(LocalDecl<'_>, 40);
30863089
static_assert_size!(Statement<'_>, 32);
30873090
static_assert_size!(StatementKind<'_>, 16);

compiler/rustc_middle/src/mir/syntax.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,9 @@ mod size_asserts {
12511251
static_assert_size!(Operand<'_>, 24);
12521252
static_assert_size!(Place<'_>, 16);
12531253
static_assert_size!(PlaceElem<'_>, 24);
1254-
static_assert_size!(Rvalue<'_>, 40);
1254+
static_assert_size!(
1255+
Rvalue<'_>,
1256+
40 + std::mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
1257+
);
12551258
// tidy-alphabetical-end
12561259
}

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
@@ -467,8 +467,12 @@ fn make_token_stream(
467467
mod size_asserts {
468468
use super::*;
469469
use rustc_data_structures::static_assert_size;
470+
use std::alloc::{Allocator, Global};
470471
// tidy-alphabetical-start
471472
static_assert_size!(AttrWrapper, 16);
472-
static_assert_size!(LazyAttrTokenStreamImpl, 120);
473+
static_assert_size!(
474+
LazyAttrTokenStreamImpl,
475+
120 + std::mem::size_of::<<Global as Allocator>::CoAllocMeta>()
476+
);
473477
// tidy-alphabetical-end
474478
}

compiler/rustc_parse/src/parser/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,10 @@ pub struct Parser<'a> {
165165
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
166166
// it doesn't unintentionally get bigger.
167167
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
168-
rustc_data_structures::static_assert_size!(Parser<'_>, 288);
168+
rustc_data_structures::static_assert_size!(
169+
Parser<'_>,
170+
288 + 4 * mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
171+
);
169172

170173
/// Stores span information about a closure.
171174
#[derive(Clone)]

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,7 @@ symbols! {
14821482
tmm_reg,
14831483
to_string,
14841484
to_vec,
1485+
to_vec_co,
14851486
todo_macro,
14861487
tool_attributes,
14871488
tool_lints,

compiler/rustc_trait_selection/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
//! This API is completely unstable and subject to change.
1212
1313
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
14+
#![feature(allocator_api)]
1415
#![feature(associated_type_bounds)]
1516
#![feature(box_patterns)]
1617
#![feature(control_flow_enum)]
1718
#![feature(drain_filter)]
19+
#![feature(global_co_alloc_meta)]
1820
#![feature(hash_drain_filter)]
1921
#![feature(let_chains)]
2022
#![feature(if_let_guard)]

compiler/rustc_trait_selection/src/traits/fulfill.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::infer::{InferCtxt, TyOrConstInferVar};
2+
// use rustc_data_structures::fx::FxHashMap;
23
use rustc_data_structures::obligation_forest::ProcessResult;
34
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
45
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
@@ -78,7 +79,10 @@ pub struct PendingPredicateObligation<'tcx> {
7879

7980
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
8081
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
81-
static_assert_size!(PendingPredicateObligation<'_>, 72);
82+
static_assert_size!(
83+
PendingPredicateObligation<'_>,
84+
72 + std::mem::size_of::<<std::alloc::Global as std::alloc::Allocator>::CoAllocMeta>()
85+
);
8286

8387
impl<'a, 'tcx> FulfillmentContext<'tcx> {
8488
/// Creates a new fulfillment context.

library/alloc/src/boxed.rs

+54-13
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;
@@ -640,7 +642,10 @@ impl<T> Box<[T]> {
640642
#[unstable(feature = "new_uninit", issue = "63291")]
641643
#[must_use]
642644
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
643-
unsafe { RawVec::with_capacity(len).into_box(len) }
645+
// false = no need for co-alloc metadata, since it would get lost once converted to Box.
646+
unsafe {
647+
RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity(len).into_box(len)
648+
}
644649
}
645650

646651
/// Constructs a new boxed slice with uninitialized contents, with the memory
@@ -665,7 +670,11 @@ impl<T> Box<[T]> {
665670
#[unstable(feature = "new_uninit", issue = "63291")]
666671
#[must_use]
667672
pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
668-
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
673+
// false = no need for co-alloc metadata, since it would get lost once converted to Box.
674+
unsafe {
675+
RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity_zeroed(len)
676+
.into_box(len)
677+
}
669678
}
670679

671680
/// Constructs a new boxed slice with uninitialized contents. Returns an error if
@@ -697,7 +706,12 @@ impl<T> Box<[T]> {
697706
Err(_) => return Err(AllocError),
698707
};
699708
let ptr = Global.allocate(layout)?;
700-
Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len))
709+
Ok(RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::from_raw_parts_in(
710+
ptr.as_mut_ptr() as *mut _,
711+
len,
712+
Global,
713+
)
714+
.into_box(len))
701715
}
702716
}
703717

@@ -729,12 +743,21 @@ impl<T> Box<[T]> {
729743
Err(_) => return Err(AllocError),
730744
};
731745
let ptr = Global.allocate_zeroed(layout)?;
732-
Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len))
746+
Ok(RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::from_raw_parts_in(
747+
ptr.as_mut_ptr() as *mut _,
748+
len,
749+
Global,
750+
)
751+
.into_box(len))
733752
}
734753
}
735754
}
736755

737-
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+
{
738761
/// Constructs a new boxed slice with uninitialized contents in the provided allocator.
739762
///
740763
/// # Examples
@@ -761,8 +784,11 @@ impl<T, A: Allocator> Box<[T], A> {
761784
#[unstable(feature = "allocator_api", issue = "32838")]
762785
// #[unstable(feature = "new_uninit", issue = "63291")]
763786
#[must_use]
787+
#[allow(unused_braces)]
764788
pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
765-
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+
}
766792
}
767793

768794
/// Constructs a new boxed slice with uninitialized contents in the provided allocator,
@@ -789,8 +815,12 @@ impl<T, A: Allocator> Box<[T], A> {
789815
#[unstable(feature = "allocator_api", issue = "32838")]
790816
// #[unstable(feature = "new_uninit", issue = "63291")]
791817
#[must_use]
818+
#[allow(unused_braces)]
792819
pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
793-
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+
}
794824
}
795825
}
796826

@@ -1497,7 +1527,8 @@ impl<T: Copy> From<&[T]> for Box<[T]> {
14971527
/// ```
14981528
fn from(slice: &[T]) -> Box<[T]> {
14991529
let len = slice.len();
1500-
let buf = RawVec::with_capacity(len);
1530+
// false = no need for co-alloc metadata, since it would get lost once converted to Box.
1531+
let buf = RawVec::<T, Global, { CO_ALLOC_PREF_META_NO!() }>::with_capacity(len);
15011532
unsafe {
15021533
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
15031534
buf.into_box(slice.len()).assume_init()
@@ -1661,8 +1692,13 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
16611692

16621693
#[cfg(not(no_global_oom_handling))]
16631694
#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")]
1664-
impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
1665-
type Error = Vec<T>;
1695+
#[allow(unused_braces)]
1696+
impl<T, const N: usize, const CO_ALLOC_PREF: CoAllocPref> TryFrom<Vec<T, Global, CO_ALLOC_PREF>>
1697+
for Box<[T; N]>
1698+
where
1699+
[(); { meta_num_slots_global!(CO_ALLOC_PREF) }]:,
1700+
{
1701+
type Error = Vec<T, Global, CO_ALLOC_PREF>;
16661702

16671703
/// Attempts to convert a `Vec<T>` into a `Box<[T; N]>`.
16681704
///
@@ -1682,7 +1718,7 @@ impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
16821718
/// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap();
16831719
/// assert_eq!(state.len(), 100);
16841720
/// ```
1685-
fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
1721+
fn try_from(vec: Vec<T, Global, CO_ALLOC_PREF>) -> Result<Self, Self::Error> {
16861722
if vec.len() == N {
16871723
let boxed_slice = vec.into_boxed_slice();
16881724
Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
@@ -2019,10 +2055,15 @@ impl<I> FromIterator<I> for Box<[I]> {
20192055

20202056
#[cfg(not(no_global_oom_handling))]
20212057
#[stable(feature = "box_slice_clone", since = "1.3.0")]
2022-
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
2058+
#[allow(unused_braces)]
2059+
impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A>
2060+
where
2061+
[(); { crate::meta_num_slots!(A, crate::CO_ALLOC_PREF_META_NO!()) }]:,
2062+
{
20232063
fn clone(&self) -> Self {
20242064
let alloc = Box::allocator(self).clone();
2025-
self.to_vec_in(alloc).into_boxed_slice()
2065+
// false = no need for co-alloc metadata, since it would get lost once converted to the boxed slice.
2066+
self.to_vec_in_co::<A, { CO_ALLOC_PREF_META_NO!() }>(alloc).into_boxed_slice()
20262067
}
20272068

20282069
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 q ualified 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)