Skip to content

Commit f21881f

Browse files
committed
Commit new files + fix const eval error
rust-lang/rust#51910 We will have to provide the drop_in_place::<T> ptr upon Arena<T> registration
1 parent 34aca3b commit f21881f

File tree

6 files changed

+224
-3
lines changed

6 files changed

+224
-3
lines changed

src/arena.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use super::auto_traits::*;
2+
use super::gc::*;
3+
use super::trace::Trace;
4+
use super::Mark;
5+
use std::ptr;
6+
7+
pub struct Arena<T> {
8+
// roots: usize,
9+
high_ptr: *const T,
10+
capacity: u16,
11+
}
12+
13+
impl<T: Trace> Arena<T> {
14+
pub fn new() -> Self {
15+
// GC_BUS.with(|type_map| T::TRACE_TYPE_INFOtype_map.entry());
16+
Self {
17+
high_ptr: ptr::null(),
18+
capacity: 1000,
19+
}
20+
}
21+
pub fn gc_alloc<'r>(&'r self, _t: T) -> Gc<'r, T>
22+
where
23+
T: 'r,
24+
{
25+
unimplemented!()
26+
}
27+
28+
pub fn advance(&mut self) -> Self {
29+
unimplemented!()
30+
}
31+
}
32+
33+
unsafe impl<'o, 'n, T: NoGc + Immutable> Mark<'o, 'n, T, T> for Arena<T> {
34+
fn mark(&'n self, o: Gc<'o, T>) -> Gc<'n, T> {
35+
unsafe { std::mem::transmute(o) }
36+
}
37+
}

src/auto_traits.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use std::cell::UnsafeCell;
2+
use super::gc::*;
3+
4+
pub unsafe auto trait NoGc {}
5+
impl<'r, T> !NoGc for Gc<'r, T> {}
6+
unsafe impl<'r, T: NoGc> NoGc for Box<T> {}
7+
8+
/// Shallow immutability
9+
pub unsafe auto trait Immutable {}
10+
impl<T> !Immutable for &mut T {}
11+
impl<T> !Immutable for UnsafeCell<T> {}
12+
unsafe impl<T> Immutable for Box<T> {}

src/gc.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use super::auto_traits::*;
2+
use super::trace::*;
3+
4+
use std::ops::Deref;
5+
6+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
7+
pub struct Gc<'r, T> {
8+
ptr: &'r T,
9+
}
10+
11+
impl<'r, T: Trace> Deref for Gc<'r, T> {
12+
type Target = T;
13+
fn deref(&self) -> &T {
14+
self.ptr
15+
}
16+
}
17+
18+
unsafe impl<'r, T: 'r + Immutable + Trace> Trace for Gc<'r, T> {
19+
fn trace(_: usize) {}
20+
// A Gc<Gc<T>> is equvlent to Gc<T>
21+
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<T>();
22+
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [
23+
Some(GcTypeInfo::new::<T>()),
24+
None,
25+
None,
26+
None,
27+
None,
28+
None,
29+
None,
30+
None,
31+
];
32+
fn trace_transitive_type_info(tti: &mut Tti) {
33+
tti.add_direct::<Self>();
34+
T::trace_transitive_type_info(tti)
35+
}
36+
}

src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct List<'r, T> {
5252

5353
// These three impls will be derived with a procedural macro
5454
unsafe impl<'r, T: 'r + Trace + Immutable> Trace for List<'r, T> {
55-
fn trace(_: &List<'r, T>) {}
55+
fn trace(_: usize) {}
5656
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
5757
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [
5858
Some(GcTypeInfo::new::<T>()),
@@ -107,7 +107,7 @@ struct Foo<'r> {
107107
}
108108

109109
unsafe impl<'r> Trace for Foo<'r> {
110-
fn trace(_: &Foo<'r>) {}
110+
fn trace(_: usize) {}
111111
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
112112
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = GcTypeInfo::one_child::<Gc<'r, usize>>();
113113
fn trace_transitive_type_info(tti: &mut Tti) {
@@ -180,7 +180,7 @@ fn hidden_lifetime_test() {
180180

181181
// This may not be trivail to implement as a proc macro
182182
unsafe impl<'a, 'b: 'a> Trace for Foo2<'a, 'b> {
183-
fn trace(_: &Foo2<'a, 'b>) {}
183+
fn trace(_: usize) {}
184184
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
185185
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] =
186186
GcTypeInfo::one_child::<Gc<'a, Bar<'b>>>();

src/mark.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use super::Gc;
2+
3+
pub unsafe trait Mark<'o, 'n, O, N> {
4+
fn mark(&'n self, o: Gc<'o, O>) -> Gc<'n, N>;
5+
}
6+
7+
// GAT Mark
8+
// pub unsafe trait Mark<'o, 'n, O> {
9+
// type Struct<'l>;
10+
// fn mark(&'n self, o: Gc<'o, Self::Struct<'o>>) -> Gc<'n, Self::Struct<'n>>;
11+
// }
12+
13+
// Blanket Arena<T> impl is in src/arena.rs

src/trace.rs

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
use super::auto_traits::*;
2+
3+
use std::collections::HashSet;
4+
use std::mem::*;
5+
use std::ops::Deref;
6+
7+
pub unsafe trait Trace {
8+
fn trace(t: usize);
9+
const TRACE_TYPE_INFO: GcTypeInfo;
10+
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8];
11+
fn trace_transitive_type_info(tti: &mut Tti);
12+
}
13+
14+
// Ideally would use negative impls
15+
// Blanket impl seems to be safe, since Mark's blanket requires NoGc
16+
// If you only implement Mark and not Trace CHILD_TYPE_INFO will all be const None
17+
unsafe impl<T: Immutable> Trace for T {
18+
default fn trace(_: usize) {}
19+
default const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
20+
default const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [None; 8];
21+
default fn trace_transitive_type_info(_: &mut Tti) {}
22+
}
23+
24+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
25+
pub struct GcTypeInfo {
26+
trace_ptr: fn(usize),
27+
needs_drop: bool,
28+
byte_size: u16,
29+
alignment: u16,
30+
}
31+
32+
impl GcTypeInfo {
33+
pub const fn new<T: Trace>() -> Self {
34+
Self {
35+
trace_ptr: T::trace,
36+
needs_drop: needs_drop::<T>(),
37+
byte_size: size_of::<T>() as u16,
38+
alignment: align_of::<T>() as u16,
39+
}
40+
}
41+
42+
pub(crate) const fn one_child<T: Trace>() -> [Option<GcTypeInfo>; 8] {
43+
[
44+
Some(GcTypeInfo::new::<T>()),
45+
None,
46+
None,
47+
None,
48+
None,
49+
None,
50+
None,
51+
None,
52+
]
53+
}
54+
}
55+
56+
pub struct Tti {
57+
/// Holds fn ptr of trace_transitive_type_info calls
58+
parrents: HashSet<usize>,
59+
type_info: HashSet<GcTypeInfo>,
60+
}
61+
62+
impl Tti {
63+
pub fn new() -> Self {
64+
Self {
65+
parrents: HashSet::new(),
66+
type_info: HashSet::new(),
67+
}
68+
}
69+
70+
pub fn add_direct<T: Trace>(&mut self) {
71+
self.type_info
72+
.extend(T::TRACE_CHILD_TYPE_INFO.iter().filter_map(|o| *o));
73+
}
74+
75+
pub fn add_trans(&mut self, tti: fn(&mut Tti)) {
76+
if self.parrents.insert(tti as *const fn(&mut Tti) as usize) {
77+
tti(self)
78+
}
79+
}
80+
}
81+
82+
/// # std impls
83+
84+
unsafe impl<'r, T: Immutable + Trace> Trace for Option<T> {
85+
default fn trace(o: usize) {
86+
if let Some(t) = unsafe { &*(o as *const Self) } {
87+
T::trace(t as *const T as usize)
88+
}
89+
}
90+
default const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
91+
default const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = GcTypeInfo::one_child::<T>();
92+
default fn trace_transitive_type_info(tti: &mut Tti) {
93+
tti.add_direct::<Self>();
94+
tti.add_trans(T::trace_transitive_type_info);
95+
}
96+
}
97+
98+
unsafe impl<'r, T: Immutable + Trace + NoGc> Trace for Option<T> {
99+
fn trace(_: usize) {}
100+
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
101+
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [None; 8];
102+
fn trace_transitive_type_info(_: &mut Tti) {}
103+
}
104+
105+
unsafe impl<T: Immutable + Trace> Trace for Box<T> {
106+
default fn trace(b: usize) {
107+
let t = unsafe { &*(b as *const Self) }.deref();
108+
T::trace(t as *const T as usize)
109+
}
110+
default const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
111+
default const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = [None; 8];
112+
default fn trace_transitive_type_info(_: &mut Tti) {}
113+
}
114+
115+
unsafe impl<T: Immutable + Trace + NoGc> Trace for Box<T> {
116+
fn trace(_: usize) {}
117+
const TRACE_TYPE_INFO: GcTypeInfo = GcTypeInfo::new::<Self>();
118+
const TRACE_CHILD_TYPE_INFO: [Option<GcTypeInfo>; 8] = GcTypeInfo::one_child::<T>();
119+
fn trace_transitive_type_info(tti: &mut Tti) {
120+
tti.add_direct::<Self>();
121+
tti.add_trans(T::trace_transitive_type_info);
122+
}
123+
}

0 commit comments

Comments
 (0)