Skip to content

Commit

Permalink
Commit new files + fix const eval error
Browse files Browse the repository at this point in the history
rust-lang/rust#51910
We will have to provide the drop_in_place::<T> ptr upon Arena<T> registration
  • Loading branch information
Avi-D-coder committed Jun 4, 2020
1 parent 34aca3b commit f21881f
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 3 deletions.
37 changes: 37 additions & 0 deletions src/arena.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use super::auto_traits::*;
use super::gc::*;
use super::trace::Trace;
use super::Mark;
use std::ptr;

pub struct Arena<T> {
// roots: usize,
high_ptr: *const T,
capacity: u16,
}

impl<T: Trace> Arena<T> {
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<T> {
fn mark(&'n self, o: Gc<'o, T>) -> Gc<'n, T> {
unsafe { std::mem::transmute(o) }
}
}
12 changes: 12 additions & 0 deletions src/auto_traits.rs
Original file line number Diff line number Diff line change
@@ -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<T> {}

/// Shallow immutability
pub unsafe auto trait Immutable {}
impl<T> !Immutable for &mut T {}
impl<T> !Immutable for UnsafeCell<T> {}
unsafe impl<T> Immutable for Box<T> {}
36 changes: 36 additions & 0 deletions src/gc.rs
Original file line number Diff line number Diff line change
@@ -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<Gc<T>> is equvlent to Gc<T>
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<T>();
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [
Some(GcTypeInfo::new::<T>()),
None,
None,
None,
None,
None,
None,
None,
];
fn trace_transitive_type_info(tti: &mut Tti) {
tti.add_direct::<Self>();
T::trace_transitive_type_info(tti)
}
}
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Self>();
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [
Some(GcTypeInfo::new::<T>()),
Expand Down Expand Up @@ -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::<Self>();
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = GcTypeInfo::one_child::<Gc<'r, usize>>();
fn trace_transitive_type_info(tti: &mut Tti) {
Expand Down Expand Up @@ -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::<Self>();
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] =
GcTypeInfo::one_child::<Gc<'a, Bar<'b>>>();
Expand Down
13 changes: 13 additions & 0 deletions src/mark.rs
Original file line number Diff line number Diff line change
@@ -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<T> impl is in src/arena.rs
123 changes: 123 additions & 0 deletions src/trace.rs
Original file line number Diff line number Diff line change
@@ -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<GcTypeInfo>; 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<T: Immutable> Trace for T {
default fn trace(_: usize) {}
default const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
default const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 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<T: Trace>() -> Self {
Self {
trace_ptr: T::trace,
needs_drop: needs_drop::<T>(),
byte_size: size_of::<T>() as u16,
alignment: align_of::<T>() as u16,
}
}

pub(crate) const fn one_child<T: Trace>() -> [Option<GcTypeInfo>; 8] {
[
Some(GcTypeInfo::new::<T>()),
None,
None,
None,
None,
None,
None,
None,
]
}
}

pub struct Tti {
/// Holds fn ptr of trace_transitive_type_info calls
parrents: HashSet<usize>,
type_info: HashSet<GcTypeInfo>,
}

impl Tti {
pub fn new() -> Self {
Self {
parrents: HashSet::new(),
type_info: HashSet::new(),
}
}

pub fn add_direct<T: Trace>(&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<T> {
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::<Self>();
default const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = GcTypeInfo::one_child::<T>();
default fn trace_transitive_type_info(tti: &mut Tti) {
tti.add_direct::<Self>();
tti.add_trans(T::trace_transitive_type_info);
}
}

unsafe impl<'r, T: Immutable + Trace + NoGc> Trace for Option<T> {
fn trace(_: usize) {}
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [None; 8];
fn trace_transitive_type_info(_: &mut Tti) {}
}

unsafe impl<T: Immutable + Trace> Trace for Box<T> {
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::<Self>();
default const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [None; 8];
default fn trace_transitive_type_info(_: &mut Tti) {}
}

unsafe impl<T: Immutable + Trace + NoGc> Trace for Box<T> {
fn trace(_: usize) {}
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = GcTypeInfo::one_child::<T>();
fn trace_transitive_type_info(tti: &mut Tti) {
tti.add_direct::<Self>();
tti.add_trans(T::trace_transitive_type_info);
}
}

0 comments on commit f21881f

Please sign in to comment.