about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-03-30 01:36:51 +0100
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-04-05 00:55:07 +0200
commite835d27ad3f464bf81e5b702c1412be09761c991 (patch)
tree62303ea3b87402dfaed6439056001eead0679b26
parent002c70f2d46e80fcb02ee4214d9a4d4041ee011c (diff)
downloadrust-e835d27ad3f464bf81e5b702c1412be09761c991.tar.gz
rust-e835d27ad3f464bf81e5b702c1412be09761c991.zip
Make ArenaAllocatable a marker trait to allow overlapping impls and use specialization to find the right field
-rw-r--r--src/librustc/arena.rs51
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/ty/codec.rs4
3 files changed, 28 insertions, 28 deletions
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index 23493d5c93f..1f1060ee243 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<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)
         }
     }
 }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index ab44efa5dec..c5c2cbfcb89 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 038cd9812e7..3046d53086c 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>,