Skip to content

Commit

Permalink
Make ArenaAllocatable a marker trait to allow overlapping impls and u…
Browse files Browse the repository at this point in the history
…se specialization to find the right field
  • Loading branch information
Zoxc committed Apr 4, 2019
1 parent 002c70f commit e835d27
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 28 deletions.
51 changes: 25 additions & 26 deletions src/librustc/arena.rs
@@ -1,4 +1,5 @@
use arena::{TypedArena, DroplessArena};
use std::mem;

#[macro_export]
macro_rules! arena_types {
Expand Down Expand Up @@ -35,10 +36,11 @@ macro_rules! impl_arena_allocatable {
$(
impl_specialized_decodable!($a $ty, $tcx);

impl<$tcx> ArenaAllocatable<$tcx> for $ty {
impl ArenaAllocatable for $ty {}
impl<$tcx> ArenaField<$tcx> for $ty {
#[inline]
fn arena<'a>(arena: &'a Arena<$tcx>) -> Option<&'a TypedArena<Self>> {
Some(&arena.$name)
fn arena<'a>(arena: &'a Arena<$tcx>) -> &'a TypedArena<Self> {
&arena.$name
}
}
)*
Expand All @@ -49,46 +51,43 @@ arena_types!(declare_arena, [], 'tcx);

arena_types!(impl_arena_allocatable, [], 'tcx);

pub trait ArenaAllocatable<'tcx>: Sized {
/// Returns a specific arena to allocate from if the type requires destructors.
/// Otherwise it will return `None` to be allocated from the dropless arena.
fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>>;
pub trait ArenaAllocatable {}

impl<T: Copy> ArenaAllocatable for T {}

pub trait ArenaField<'tcx>: Sized {
/// Returns a specific arena to allocate from.
fn arena<'a>(arena: &'a Arena<'tcx>) -> &'a TypedArena<Self>;
}

impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {
impl<'tcx, T> ArenaField<'tcx> for T {
#[inline]
default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>> {
None
default fn arena<'a>(_: &'a Arena<'tcx>) -> &'a TypedArena<Self> {
panic!()
}
}

impl<'tcx> Arena<'tcx> {
#[inline]
pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
match T::arena(self) {
Some(arena) => {
arena.alloc(value)
}
None => {
self.dropless.alloc(value)
}
pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
if mem::needs_drop::<T>() {
<T as ArenaField<'tcx>>::arena(self).alloc(value)
} else {
self.dropless.alloc(value)
}
}

pub fn alloc_from_iter<
T: ArenaAllocatable<'tcx>,
T: ArenaAllocatable,
I: IntoIterator<Item = T>
>(
&self,
iter: I
) -> &mut [T] {
match T::arena(self) {
Some(arena) => {
arena.alloc_from_iter(iter)
}
None => {
self.dropless.alloc_from_iter(iter)
}
if mem::needs_drop::<T>() {
<T as ArenaField<'tcx>>::arena(self).alloc_from_iter(iter)
} else {
self.dropless.alloc_from_iter(iter)
}
}
}
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Expand Up @@ -40,6 +40,7 @@
#![cfg_attr(windows, feature(libc))]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(overlapping_marker_traits)]
#![feature(extern_types)]
#![feature(nll)]
#![feature(non_exhaustive)]
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/codec.rs
Expand Up @@ -132,7 +132,7 @@ pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
}

#[inline]
pub fn decode_arena_allocable<'a, 'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
pub fn decode_arena_allocable<'a, 'tcx, D, T: ArenaAllocatable + Decodable>(
decoder: &mut D
) -> Result<&'tcx T, D::Error>
where D: TyDecoder<'a, 'tcx>,
Expand All @@ -142,7 +142,7 @@ pub fn decode_arena_allocable<'a, 'tcx, D, T: ArenaAllocatable<'tcx> + Decodable
}

#[inline]
pub fn decode_arena_allocable_slice<'a, 'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
pub fn decode_arena_allocable_slice<'a, 'tcx, D, T: ArenaAllocatable + Decodable>(
decoder: &mut D
) -> Result<&'tcx [T], D::Error>
where D: TyDecoder<'a, 'tcx>,
Expand Down

0 comments on commit e835d27

Please sign in to comment.