Skip to content
Permalink
Browse files

Make ArenaAllocatable a marker trait to allow overlapping impls and u…

…se specialization to find the right field
  • Loading branch information...
Zoxc committed Mar 30, 2019
1 parent 002c70f commit e835d27ad3f464bf81e5b702c1412be09761c991
Showing with 28 additions and 28 deletions.
  1. +25 −26 src/librustc/arena.rs
  2. +1 −0 src/librustc/lib.rs
  3. +2 −2 src/librustc/ty/codec.rs
@@ -1,4 +1,5 @@
use arena::{TypedArena, DroplessArena};
use std::mem;

#[macro_export]
macro_rules! arena_types {
@@ -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
}
}
)*
@@ -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)
}
}
}
@@ -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)]
@@ -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>,
@@ -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>,

0 comments on commit e835d27

Please sign in to comment.
You can’t perform that action at this time.