diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index c3e4945c446..2e8022d9880 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -15,6 +15,8 @@ #![feature(new_uninit)] #![feature(maybe_uninit_slice)] #![feature(min_specialization)] +#![feature(decl_macro)] +#![feature(rustc_attrs)] #![cfg_attr(test, feature(test))] use rustc_data_structures::sync; @@ -608,117 +610,113 @@ impl DropArena { } } -#[macro_export] -macro_rules! arena_for_type { +pub macro arena_for_type { ([][$ty:ty]) => { $crate::TypedArena<$ty> - }; + }, ([few $(, $attrs:ident)*][$ty:ty]) => { ::std::marker::PhantomData<$ty> - }; + }, ([$ignore:ident $(, $attrs:ident)*]$args:tt) => { $crate::arena_for_type!([$($attrs),*]$args) - }; + }, } -#[macro_export] -macro_rules! which_arena_for_type { +pub macro which_arena_for_type { ([][$arena:expr]) => { ::std::option::Option::Some($arena) - }; + }, ([few$(, $attrs:ident)*][$arena:expr]) => { ::std::option::Option::None - }; + }, ([$ignore:ident$(, $attrs:ident)*]$args:tt) => { $crate::which_arena_for_type!([$($attrs),*]$args) - }; + }, } -#[macro_export] -macro_rules! declare_arena { - ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { - #[derive(Default)] - pub struct Arena<$tcx> { - pub dropless: $crate::DroplessArena, - drop: $crate::DropArena, - $($name: $crate::arena_for_type!($a[$ty]),)* +#[rustc_macro_transparency = "semitransparent"] +pub macro declare_arena([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) { + #[derive(Default)] + pub struct Arena<$tcx> { + pub dropless: $crate::DroplessArena, + drop: $crate::DropArena, + $($name: $crate::arena_for_type!($a[$ty]),)* + } + + pub trait ArenaAllocatable<'tcx, T = Self>: Sized { + fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self; + fn allocate_from_iter<'a>( + arena: &'a Arena<'tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'a mut [Self]; + } + + impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T { + #[inline] + fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self { + arena.dropless.alloc(self) + } + #[inline] + fn allocate_from_iter<'a>( + arena: &'a Arena<'tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'a mut [Self] { + arena.dropless.alloc_from_iter(iter) } - pub trait ArenaAllocatable<'tcx, T = Self>: Sized { - fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self; - fn allocate_from_iter<'a>( - arena: &'a Arena<'tcx>, - iter: impl ::std::iter::IntoIterator, - ) -> &'a mut [Self]; - } - - impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T { + } + $( + impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty { #[inline] - fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self { - arena.dropless.alloc(self) + fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self { + if !::std::mem::needs_drop::() { + return arena.dropless.alloc(self); + } + match $crate::which_arena_for_type!($a[&arena.$name]) { + ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => { + ty_arena.alloc(self) + } + ::std::option::Option::None => unsafe { arena.drop.alloc(self) }, + } } + #[inline] fn allocate_from_iter<'a>( - arena: &'a Arena<'tcx>, + arena: &'a Arena<$tcx>, iter: impl ::std::iter::IntoIterator, ) -> &'a mut [Self] { - arena.dropless.alloc_from_iter(iter) + if !::std::mem::needs_drop::() { + return arena.dropless.alloc_from_iter(iter); + } + match $crate::which_arena_for_type!($a[&arena.$name]) { + ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => { + ty_arena.alloc_from_iter(iter) + } + ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) }, + } } - } - $( - impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty { - #[inline] - fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self { - if !::std::mem::needs_drop::() { - return arena.dropless.alloc(self); - } - match $crate::which_arena_for_type!($a[&arena.$name]) { - ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => { - ty_arena.alloc(self) - } - ::std::option::Option::None => unsafe { arena.drop.alloc(self) }, - } - } + )* - #[inline] - fn allocate_from_iter<'a>( - arena: &'a Arena<$tcx>, - iter: impl ::std::iter::IntoIterator, - ) -> &'a mut [Self] { - if !::std::mem::needs_drop::() { - return arena.dropless.alloc_from_iter(iter); - } - match $crate::which_arena_for_type!($a[&arena.$name]) { - ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => { - ty_arena.alloc_from_iter(iter) - } - ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) }, - } - } - } - )* + impl<'tcx> Arena<'tcx> { + #[inline] + pub fn alloc, U>(&self, value: T) -> &mut T { + value.allocate_on(self) + } - impl<'tcx> Arena<'tcx> { - #[inline] - pub fn alloc, U>(&self, value: T) -> &mut T { - value.allocate_on(self) + #[inline] + pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { + if value.is_empty() { + return &mut []; } + self.dropless.alloc_slice(value) + } - #[inline] - pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { - if value.is_empty() { - return &mut []; - } - self.dropless.alloc_slice(value) - } - - pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>( - &'a self, - iter: impl ::std::iter::IntoIterator, - ) -> &'a mut [T] { - T::allocate_from_iter(self, iter) - } + pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>( + &'a self, + iter: impl ::std::iter::IntoIterator, + ) -> &'a mut [T] { + T::allocate_from_iter(self, iter) } } }