Make ArenaAllocatable a marker trait to allow overlapping impls and use specialization to find the right field

This commit is contained in:
John Kåre Alsaker 2019-03-30 01:36:51 +01:00
parent 002c70f2d4
commit e835d27ad3
3 changed files with 28 additions and 28 deletions

View File

@ -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)
}
}
}

View File

@ -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)]

View File

@ -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>,