From f21881f3bbba0ca6e8f252d782d9749c03119a13 Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Thu, 4 Jun 2020 16:17:08 -0400 Subject: [PATCH] Commit new files + fix const eval error https://github.com/rust-lang/rust/issues/51910 We will have to provide the drop_in_place:: ptr upon Arena registration --- src/arena.rs | 37 ++++++++++++++ src/auto_traits.rs | 12 +++++ src/gc.rs | 36 +++++++++++++ src/lib.rs | 6 +-- src/mark.rs | 13 +++++ src/trace.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 src/arena.rs create mode 100644 src/auto_traits.rs create mode 100644 src/gc.rs create mode 100644 src/mark.rs create mode 100644 src/trace.rs diff --git a/src/arena.rs b/src/arena.rs new file mode 100644 index 0000000..881971c --- /dev/null +++ b/src/arena.rs @@ -0,0 +1,37 @@ +use super::auto_traits::*; +use super::gc::*; +use super::trace::Trace; +use super::Mark; +use std::ptr; + +pub struct Arena { + // roots: usize, + high_ptr: *const T, + capacity: u16, +} + +impl Arena { + pub fn new() -> Self { + // GC_BUS.with(|type_map| T::TRACE_TYPE_INFOtype_map.entry()); + Self { + high_ptr: ptr::null(), + capacity: 1000, + } + } + pub fn gc_alloc<'r>(&'r self, _t: T) -> Gc<'r, T> + where + T: 'r, + { + unimplemented!() + } + + pub fn advance(&mut self) -> Self { + unimplemented!() + } +} + +unsafe impl<'o, 'n, T: NoGc + Immutable> Mark<'o, 'n, T, T> for Arena { + fn mark(&'n self, o: Gc<'o, T>) -> Gc<'n, T> { + unsafe { std::mem::transmute(o) } + } +} diff --git a/src/auto_traits.rs b/src/auto_traits.rs new file mode 100644 index 0000000..02b53b4 --- /dev/null +++ b/src/auto_traits.rs @@ -0,0 +1,12 @@ +use std::cell::UnsafeCell; +use super::gc::*; + +pub unsafe auto trait NoGc {} +impl<'r, T> !NoGc for Gc<'r, T> {} +unsafe impl<'r, T: NoGc> NoGc for Box {} + +/// Shallow immutability +pub unsafe auto trait Immutable {} +impl !Immutable for &mut T {} +impl !Immutable for UnsafeCell {} +unsafe impl Immutable for Box {} diff --git a/src/gc.rs b/src/gc.rs new file mode 100644 index 0000000..5985e56 --- /dev/null +++ b/src/gc.rs @@ -0,0 +1,36 @@ +use super::auto_traits::*; +use super::trace::*; + +use std::ops::Deref; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Gc<'r, T> { + ptr: &'r T, +} + +impl<'r, T: Trace> Deref for Gc<'r, T> { + type Target = T; + fn deref(&self) -> &T { + self.ptr + } +} + +unsafe impl<'r, T: 'r + Immutable + Trace> Trace for Gc<'r, T> { + fn trace(_: usize) {} + // A Gc> is equvlent to Gc + const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); + const TRACE_CHILD_TYPE_INFO: [Option; 8] = [ + Some(GcTypeInfo::new::()), + None, + None, + None, + None, + None, + None, + None, + ]; + fn trace_transitive_type_info(tti: &mut Tti) { + tti.add_direct::(); + T::trace_transitive_type_info(tti) + } +} diff --git a/src/lib.rs b/src/lib.rs index 01d9108..f29db00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,7 +52,7 @@ struct List<'r, T> { // These three impls will be derived with a procedural macro unsafe impl<'r, T: 'r + Trace + Immutable> Trace for List<'r, T> { - fn trace(_: &List<'r, T>) {} + fn trace(_: usize) {} const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); const TRACE_CHILD_TYPE_INFO: [Option; 8] = [ Some(GcTypeInfo::new::()), @@ -107,7 +107,7 @@ struct Foo<'r> { } unsafe impl<'r> Trace for Foo<'r> { - fn trace(_: &Foo<'r>) {} + fn trace(_: usize) {} const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); const TRACE_CHILD_TYPE_INFO: [Option; 8] = GcTypeInfo::one_child::>(); fn trace_transitive_type_info(tti: &mut Tti) { @@ -180,7 +180,7 @@ fn hidden_lifetime_test() { // This may not be trivail to implement as a proc macro unsafe impl<'a, 'b: 'a> Trace for Foo2<'a, 'b> { - fn trace(_: &Foo2<'a, 'b>) {} + fn trace(_: usize) {} const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); const TRACE_CHILD_TYPE_INFO: [Option; 8] = GcTypeInfo::one_child::>>(); diff --git a/src/mark.rs b/src/mark.rs new file mode 100644 index 0000000..5dab65a --- /dev/null +++ b/src/mark.rs @@ -0,0 +1,13 @@ +use super::Gc; + +pub unsafe trait Mark<'o, 'n, O, N> { + fn mark(&'n self, o: Gc<'o, O>) -> Gc<'n, N>; +} + +// GAT Mark +// pub unsafe trait Mark<'o, 'n, O> { +// type Struct<'l>; +// fn mark(&'n self, o: Gc<'o, Self::Struct<'o>>) -> Gc<'n, Self::Struct<'n>>; +// } + +// Blanket Arena impl is in src/arena.rs diff --git a/src/trace.rs b/src/trace.rs new file mode 100644 index 0000000..79e3275 --- /dev/null +++ b/src/trace.rs @@ -0,0 +1,123 @@ +use super::auto_traits::*; + +use std::collections::HashSet; +use std::mem::*; +use std::ops::Deref; + +pub unsafe trait Trace { + fn trace(t: usize); + const TRACE_TYPE_INFO: GcTypeInfo; + const TRACE_CHILD_TYPE_INFO: [Option; 8]; + fn trace_transitive_type_info(tti: &mut Tti); +} + +// Ideally would use negative impls +// Blanket impl seems to be safe, since Mark's blanket requires NoGc +// If you only implement Mark and not Trace CHILD_TYPE_INFO will all be const None +unsafe impl Trace for T { + default fn trace(_: usize) {} + default const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); + default const TRACE_CHILD_TYPE_INFO: [Option; 8] = [None; 8]; + default fn trace_transitive_type_info(_: &mut Tti) {} +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct GcTypeInfo { + trace_ptr: fn(usize), + needs_drop: bool, + byte_size: u16, + alignment: u16, +} + +impl GcTypeInfo { + pub const fn new() -> Self { + Self { + trace_ptr: T::trace, + needs_drop: needs_drop::(), + byte_size: size_of::() as u16, + alignment: align_of::() as u16, + } + } + + pub(crate) const fn one_child() -> [Option; 8] { + [ + Some(GcTypeInfo::new::()), + None, + None, + None, + None, + None, + None, + None, + ] + } +} + +pub struct Tti { + /// Holds fn ptr of trace_transitive_type_info calls + parrents: HashSet, + type_info: HashSet, +} + +impl Tti { + pub fn new() -> Self { + Self { + parrents: HashSet::new(), + type_info: HashSet::new(), + } + } + + pub fn add_direct(&mut self) { + self.type_info + .extend(T::TRACE_CHILD_TYPE_INFO.iter().filter_map(|o| *o)); + } + + pub fn add_trans(&mut self, tti: fn(&mut Tti)) { + if self.parrents.insert(tti as *const fn(&mut Tti) as usize) { + tti(self) + } + } +} + +/// # std impls + +unsafe impl<'r, T: Immutable + Trace> Trace for Option { + default fn trace(o: usize) { + if let Some(t) = unsafe { &*(o as *const Self) } { + T::trace(t as *const T as usize) + } + } + default const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); + default const TRACE_CHILD_TYPE_INFO: [Option; 8] = GcTypeInfo::one_child::(); + default fn trace_transitive_type_info(tti: &mut Tti) { + tti.add_direct::(); + tti.add_trans(T::trace_transitive_type_info); + } +} + +unsafe impl<'r, T: Immutable + Trace + NoGc> Trace for Option { + fn trace(_: usize) {} + const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); + const TRACE_CHILD_TYPE_INFO: [Option; 8] = [None; 8]; + fn trace_transitive_type_info(_: &mut Tti) {} +} + +unsafe impl Trace for Box { + default fn trace(b: usize) { + let t = unsafe { &*(b as *const Self) }.deref(); + T::trace(t as *const T as usize) + } + default const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); + default const TRACE_CHILD_TYPE_INFO: [Option; 8] = [None; 8]; + default fn trace_transitive_type_info(_: &mut Tti) {} +} + +unsafe impl Trace for Box { + fn trace(_: usize) {} + const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::(); + const TRACE_CHILD_TYPE_INFO: [Option; 8] = GcTypeInfo::one_child::(); + fn trace_transitive_type_info(tti: &mut Tti) { + tti.add_direct::(); + tti.add_trans(T::trace_transitive_type_info); + } +}