From e835d27ad3f464bf81e5b702c1412be09761c991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 30 Mar 2019 01:36:51 +0100 Subject: [PATCH] Make ArenaAllocatable a marker trait to allow overlapping impls and use specialization to find the right field --- src/librustc/arena.rs | 51 ++++++++++++++++++++-------------------- src/librustc/lib.rs | 1 + src/librustc/ty/codec.rs | 4 ++-- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 23493d5c93f22..1f1060ee243f3 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.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> { - Some(&arena.$name) + fn arena<'a>(arena: &'a Arena<$tcx>) -> &'a TypedArena { + &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>; +pub trait ArenaAllocatable {} + +impl ArenaAllocatable for T {} + +pub trait ArenaField<'tcx>: Sized { + /// Returns a specific arena to allocate from. + fn arena<'a>(arena: &'a Arena<'tcx>) -> &'a TypedArena; } -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> { - None + default fn arena<'a>(_: &'a Arena<'tcx>) -> &'a TypedArena { + panic!() } } impl<'tcx> Arena<'tcx> { #[inline] - pub fn alloc>(&self, value: T) -> &mut T { - match T::arena(self) { - Some(arena) => { - arena.alloc(value) - } - None => { - self.dropless.alloc(value) - } + pub fn alloc(&self, value: T) -> &mut T { + if mem::needs_drop::() { + >::arena(self).alloc(value) + } else { + self.dropless.alloc(value) } } pub fn alloc_from_iter< - T: ArenaAllocatable<'tcx>, + T: ArenaAllocatable, I: IntoIterator >( &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::() { + >::arena(self).alloc_from_iter(iter) + } else { + self.dropless.alloc_from_iter(iter) } } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index ab44efa5decb9..c5c2cbfcb8940 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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)] diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 038cd9812e75c..3046d53086c5f 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -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>,