Skip to content

Commit 64b8f99

Browse files
committed
Experimental: Support for const Deref
1 parent d8fa323 commit 64b8f99

File tree

9 files changed

+233
-88
lines changed

9 files changed

+233
-88
lines changed

libs/context/src/collector.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@ use alloc::sync::Arc;
99

1010
use slog::{Logger, o};
1111

12-
use zerogc::{Gc, GcSafe, GcSystem, Trace, GcSimpleAlloc, NullTrace, TraceImmutable, GcVisitor, TrustedDrop};
12+
use zerogc::array::repr::ThinArrayRepr;
13+
use zerogc::{Gc, GcSafe, GcSimpleAlloc, GcSystem, GcVisitor, NullTrace, Trace, TraceImmutable, TrustedDrop};
1314

1415
use crate::{CollectorContext};
1516
use crate::state::{CollectionManager, RawContext};
1617
use zerogc::vec::GcVec;
1718
use zerogc::vec::repr::GcVecRepr;
1819
use std::hash::{Hasher, Hash};
1920

21+
22+
pub unsafe trait ConstRawCollectorImpl: RawCollectorImpl {
23+
fn resolve_array_len_const<'gc, T>(gc: &ThinArrayRepr<'gc, T, CollectorId<Self>>) -> usize
24+
where T: 'gc;
25+
}
26+
2027
/// A specific implementation of a collector
2128
pub unsafe trait RawCollectorImpl: 'static + Sized {
2229
/// A dynamic pointer to a `Trace` root
@@ -56,10 +63,11 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
5663

5764
fn id_for_array<'a, 'gc, T>(gc: &'a <CollectorId<Self> as zerogc::CollectorId>::ArrayRepr<'gc, T>) -> &'a CollectorId<Self>
5865
where 'gc: 'a, T: 'gc;
59-
60-
fn resolve_array_len<'gc, T>(gc: <CollectorId<Self> as zerogc::CollectorId>::ArrayRepr<'gc, T>) -> usize
66+
67+
fn resolve_array_len<'gc, T>(repr: &ThinArrayRepr<'gc, T, CollectorId<Self>>) -> usize
6168
where T: 'gc;
6269

70+
6371
/// Convert the specified value into a dyn pointer
6472
unsafe fn as_dyn_trace_pointer<T: Trace>(t: *mut T) -> Self::DynTracePtr;
6573

@@ -306,6 +314,11 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
306314
C::id_for_array(gc)
307315
}
308316

317+
#[inline]
318+
fn resolve_array_len<'gc, T>(repr: &ThinArrayRepr<'gc, T, Self>) -> usize
319+
where T: 'gc {
320+
C::resolve_array_len(repr)
321+
}
309322

310323
#[inline(always)]
311324
unsafe fn gc_write_barrier<'gc, O, V>(
@@ -326,10 +339,10 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
326339
&*(self as *const CollectorId<C> as *const CollectorRef<C>)
327340
}
328341
}
329-
unsafe impl<C: RawCollectorImpl> zerogc::array::repr::ThinArrayGcAccess for CollectorId<C> {
342+
unsafe impl<C: ~const ConstRawCollectorImpl> const zerogc::internals::ConstCollectorId for CollectorId<C> {
330343
#[inline]
331-
fn resolve_array_len<'gc, T>(gc: Self::ArrayRepr<'gc, T>) -> usize where T: 'gc {
332-
C::resolve_array_len(gc)
344+
fn resolve_array_len_const<'gc, T>(repr: &Self::ArrayRepr<'gc, T>) -> usize where T: 'gc {
345+
C::resolve_array_len_const(repr)
333346
}
334347
}
335348
unsafe impl<'gc, OtherId: zerogc::CollectorId, C: RawCollectorImpl> GcSafe<'gc, OtherId> for CollectorId<C> {}

libs/context/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
untagged_unions, // I want to avoid ManuallyDrop in unions
44
const_fn_trait_bound, // So generics + const fn are unstable, huh?
55
generic_associated_types, // Finally!
6+
const_trait_impl,
67
)]
78
#![allow(
89
clippy::missing_safety_doc, // Entirely internal code

libs/simple/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ unsafe impl ::zerogc_context::collector::RawCollectorImpl for RawSimpleCollector
662662
}
663663

664664
#[inline]
665-
fn resolve_array_len<'gc, T>(gc: ThinArrayRepr<'gc, T, CollectorId>) -> usize where T: 'gc {
665+
fn resolve_array_len<'gc, T>(gc: &ThinArrayRepr<'gc, T, CollectorId>) -> usize where T: 'gc {
666666
unsafe {
667667
let header = GcArrayHeader::LAYOUT.from_value_ptr(gc.as_raw_ptr());
668668
(*header).len

src/array.rs

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use core::str;
66
use core::fmt::{self, Formatter, Debug, Display};
77
use core::hash::{Hash, Hasher};
88

9-
use crate::{CollectorId, GcSafe, GcRebrand};
9+
use crate::{CollectorId, internals::ConstCollectorId, GcSafe, GcRebrand};
1010
use zerogc_derive::{Trace, unsafe_gc_impl};
1111

12-
use self::repr::GcArrayRepr;
12+
use self::repr::{GcArrayRepr};
1313

1414
pub mod repr;
1515

@@ -48,12 +48,12 @@ impl<'gc, Id: CollectorId> GcString<'gc, Id> {
4848
/// Undefined behavior if the bytes aren't valid
4949
/// UTF8, just like with [core::str::from_utf8_unchecked]
5050
#[inline]
51-
pub unsafe fn from_utf8_unchecked(bytes: GcArray<'gc, u8, Id>) -> Self {
51+
pub const unsafe fn from_utf8_unchecked(bytes: GcArray<'gc, u8, Id>) -> Self {
5252
GcString { bytes }
5353
}
5454
/// Retrieve this string as a raw array of bytes
5555
#[inline]
56-
pub fn as_bytes(&self) -> GcArray<'gc, u8, Id> {
56+
pub const fn as_bytes(&self) -> GcArray<'gc, u8, Id> {
5757
self.bytes
5858
}
5959
/// Convert this string into a slice of bytes
@@ -62,6 +62,29 @@ impl<'gc, Id: CollectorId> GcString<'gc, Id> {
6262
unsafe { str::from_utf8_unchecked(self.as_bytes().as_slice()) }
6363
}
6464
}
65+
/// Const access to [GcString]
66+
pub trait ConstStringAccess<'gc> {
67+
/// Get this string as a slice of bytes
68+
fn as_bytes_const(&self) -> &'gc [u8];
69+
/// Convert this string to a `str` slice
70+
fn as_str_const(&self) -> &'gc str;
71+
/// Get the length of this string (in bytes)
72+
fn len_const(&self) -> usize;
73+
}
74+
impl<'gc, Id: ~const ConstCollectorId> const ConstStringAccess<'gc> for GcString<'gc, Id> {
75+
#[inline]
76+
fn as_bytes_const(&self) -> &'gc [u8] {
77+
self.bytes.as_slice_const()
78+
}
79+
#[inline]
80+
fn as_str_const(&self) -> &'gc str {
81+
unsafe { str::from_utf8_unchecked(self.as_bytes_const()) }
82+
}
83+
#[inline]
84+
fn len_const(&self) -> usize {
85+
self.bytes.len_const()
86+
}
87+
}
6588
impl<'gc, Id: CollectorId> Deref for GcString<'gc, Id> {
6689
type Target = str;
6790
#[inline]
@@ -92,28 +115,16 @@ impl<'gc, Id: CollectorId> Display for GcString<'gc, Id> {
92115
pub struct GcArray<'gc, T: 'gc, Id: CollectorId> {
93116
repr: Id::ArrayRepr<'gc, T>
94117
}
95-
impl<'gc, T: GcSafe<'gc, Id>, Id: CollectorId> GcArray<'gc, T, Id> {
96-
/// Create an array from the specified raw pointer and length
97-
///
98-
/// ## Safety
99-
/// Pointer and length must be valid, and point to a garbage collected
100-
/// value allocated from the corresponding [CollectorId]
101-
#[inline]
102-
pub unsafe fn from_raw_ptr(ptr: NonNull<T>, len: usize) -> Self {
103-
GcArray { repr: Id::ArrayRepr::<'gc, T>::from_raw_parts(ptr, len) }
104-
}
105-
}
106-
// Relax T: GcSafe bound
107118
impl<'gc, T, Id: CollectorId> GcArray<'gc, T, Id> {
108-
/// The value of the array as a slice
119+
/// Convert this array into a slice
109120
#[inline]
110-
pub fn as_slice(self) -> &'gc [T] {
121+
pub fn as_slice(&self) -> &'gc [T] {
111122
self.repr.as_slice()
112123
}
113124
/// Load a raw pointer to the array's value
114125
#[inline]
115-
pub fn as_raw_ptr(self) -> *mut T {
116-
self.repr.as_raw_ptr()
126+
pub fn as_raw_ptr(&self) -> *mut T {
127+
self.as_slice().as_ptr() as *mut T
117128
}
118129
/// Load the length of the array
119130
#[inline]
@@ -123,7 +134,7 @@ impl<'gc, T, Id: CollectorId> GcArray<'gc, T, Id> {
123134
/// Check if the array is empty
124135
#[inline]
125136
pub fn is_empty(&self) -> bool {
126-
self.repr.is_empty()
137+
self.len() == 0
127138
}
128139
/// Resolve the [CollectorId]
129140
#[inline]
@@ -135,6 +146,68 @@ impl<'gc, T, Id: CollectorId> GcArray<'gc, T, Id> {
135146
pub fn as_raw_repr(&self) -> &Id::ArrayRepr<'gc, T> {
136147
&self.repr
137148
}
149+
/// Create an array from the specified raw pointer and length
150+
///
151+
/// ## Safety
152+
/// Pointer and length must be valid, and point to a garbage collected
153+
/// value allocated from the corresponding [CollectorId]
154+
#[inline]
155+
pub unsafe fn from_raw_ptr(ptr: NonNull<T>, len: usize) -> Self {
156+
GcArray { repr: Id::ArrayRepr::<'gc, T>::from_raw_parts(ptr, len) }
157+
}
158+
}
159+
/// Const access to [GcString]
160+
pub trait ConstArrayAccess<'gc, T> {
161+
/// The value of the array as a slice
162+
fn as_slice_const(&self) -> &'gc [T];
163+
/// Load a raw pointer to the array's value
164+
fn as_raw_ptr_const(&self) -> *mut T;
165+
/// The length of this array
166+
fn len_const(&self) -> usize;
167+
}
168+
// Relax T: GcSafe bound
169+
impl<'gc, T, Id: ~const ConstCollectorId> const ConstArrayAccess<'gc, T> for GcArray<'gc, T, Id> {
170+
#[inline]
171+
fn as_slice_const(&self) -> &'gc [T] {
172+
/*
173+
* TODO: This is horrible, but currently nessicarry
174+
* to do this in a const-fn context.
175+
*/
176+
match Id::ArrayRepr::<'gc, T>::UNCHECKED_KIND {
177+
repr::ArrayReprKind::Fat => {
178+
unsafe {
179+
core::mem::transmute_copy::<
180+
Id::ArrayRepr<'gc, T>,
181+
&'gc [T]
182+
>(&self.repr)
183+
}
184+
},
185+
repr::ArrayReprKind::Thin => {
186+
unsafe {
187+
let ptr = core::mem::transmute_copy::<
188+
Id::ArrayRepr<'gc, T>,
189+
NonNull<T>
190+
>(&self.repr);
191+
&*core::ptr::slice_from_raw_parts(
192+
ptr.as_ptr(),
193+
Id::resolve_array_len_const(
194+
&self.repr
195+
)
196+
)
197+
}
198+
},
199+
}
200+
}
201+
/// Load a raw pointer to the array's value
202+
#[inline]
203+
fn as_raw_ptr_const(&self) -> *mut T {
204+
self.as_slice_const().as_ptr() as *mut T
205+
}
206+
/// Load the length of the array
207+
#[inline]
208+
fn len_const(&self) -> usize {
209+
self.as_slice_const().len()
210+
}
138211
}
139212
impl<'gc, T, Id: CollectorId> Deref for GcArray<'gc, T, Id> {
140213
type Target = [T];
@@ -192,7 +265,7 @@ impl<'gc, T: Hash, Id: CollectorId> Hash for GcArray<'gc, T, Id> {
192265
fn hash<H: Hasher>(&self, hasher: &mut H) {
193266
T::hash_slice(self.as_slice(), hasher)
194267
}
195-
}
268+
}
196269
// Need to implement by hand, because [T] is not GcRebrand
197270
unsafe_gc_impl!(
198271
target => GcArray<'gc, T, Id>,

0 commit comments

Comments
 (0)