Skip to content

Commit f8154c2

Browse files
committed
Parameterize GcSafe by 'gc and CollectorId
We now have a very specific way to indicate that we expect a specific gc lifetime, beyond just T: 'gc. This will also allow us to begin to relax the `T: 'gc` requirement to allow short-lied references in GC types... This also gives us a clearer handling of mixing multiple collectors. Derive code is now broken....
1 parent 968ceca commit f8154c2

File tree

16 files changed

+523
-305
lines changed

16 files changed

+523
-305
lines changed

libs/context/src/collector.rs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use alloc::sync::Arc;
99

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

12-
use zerogc::{Gc, GcSafe, GcSystem, Trace, GcSimpleAlloc, NullTrace, TraceImmutable, GcVisitor, GcArray};
12+
use zerogc::{Gc, GcSafe, GcSystem, Trace, GcSimpleAlloc, NullTrace, TraceImmutable, GcVisitor, GcArray, TrustedDrop};
1313

1414
use crate::{CollectorContext};
1515
use crate::state::{CollectionManager, RawContext};
@@ -37,7 +37,7 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
3737
/// The context
3838
type RawContext: RawContext<Self>;
3939
/// The raw representation of a vec
40-
type RawVecRepr: GcVecRepr;
40+
type RawVecRepr<'gc>: GcVecRepr<'gc, Id=CollectorId<Self>>;
4141

4242
/// True if this collector is a singleton
4343
///
@@ -49,13 +49,13 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
4949
const SYNC: bool;
5050

5151
fn id_for_gc<'a, 'gc, T>(gc: &'a Gc<'gc, T, CollectorId<Self>>) -> &'a CollectorId<Self>
52-
where 'gc: 'a, T: GcSafe + ?Sized + 'gc;
52+
where 'gc: 'a, T: GcSafe<'gc, CollectorId<Self>> + ?Sized + 'gc;
5353

5454
fn id_for_array<'a, 'gc, T>(gc: &'a GcArray<'gc, T, CollectorId<Self>>) -> &'a CollectorId<Self>
55-
where 'gc: 'a, T: GcSafe + 'gc;
55+
where 'gc: 'a, T: GcSafe<'gc, CollectorId<Self>> + 'gc;
5656

5757
fn resolve_array_len<'gc, T>(gc: GcArray<'gc, T, CollectorId<Self>>) -> usize
58-
where T: GcSafe + 'gc;
58+
where T: GcSafe<'gc, CollectorId<Self>> + 'gc;
5959

6060
/// Convert the specified value into a dyn pointer
6161
unsafe fn as_dyn_trace_pointer<T: Trace>(t: *mut T) -> Self::DynTracePtr;
@@ -74,7 +74,7 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
7474
owner: &Gc<'gc, O, CollectorId<Self>>,
7575
value: &Gc<'gc, V, CollectorId<Self>>,
7676
field_offset: usize
77-
) where O: GcSafe + ?Sized + 'gc, V: GcSafe + ?Sized + 'gc;
77+
) where O: GcSafe<'gc, CollectorId<Self>> + ?Sized + 'gc, V: GcSafe<'gc, CollectorId<Self>> + ?Sized + 'gc;
7878
/// The logger associated with this collector
7979
fn logger(&self) -> &Logger;
8080

@@ -283,20 +283,20 @@ impl<C: RawCollectorImpl> CollectorId<C> {
283283
}
284284
unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
285285
type System = CollectorRef<C>;
286-
type RawVecRepr = C::RawVecRepr;
286+
type RawVecRepr<'gc> = C::RawVecRepr<'gc>;
287287

288288
#[inline]
289-
fn from_gc_ptr<'a, 'gc, T>(gc: &'a Gc<'gc, T, Self>) -> &'a Self where T: GcSafe + ?Sized + 'gc, 'gc: 'a {
289+
fn from_gc_ptr<'a, 'gc, T>(gc: &'a Gc<'gc, T, Self>) -> &'a Self where T: GcSafe<'gc, Self> + ?Sized + 'gc, 'gc: 'a {
290290
C::id_for_gc(gc)
291291
}
292292

293293
#[inline]
294-
fn resolve_array_len<'gc, T>(gc: GcArray<'gc, T, Self>) -> usize where T: GcSafe + 'gc {
294+
fn resolve_array_len<'gc, T>(gc: GcArray<'gc, T, Self>) -> usize where T: GcSafe<'gc, Self> + 'gc {
295295
C::resolve_array_len(gc)
296296
}
297297

298298
#[inline]
299-
fn resolve_array_id<'a, 'gc, T>(gc: &'a GcArray<'gc, T, Self>) -> &'a Self where T: GcSafe + 'gc, 'gc: 'a {
299+
fn resolve_array_id<'a, 'gc, T>(gc: &'a GcArray<'gc, T, Self>) -> &'a Self where T: GcSafe<'gc, Self> + 'gc, 'gc: 'a {
300300
C::id_for_array(gc)
301301
}
302302

@@ -306,7 +306,7 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
306306
owner: &Gc<'gc, O, Self>,
307307
value: &Gc<'gc, V, Self>,
308308
field_offset: usize
309-
) where O: GcSafe + ?Sized + 'gc, V: GcSafe + ?Sized + 'gc {
309+
) where O: GcSafe<'gc, Self> + ?Sized + 'gc, V: GcSafe<'gc, Self> + ?Sized + 'gc {
310310
C::gc_write_barrier(owner, value, field_offset)
311311
}
312312

@@ -320,6 +320,7 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
320320
&*(self as *const CollectorId<C> as *const CollectorRef<C>)
321321
}
322322
}
323+
unsafe impl<'gc, OtherId: zerogc::CollectorId, C: RawCollectorImpl> GcSafe<'gc, OtherId> for CollectorId<C> {}
323324
unsafe impl<C: RawCollectorImpl> Trace for CollectorId<C> {
324325
const NEEDS_TRACE: bool = false;
325326
const NEEDS_DROP: bool = false;
@@ -329,11 +330,12 @@ unsafe impl<C: RawCollectorImpl> Trace for CollectorId<C> {
329330
}
330331

331332
#[inline]
332-
unsafe fn visit_inside_gc<'gc, V, Id>(gc: &mut Gc<'gc, Self, Id>, visitor: &mut V) -> Result<(), V::Err> where V: GcVisitor, Id: zerogc::CollectorId, Self: GcSafe + 'gc {
333+
unsafe fn visit_inside_gc<'gc, V, Id>(gc: &mut Gc<'gc, Self, Id>, visitor: &mut V) -> Result<(), V::Err> where V: GcVisitor, Id: zerogc::CollectorId, Self: GcSafe<'gc, Id> {
333334
// Fine to stuff inside a pointer. We're a regular 'Sized' type
334335
visitor.visit_gc(gc)
335336
}
336337
}
338+
unsafe impl<C: RawCollectorImpl> TrustedDrop for CollectorId<C> {}
337339
unsafe impl<C: RawCollectorImpl> TraceImmutable for CollectorId<C> {
338340
#[inline(always)]
339341
fn visit_immutable<V: GcVisitor>(&self, _visitor: &mut V) -> Result<(), <V as GcVisitor>::Err> {
@@ -363,35 +365,35 @@ impl<C: RawCollectorImpl> WeakCollectorRef<C> {
363365
}
364366

365367
pub unsafe trait RawSimpleAlloc: RawCollectorImpl {
366-
unsafe fn alloc_uninit<'gc, T: GcSafe + 'gc>(context: &'gc CollectorContext<Self>) -> (CollectorId<Self>, *mut T);
368+
unsafe fn alloc_uninit<'gc, T: GcSafe<'gc, CollectorId<Self>>>(context: &'gc CollectorContext<Self>) -> (CollectorId<Self>, *mut T);
367369
unsafe fn alloc_uninit_slice<'gc, T>(context: &'gc CollectorContext<Self>, len: usize) -> (CollectorId<Self>, *mut T)
368-
where T: GcSafe + 'gc;
370+
where T: GcSafe<'gc, CollectorId<Self>>;
369371
fn alloc_vec<'gc, T>(context: &'gc CollectorContext<Self>) -> GcVec<'gc, T, CollectorContext<Self>>
370-
where T: GcSafe + 'gc;
372+
where T: GcSafe<'gc, CollectorId<Self>>;
371373
fn alloc_vec_with_capacity<'gc, T>(context: &'gc CollectorContext<Self>, capacity: usize) -> GcVec<'gc, T, CollectorContext<Self>>
372-
where T: GcSafe + 'gc;
374+
where T: GcSafe<'gc, CollectorId<Self>>;
373375
}
374376
unsafe impl<C> GcSimpleAlloc for CollectorContext<C>
375377
where C: RawSimpleAlloc {
376378
#[inline]
377379
unsafe fn alloc_uninit<'gc, T>(&'gc self) -> (CollectorId<C>, *mut T)
378-
where T: GcSafe + 'gc {
380+
where T: GcSafe<'gc, CollectorId<C>> + 'gc {
379381
C::alloc_uninit(self)
380382
}
381383

382384
#[inline]
383385
unsafe fn alloc_uninit_slice<'gc, T>(&'gc self, len: usize) -> (Self::Id, *mut T)
384-
where T: GcSafe + 'gc {
386+
where T: GcSafe<'gc, CollectorId<C>> + 'gc {
385387
C::alloc_uninit_slice(self, len)
386388
}
387389

388390
#[inline]
389-
fn alloc_vec<'gc, T>(&'gc self) -> GcVec<'gc, T, Self> where T: GcSafe + 'gc {
391+
fn alloc_vec<'gc, T>(&'gc self) -> GcVec<'gc, T, Self> where T: GcSafe<'gc, CollectorId<C>> + 'gc {
390392
C::alloc_vec(self)
391393
}
392394

393395
#[inline]
394-
fn alloc_vec_with_capacity<'gc, T>(&'gc self, capacity: usize) -> GcVec<'gc, T, Self> where T: GcSafe + 'gc {
396+
fn alloc_vec_with_capacity<'gc, T>(&'gc self, capacity: usize) -> GcVec<'gc, T, Self> where T: GcSafe<'gc, CollectorId<C>> + 'gc {
395397
C::alloc_vec_with_capacity(self, capacity)
396398
}
397399
}

libs/context/src/handle.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub unsafe trait RawHandleImpl: RawCollectorImpl {
1919
/// Type information
2020
type TypeInfo: Sized;
2121

22-
fn type_info_of<T: GcSafe>() -> &'static Self::TypeInfo;
22+
fn type_info_of<'gc, T: GcSafe<'gc, CollectorId<Self>>>() -> &'static Self::TypeInfo;
2323

2424
fn handle_list(&self) -> &GcHandleList<Self>;
2525
}
@@ -397,12 +397,12 @@ impl<C: RawHandleImpl> GcRawHandle<C> {
397397
trace(value, type_info)
398398
}
399399
}
400-
pub struct GcHandle<T: GcSafe, C: RawHandleImpl> {
400+
pub struct GcHandle<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> {
401401
inner: NonNull<GcRawHandle<C>>,
402402
collector: WeakCollectorRef<C>,
403403
marker: PhantomData<*mut T>
404404
}
405-
impl<T: GcSafe, C: RawHandleImpl> GcHandle<T, C> {
405+
impl<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> GcHandle<T, C> {
406406
#[inline]
407407
pub(crate) unsafe fn new(
408408
inner: NonNull<GcRawHandle<C>>,
@@ -414,7 +414,7 @@ impl<T: GcSafe, C: RawHandleImpl> GcHandle<T, C> {
414414
}
415415
}
416416
}
417-
unsafe impl<T: GcSafe, C: RawHandleImpl> ::zerogc::GcHandle<T> for GcHandle<T, C> {
417+
unsafe impl<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> ::zerogc::GcHandle<T> for GcHandle<T, C> {
418418
type System = CollectorRef<C>;
419419
type Id = CollectorId<C>;
420420

@@ -438,8 +438,9 @@ unsafe impl<T: GcSafe, C: RawHandleImpl> ::zerogc::GcHandle<T> for GcHandle<T, C
438438
}
439439
}
440440
unsafe impl<'new_gc, T, C> GcBindHandle<'new_gc, T> for GcHandle<T, C>
441-
where T: GcSafe, T: GcRebrand<'new_gc, CollectorId<C>>, T::Branded: Sized,
442-
T::Branded: GcSafe, C: RawHandleImpl {
441+
where T: GcSafe<'static, CollectorId<C>>, T: GcRebrand<'new_gc, CollectorId<C>>, T::Branded: Sized,
442+
T::Branded: GcSafe<'new_gc, CollectorId<C>>,
443+
C: RawHandleImpl {
443444
#[inline]
444445
fn bind_to(&self, context: &'new_gc CollectorContext<C>) -> Gc<'new_gc, T::Branded, CollectorId<C>> {
445446
/*
@@ -474,7 +475,7 @@ unsafe impl<'new_gc, T, C> GcBindHandle<'new_gc, T> for GcHandle<T, C>
474475
}
475476

476477
}
477-
unsafe impl<T: GcSafe, C: RawHandleImpl> Trace for GcHandle<T, C> {
478+
unsafe impl<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> Trace for GcHandle<T, C> {
478479
/// See docs on reachability
479480
const NEEDS_TRACE: bool = false;
480481
const NEEDS_DROP: bool = true;
@@ -486,20 +487,20 @@ unsafe impl<T: GcSafe, C: RawHandleImpl> Trace for GcHandle<T, C> {
486487

487488
#[inline]
488489
unsafe fn visit_inside_gc<'gc, V, Id>(gc: &mut Gc<'gc, Self, Id>, visitor: &mut V) -> Result<(), V::Err>
489-
where V: GcVisitor, Id: zerogc::CollectorId, Self: GcSafe + 'gc {
490+
where V: GcVisitor, Id: zerogc::CollectorId, Self: GcSafe<'gc, Id> {
490491
// Fine to stuff inside a pointer. We're a `Sized` type
491492
visitor.visit_gc(gc)
492493
}
493494
}
494-
unsafe impl<T: GcSafe, C: RawHandleImpl> TraceImmutable for GcHandle<T, C> {
495+
unsafe impl<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> TraceImmutable for GcHandle<T, C> {
495496
#[inline(always)]
496497
fn visit_immutable<V>(&self, _visitor: &mut V) -> Result<(), V::Err>
497498
where V: GcVisitor {
498499
Ok(())
499500
}
500501
}
501-
unsafe impl<T: GcSafe, C: RawHandleImpl> NullTrace for GcHandle<T, C> {}
502-
impl<T: GcSafe, C: RawHandleImpl> Clone for GcHandle<T, C> {
502+
unsafe impl<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> NullTrace for GcHandle<T, C> {}
503+
impl<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> Clone for GcHandle<T, C> {
503504
fn clone(&self) -> Self {
504505
// NOTE: Dead collector -> invalid handle
505506
let collector = self.collector
@@ -542,7 +543,7 @@ impl<T: GcSafe, C: RawHandleImpl> Clone for GcHandle<T, C> {
542543
}
543544
}
544545
}
545-
impl<T: GcSafe, C: RawHandleImpl> Drop for GcHandle<T, C> {
546+
impl<T: GcSafe<'static, CollectorId<C>>, C: RawHandleImpl> Drop for GcHandle<T, C> {
546547
fn drop(&mut self) {
547548
self.collector.try_ensure_valid(|id| {
548549
let collector = match id {
@@ -596,20 +597,20 @@ impl<T: GcSafe, C: RawHandleImpl> Drop for GcHandle<T, C> {
596597
/// This is the same reason that `Arc<T>: Send` requires `T: Sync`
597598
///
598599
/// Requires that the collector is thread-safe.
599-
unsafe impl<T: GcSafe + Sync, C: RawHandleImpl + Sync> Send for GcHandle<T, C> {}
600+
unsafe impl<T: GcSafe<'static, CollectorId<C>> + Sync, C: RawHandleImpl + Sync> Send for GcHandle<T, C> {}
600601

601602
/// If the underlying type is Sync,
602603
/// it's safe to share garbage collected references between threads.
603604
///
604605
/// Requires that the collector is thread-safe.
605-
unsafe impl<T: GcSafe + Sync, C: RawHandleImpl + Sync> Sync for GcHandle<T, C> {}
606+
unsafe impl<T: GcSafe<'static, CollectorId<C>> + Sync, C: RawHandleImpl + Sync> Sync for GcHandle<T, C> {}
606607

607608
/// We support handles
608-
unsafe impl<'gc, 'a, T, C> GcHandleSystem<'gc, 'a, T> for CollectorRef<C>
609+
unsafe impl<'gc, T, C> GcHandleSystem<'gc, T> for CollectorRef<C>
609610
where C: RawHandleImpl,
610-
T: GcSafe + 'gc,
611-
T: GcRebrand<'a, CollectorId<C>>,
612-
T::Branded: GcSafe + Sized {
611+
T: GcSafe<'gc, CollectorId<C>>,
612+
T: GcRebrand<'static, CollectorId<C>>,
613+
T::Branded: GcSafe<'static, CollectorId<C>> + Sized {
613614
type Handle = GcHandle<T::Branded, C>;
614615

615616
#[inline]

libs/context/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
negative_impls, // !Send is much cleaner than `PhantomData<Rc>`
33
untagged_unions, // I want to avoid ManuallyDrop in unions
44
const_fn_trait_bound, // So generics + const fn are unstable, huh?
5+
generic_associated_types, // Finally!
56
)]
67
#![allow(
78
clippy::missing_safety_doc, // Entirely internal code

libs/derive/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ quote = "1.0.8"
2121
proc-macro2 = "1"
2222
# Utilities for argument parsing
2323
proc-macro-kwargs = "0.1.1"
24+
# Misc
25+
indexmap = "1"
26+
itertools = "0.10.1"

libs/derive/src/lib.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,11 +441,20 @@ pub fn unsafe_gc_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream
441441
let parsed = parse_macro_input!(input as macros::MacroInput);
442442
let res = parsed.expand_output()
443443
.unwrap_or_else(|e| e.to_compile_error());
444+
let tp = match parsed.target_type {
445+
Type::Path(ref p) => Some(&p.path.segments.last().unwrap().ident),
446+
_ => None
447+
};
444448
let span_loc = span_file_loc(Span::call_site());
449+
let f = if let Some(tp) = tp {
450+
format!("unsafe_gc_impl!(target={}, ...) @ {}", tp, span_loc)
451+
} else {
452+
format!("unsafe_gc_impl! @ {}", span_loc)
453+
};
445454
debug_derive(
446455
"unsafe_gc_impl!",
447-
&span_loc,
448-
&format_args!("unsafe_gc_impl! @ {}", span_loc),
456+
&tp.map_or_else(|| span_loc.to_string(), |tp| tp.to_string()),
457+
&f,
449458
&res
450459
);
451460
res.into()

0 commit comments

Comments
 (0)