zerogc/lib.rs
1// NOTE: Both these features have accepted RFCs
2#![feature(
3 const_panic, // RFC 2345 - Const asserts
4)]
5#![deny(missing_docs)]
6#![cfg_attr(not(feature = "std"), no_std)]
7//! Zero overhead tracing garbage collection for rust,
8//! by abusing the borrow checker.
9//!
10//! ## Features
11//! 1. Easy to use, since `Gc<T>` is `Copy` and coerces to a reference.
12//! 2. Absolutely zero overhead when modifying pointers, since `Gc<T>` is `Copy`.
13//! 3. Implementation agnostic API
14//! 4. Unsafe code has complete freedom to manipulate garbage collected pointers, and it doesn't need to understand the distinction
15//! 5. Uses rust's lifetime system to ensure all roots are known at explicit safepoints, without any runtime overhead.
16//! 6. Collection can only happen with an explicit `safepoint` call and has no overhead between these calls,
17//! 7. API supports moving objects (allowing copying/generational GCs)
18
19#![cfg(any(feature = "alloc", feature = "std"))]
20extern crate alloc;
21
22/*
23 * I want this library to use 'mostly' stable features,
24 * unless there's good justification to use an unstable feature.
25 */
26use core::mem;
27use core::ops::{Deref, DerefMut};
28use core::ptr::NonNull;
29use core::marker::PhantomData;
30use core::hash::{Hash, Hasher};
31use core::fmt::{self, Debug, Formatter};
32
33#[macro_use]
34mod manually_traced;
35pub mod cell;
36pub mod prelude;
37
38/// Invoke the closure with a temporary [GcContext],
39/// then perform a safepoint afterwards.
40///
41/// Normally returns a tuple `($updated_root, $closure_result)`.
42///
43/// If a value is provided it is considered as a root of garbage collection
44/// both for the safepoint and the duration of the entire context.
45///
46/// # Safety
47/// This macro is completely safe, although it expands to unsafe code internally.
48// TODO: Document all forms of this macro
49#[macro_export(local_inner_macros)]
50macro_rules! safepoint_recurse {
51 ($context:ident, |$sub_context:ident| $closure:expr) => {{
52 let ((), result) = safepoint_recurse!($context, (), |$sub_context, new_root| {
53 let () = new_root;
54 $closure
55 });
56 result
57 }};
58 ($context:ident, $root:expr, |$sub_context:ident, $new_root:ident| $closure:expr) => {{
59 let mut root = $root;
60 let result = unsafe { __recurse_context!($context, &mut root, |$sub_context, $new_root| {
61 $closure
62 }) };
63 /*
64 * NOTE: We're assuming result is unmanaged here
65 * The borrow checker will verify this is true (by marking this as a mutation).
66 * If you need a manged result, use the @managed_result variant
67 */
68 let updated_root = safepoint!($context, $root);
69 (updated_root, result)
70 }};
71 ($context:ident, $root:expr, @managed_result, |$sub_context:ident, $new_root:ident| $closure:expr) => {{
72 use $crate::{GcContext};
73 let mut root = $root;
74 let erased_result = unsafe { __recurse_context!(
75 $context, &mut root,
76 |$sub_context, $new_root| {
77 let result = $closure;
78 $sub_context.rebrand_static(result)
79 }
80 ) };
81 /*
82 * Rebrand back to the current collector lifetime
83 * It could have possibly been allocated from the sub-context inside the closure,
84 * but as long as it was valid at the end of the closure it's valid now.
85 * We trust that GcContext::recurse_context
86 * did not perform a collection after calling the closure.
87 */
88 let result = unsafe { $context.rebrand_self(erased_result) };
89 safepoint!($context, (root, result))
90 }};
91}
92
93/// Create a new sub-context for the duration of the closure
94///
95/// The specified `root` object will be appended to the shadowstack
96/// and is guarenteed to live for the entire lifetime of the closure (and the created sub-context).
97///
98/// Unlike `safepoint_recurse!` this doesn't imply a safepoint anywhere.
99///
100/// # Safety
101/// This doesn't actually mutate the original collector.
102/// It is possible user code could trigger a collection in the closure
103/// without the borrow checker noticing invalid pointers elsewhere.
104/// (See docs for [GcContext::recurse_context])
105///
106/// It is not publicly exposed for this reason
107#[macro_export]
108#[doc(hidden)]
109macro_rules! __recurse_context {
110 ($context:ident, $root:expr, |$sub_context:ident, $new_root:ident| $closure:expr) => {{
111 use $crate::{GcContext};
112 // TODO: Panic safety
113 $context.recurse_context(&mut $root, |mut $sub_context, erased_root| {
114 /*
115 * NOTE: Guarenteed to live for the lifetime of the entire closure.
116 * However, it could be relocated if 'sub_collector' is collected
117 */
118 let $new_root = $sub_context.rebrand_self(erased_root);
119 $closure
120 })
121 }};
122}
123
124/// Indicate it's safe to begin a garbage collection,
125/// while keeping the specified root alive.
126///
127/// All other garbage collected pointers that aren't reachable from the root are invalidated.
128/// They have a lifetime that references the [GcRef]
129/// and the borrow checker considers the safepoint a 'mutation'.
130///
131/// The root is exempted from the "mutation" and rebound to the new lifetime.
132///
133/// ## Example
134/// ```
135/// let root = safepoint!(collector, root);
136/// ```
137///
138/// ## Safety
139/// This macro is completely safe, although it expands to unsafe code internally.
140#[macro_export]
141macro_rules! safepoint {
142 ($context:ident, $value:expr) => {unsafe {
143 use $crate::{GcContext};
144 // TODO: What happens if we panic during a collection
145 /*
146 * Some collectors support multiple running instances
147 * with different ids, handing out different GC pointers.
148 * TODO: Should we be checking somehow that the ids match?
149 */
150 let mut erased = $context.rebrand_static($value);
151 $context.basic_safepoint(&mut &mut erased);
152 $context.rebrand_self(erased)
153 }};
154}
155
156/// Indicate its safe to begin a garbage collection (like [safepoint!])
157/// and then "freeze" the specified context.
158///
159/// Until it's unfrozen, the context can't be used for allocation.
160/// Its roots are marked invalid, since the collector could be relocating them.
161/// However, the roots of any parent contexts are still considered valid.
162///
163/// This allows other threads to perform collections *without blocking this thread*.
164#[macro_export]
165macro_rules! freeze_context {
166 ($context:ident) => {unsafe {
167 use $crate::{GcContext, FrozenContext};
168 let mut context = $context;
169 context.freeze();
170 FrozenContext::new(context)
171 }};
172}
173
174/// Unfreeze the context, allowing it to be used again
175///
176/// Returns a [GcContext] struct.
177#[macro_export]
178macro_rules! unfreeze_context {
179 ($frozen:ident) => {unsafe {
180 use $crate::{FrozenContext, GcContext};
181 let mut context = FrozenContext::into_context($frozen);
182 context.unfreeze();
183 context
184 }};
185}
186
187/// A garbage collector implementation.
188///
189/// These implementations should be completely safe and zero-overhead.
190pub unsafe trait GcSystem {
191 /// The type of collector IDs given by this system
192 type Id: CollectorId;
193 /// The type of contexts used in this sytem
194 type Context: GcContext<Id=Self::Id>;
195}
196
197
198/// A system which supports creating handles to [Gc] references.
199///
200/// This type-system hackery is needed because
201/// we need to place bounds on `T as GcBrand`
202// TODO: Remove when we get more powerful types
203pub unsafe trait GcHandleSystem<'gc, T: GcSafe + ?Sized + 'gc>: GcSystem
204 where T: GcBrand<'static, Self::Id>,
205 <T as GcBrand<'static, Self::Id>>::Branded: GcSafe {
206 /// The type of handles to this object.
207 type Handle: GcHandle<<T as GcBrand<'static, Self::Id>>::Branded, System=Self>;
208
209 /// Create a handle to the specified GC pointer,
210 /// which can be used without a context
211 ///
212 /// NOTE: Users should only use from [Gc::create_handle].
213 ///
214 /// The system is implicit in the [Gc]
215 #[doc(hidden)]
216 fn create_handle(gc: Gc<'gc, T, Self::Id>) -> Self::Handle;
217}
218
219/// The context of garbage collection,
220/// which can be frozen at a safepoint.
221///
222/// This is essentially used to maintain a shadow-stack to a set of roots,
223/// which are guarenteed not to be collected until a safepoint.
224///
225/// This context doesn't necessarily support allocation (see [GcSimpleAlloc] for that).
226pub unsafe trait GcContext: Sized {
227 /// The system used with this context
228 type System: GcSystem<Context=Self, Id=Self::Id>;
229 /// The type of ids used in the system
230 type Id: CollectorId;
231
232 /// Inform the garbage collection system we are at a safepoint
233 /// and are ready for a potential garbage collection.
234 ///
235 /// ## Safety
236 /// This method is unsafe and should never be invoked by user code.
237 ///
238 /// See the [safepoint!] macro for a safe wrapper.
239 unsafe fn basic_safepoint<T: Trace>(&mut self, value: &mut &mut T);
240
241 /// Inform the garbage collection system we are at a safepoint
242 /// and are ready for a potential garbage collection.
243 ///
244 /// Unlike a `basic_safepoint`, the collector continues to
245 /// stay at the safepoint instead of returning immediately.
246 /// The context can't be used for anything (including allocations),
247 /// until it is unfrozen.
248 ///
249 /// This allows other threds to perform collections while this
250 /// thread does other work (without using the GC).
251 ///
252 /// The current contexts roots are considered invalid
253 /// for the duration of the collection,
254 /// since the collector could potentially relocate them.
255 ///
256 /// Any parent contexts are fine and their roots will be
257 /// preserved by collections.
258 ///
259 /// ## Safety
260 /// Assumes this context is valid and not already frozen.
261 ///
262 /// Don't invoke this directly
263 unsafe fn freeze(&mut self);
264
265 /// Unfreeze this context, allowing it to be used again.
266 ///
267 /// ## Safety
268 /// Must be a valid context!
269 /// Must be currently frozen!
270 ///
271 /// Don't invoke this directly
272 unsafe fn unfreeze(&mut self);
273
274 #[inline(always)]
275 #[doc(hidden)]
276 unsafe fn rebrand_static<T>(&self, value: T) -> T::Branded
277 where T: GcBrand<'static, Self::Id> {
278 let branded = mem::transmute_copy(&value);
279 mem::forget(value);
280 branded
281 }
282 #[inline(always)]
283 #[doc(hidden)]
284 unsafe fn rebrand_self<'a, T>(&'a self, value: T) -> T::Branded
285 where T: GcBrand<'a, Self::Id> {
286 let branded = mem::transmute_copy(&value);
287 mem::forget(value);
288 branded
289 }
290
291 /// Invoke the closure with a temporary [GcContext].
292 ///
293 /// The specified value is
294 /// guarenteed to live throughout the created context for the closure.
295 /// However, because it could possibly be relocated by a collection,
296 /// it's bound to the lifetime of the sub-collector.
297 ///
298 /// ## Safety
299 /// This macro doesn't imply garbage collection,
300 /// so it doesn't mutate the collector directly.
301 /// However the specified closure could trigger a collection in the sub-context.
302 /// This would in undefined behavior if the collection
303 /// invalidates a pointer tied to this context.
304 ///
305 /// For this reason, this function should never be invoked by user code.
306 ///
307 /// See the [safepoint_recurse!] macro for a safe wrapper
308 unsafe fn recurse_context<T, F, R>(&self, value: &mut &mut T, func: F) -> R
309 where T: Trace, F: for <'gc> FnOnce(&'gc mut Self, &'gc mut T) -> R;
310}
311/// A simple interface to allocating from a [GcContext].
312///
313/// Some garbage collectors implement more complex interfaces,
314/// so implementing this is optional
315pub unsafe trait GcSimpleAlloc<'gc, T: GcSafe + 'gc>: GcContext + 'gc {
316 /// Allocate the specified object in this garbage collector,
317 /// binding it to the lifetime of this collector.
318 ///
319 /// The object will never be collected until the next safepoint,
320 /// which is considered a mutation by the borrow checker and will be statically checked.
321 /// Therefore, we can statically guarantee the pointers will survive until the next safepoint.
322 ///
323 /// See `safepoint!` docs on how to properly invoke a safepoint
324 /// and transfer values across it.
325 ///
326 /// This gives a immutable reference to the resulting object.
327 /// Once allocated, the object can only be correctly modified with a `GcCell`
328 fn alloc(&'gc self, value: T) -> Gc<'gc, T, Self::Id>;
329}
330/// The internal representation of a frozen context
331///
332/// ## Safety
333/// Don't use this directly!!!
334#[doc(hidden)]
335#[must_use]
336pub struct FrozenContext<C: GcContext> {
337 /// The frozen context
338 context: C,
339}
340impl<C: GcContext> FrozenContext<C> {
341 #[doc(hidden)]
342 #[inline]
343 pub unsafe fn new(context: C) -> Self {
344 FrozenContext { context }
345 }
346 #[doc(hidden)]
347 #[inline]
348 pub unsafe fn into_context(self) -> C {
349 self.context
350 }
351}
352
353/// Uniquely identifies the collector in case there are
354/// multiple collectors.
355///
356/// ## Safety
357/// To simply the typing, this contains no references to the
358/// lifetime of the associated [GcSystem].
359///
360/// It's implicitly held and is unsafe to access.
361/// As long as the collector is valid,
362/// this id should be too.
363///
364/// It should be safe to assume that a collector exists
365/// if any of its pointers still do!
366pub unsafe trait CollectorId: Copy + Eq + Debug + NullTrace + 'static {
367 /// The type of the garbage collector system
368 type System: GcSystem<Id=Self>;
369 /// Perform a write barrier before writing to a garbage collected field
370 ///
371 /// ## Safety
372 /// Smilar to the [GcDirectBarrier] trait, it can be assumed that
373 /// the field offset is correct and the types match.
374 unsafe fn gc_write_barrier<'gc, T: GcSafe + ?Sized + 'gc, V: GcSafe + ?Sized + 'gc>(
375 owner: &Gc<'gc, T, Self>,
376 value: &Gc<'gc, V, Self>,
377 field_offset: usize
378 );
379
380 /// Assume the ID is valid and use it to access the [GcSystem]
381 ///
382 /// NOTE: The system is bound to the lifetime of *THIS* id.
383 /// A CollectorId may have an internal pointer to the system
384 /// and the pointer may not have a stable address. In other words,
385 /// it may be difficult to reliably take a pointer to a pointer.
386 ///
387 /// ## Safety
388 /// Undefined behavior if the associated collector no longer exists.
389 unsafe fn assume_valid_system(&self) -> &Self::System;
390}
391
392/// A garbage collected pointer to a value.
393///
394/// This is the equivalent of a garbage collected smart-pointer.
395/// It's so smart, you can even coerce it to a reference bound to the lifetime of the `GarbageCollectorRef`.
396/// However, all those references are invalidated by the borrow checker as soon as
397/// your reference to the collector reaches a safepoint.
398/// The objects can only survive garbage collection if they live in this smart-pointer.
399///
400/// The smart pointer is simply a guarantee to the garbage collector
401/// that this points to a garbage collected object with the correct header,
402/// and not some arbitrary bits that you've decided to heap allocate.
403#[repr(C)]
404pub struct Gc<'gc, T: GcSafe + ?Sized + 'gc, Id: CollectorId> {
405 value: NonNull<T>,
406 /// Used to uniquely identify the collector,
407 /// to ensure we aren't modifying another collector's pointers
408 collector_id: Id,
409 marker: PhantomData<&'gc T>,
410}
411impl<'gc, T: GcSafe + ?Sized + 'gc, Id: CollectorId> Gc<'gc, T, Id> {
412 /// Create a GC pointer from a raw ID/pointer pair
413 ///
414 /// ## Safety
415 /// Undefined behavior if the underlying pointer is not valid
416 /// and associated with the collector corresponding to the id.
417 #[inline(always)]
418 pub unsafe fn from_raw(id: Id, value: NonNull<T>) -> Self {
419 Gc { collector_id: id, value, marker: PhantomData }
420 }
421
422 /// The value of the underlying pointer
423 #[inline(always)]
424 pub fn value(&self) -> &'gc T {
425 unsafe { *(&self.value as *const NonNull<T> as *const &'gc T) }
426 }
427 /// Cast this reference to a raw pointer
428 ///
429 /// ## Safety
430 /// It's undefined behavior to mutate the
431 /// value.
432 /// The pointer is only valid as long as
433 /// the reference is.
434 #[inline]
435 pub unsafe fn as_raw_ptr(&self) -> *mut T {
436 self.value.as_ptr() as *const T as *mut T
437 }
438
439
440 /// Create a handle to this object, which can be used without a context
441 #[inline]
442 pub fn create_handle(&self) -> <Id::System as GcHandleSystem<'gc, T>>::Handle
443 where Id::System: GcHandleSystem<'gc, T>,
444 T: GcBrand<'static, Id>,
445 <T as GcBrand<'static, Id>>::Branded: GcSafe {
446 <Id::System as GcHandleSystem<'gc, T>>::create_handle(*self)
447 }
448
449 /// Get a reference to the system
450 ///
451 /// ## Safety
452 /// This is based on the assumption that a [GcSystem] must outlive
453 /// all of the pointers it owns.
454 /// Although it could be restricted to the lifetime of the [CollectorId]
455 /// (in theory that may have an internal pointer) it will still live for '&self'.
456 #[inline]
457 pub fn system(&self) -> &'_ Id::System {
458 // This assumption is safe - see the docs
459 unsafe { self.collector_id.assume_valid_system() }
460 }
461
462 /// Get a copy of the collector's id
463 ///
464 /// The underlying collector it points to is not necessarily always valid
465 #[inline]
466 pub fn collector_id(&self) -> Id {
467 self.collector_id
468 }
469}
470
471/// Double-indirection is completely safe
472unsafe impl<'gc, T: GcSafe + 'gc, Id: CollectorId> GcSafe for Gc<'gc, T, Id> {
473 const NEEDS_DROP: bool = true; // We are Copy
474}
475/// Rebrand
476unsafe impl<'gc, 'new_gc, T, Id> GcBrand<'new_gc, Id> for Gc<'gc, T, Id>
477 where T: GcSafe + GcBrand<'new_gc, Id>,
478 T::Branded: GcSafe, Id: CollectorId {
479 type Branded = Gc<'new_gc, <T as GcBrand<'new_gc, Id>>::Branded, Id>;
480}
481unsafe impl<'gc, T: GcSafe + 'gc, Id: CollectorId> Trace for Gc<'gc, T, Id> {
482 // We always need tracing....
483 const NEEDS_TRACE: bool = true;
484
485 #[inline]
486 fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
487 unsafe {
488 // We're doing this correctly!
489 V::visit_gc(visitor, self)
490 }
491 }
492}
493impl<'gc, T: GcSafe + 'gc, Id: CollectorId> Deref for Gc<'gc, T, Id> {
494 type Target = &'gc T;
495
496 #[inline(always)]
497 fn deref(&self) -> &Self::Target {
498 unsafe { &*(&self.value as *const NonNull<T> as *const &'gc T) }
499 }
500}
501unsafe impl<'gc, O, V, Id> GcDirectBarrier<'gc, Gc<'gc, O, Id>> for Gc<'gc, V,Id>
502 where O: GcSafe + 'gc, V: GcSafe + 'gc, Id: CollectorId {
503 #[inline(always)]
504 unsafe fn write_barrier(&self, owner: &Gc<'gc, O, Id>, field_offset: usize) {
505 Id::gc_write_barrier(owner, self, field_offset)
506 }
507}
508// We can be copied freely :)
509impl<'gc, T: GcSafe + ?Sized + 'gc, Id: CollectorId> Copy for Gc<'gc, T, Id> {}
510impl<'gc, T: GcSafe + ?Sized + 'gc, Id: CollectorId> Clone for Gc<'gc, T, Id> {
511 #[inline(always)]
512 fn clone(&self) -> Self {
513 *self
514 }
515}
516// Delegating impls
517impl<'gc, T: GcSafe + Hash + 'gc, Id: CollectorId> Hash for Gc<'gc, T, Id> {
518 #[inline]
519 fn hash<H: Hasher>(&self, state: &mut H) {
520 self.value().hash(state)
521 }
522}
523impl<'gc, T: GcSafe + PartialEq + 'gc, Id: CollectorId> PartialEq for Gc<'gc, T, Id> {
524 #[inline]
525 fn eq(&self, other: &Self) -> bool {
526 // NOTE: We compare by value, not identity
527 self.value() == other.value()
528 }
529}
530impl<'gc, T: GcSafe + Eq + 'gc, Id: CollectorId> Eq for Gc<'gc, T, Id> {}
531impl<'gc, T: GcSafe + PartialEq + 'gc, Id: CollectorId> PartialEq<T> for Gc<'gc, T, Id> {
532 #[inline]
533 fn eq(&self, other: &T) -> bool {
534 self.value() == other
535 }
536}
537impl<'gc, T: GcSafe + Debug + 'gc, Id: CollectorId> Debug for Gc<'gc, T, Id> {
538 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
539 if !f.alternate() {
540 // Pretend we're a newtype by default
541 f.debug_tuple("Gc").field(self.value()).finish()
542 } else {
543 // Alternate spec reveals `collector_id`
544 f.debug_struct("Gc")
545 .field("collector_id", &self.collector_id)
546 .field("value", self.value())
547 .finish()
548 }
549 }
550}
551
552/// In order to send *references* between threads,
553/// the underlying type must be sync.
554///
555/// This is the same reason that `Arc<T>: Send` requires `T: Sync`
556unsafe impl<'gc, T, Id> Send for Gc<'gc, T, Id>
557 where T: GcSafe + ?Sized + Sync, Id: CollectorId + Sync {}
558
559/// If the underlying type is `Sync`, it's safe
560/// to share garbage collected references between threads.
561///
562/// The safety of the collector itself depends on whether [CollectorId] is Sync.
563/// If it is, the whole garbage collection implenentation should be as well.
564unsafe impl<'gc, T, Id> Sync for Gc<'gc, T, Id>
565 where T: GcSafe + ?Sized + Sync, Id: CollectorId + Sync {}
566
567/// A owned handle which points to a garbage collected object.
568///
569/// This is considered a root by the garbage collector that is independent
570/// of any specific [GcContext]. Safepoints
571/// don't need to be informed of this object for collection to start.
572/// The root is manually managed by user-code, much like a [Box] or
573/// a reference counted pointer.
574///
575/// This can be cloned and stored independently from a context,
576/// bridging the gap between native memory and managed memory.
577/// These are useful to pass to C APIs or any other code
578/// that doesn't cooperate with zerogc.
579///
580/// ## Tracing
581/// The object behind this handle is already considered a root of the collection.
582/// It should always be considered reachable by the garbage collector.
583///
584/// Validity is tracked by this smart-pointer and not by tracing.
585/// Therefore it is safe to implement [NullTrace] for handles.
586/*
587 * TODO: Should we drop the Clone requirement?
588 */
589pub unsafe trait GcHandle<T: GcSafe + ?Sized>: Clone + NullTrace {
590 /// The type of the system used with this handle
591 type System: GcSystem<Id=Self::Id>;
592 /// The type of [CollectorId] used with this sytem
593 type Id: CollectorId;
594
595 /// Access this handle inside the closure,
596 /// possibly associating it with the specified
597 ///
598 /// This is accesses the object within "critical section"
599 /// that will **block collections**
600 /// for as long as the closure is in use.
601 ///
602 /// These calls cannot be invoked recursively or they
603 /// may cause a deadlock.
604 ///
605 /// This is similar in purpose to JNI's [GetPrimitiveArrayCritical](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetPrimitiveArrayCritical_ReleasePrimitiveArrayCritical).
606 /// However it never performs a copy, it is just guarenteed to block any collections.
607 /*
608 * TODO: Should we require this of all collectors?
609 * How much does it limit flexibility?
610 */
611 fn use_critical<R>(&self, func: impl FnOnce(&T) -> R) -> R;
612}
613/// Trait for binding [GcHandle]s to contexts
614/// using [GcBindHandle::bind_to]
615///
616/// This is separate from the [GcHandle] trait
617/// because Rust doesn't have Generic Associated Types
618///
619/// TODO: Remove when we get more powerful types
620pub unsafe trait GcBindHandle<'new_gc, T: GcSafe + ?Sized>: GcHandle<T>
621 where T: GcBrand<'new_gc, Self::Id>,
622 <T as GcBrand<'new_gc, Self::Id>>::Branded: GcSafe {
623 /// Associate this handle with the specified context,
624 /// allowing its underlying object to be accessed
625 /// as long as the context is valid.
626 ///
627 /// The underlying object can be accessed just like any
628 /// other object that would be allocated from the context.
629 /// It'll be properly collected and can even be used as a root
630 /// at the next safepoint.
631 fn bind_to(&self, context: &'new_gc <Self::System as GcSystem>::Context) -> Gc<
632 'new_gc,
633 <T as GcBrand<'new_gc, Self::Id>>::Branded,
634 Self::Id
635 >;
636}
637
638/// Safely trigger a write barrier before
639/// writing to a garbage collected value.
640///
641/// The value must be in managed memory,
642/// a *direct* part of a garbage collected object.
643/// Write barriers (and writes) must include a reference
644/// to its owning object.
645///
646/// ## Safety
647/// It is undefined behavior to forget to trigger a write barrier.
648///
649/// Field offsets are unchecked. They must refer to the correct
650/// offset (in bytes).
651///
652/// ### Indirection
653/// This trait only support "direct" writes,
654/// where the destination field is inline with the source object.
655///
656/// For example it's correct to implement `GcDirectWrite<Value=A> for (A, B)`,
657/// since since `A` is inline with the owning tuple.
658///
659/// It is **incorrect** to implement `GcDirectWrite<Value=T> for Vec<T>`,
660/// since it `T` is indirectly referred to by the vector.
661/// There's no "field offset" we can use to get from `*mut Vec` -> `*mut T`.
662///
663/// The only exception to this rule is [Gc] itself.
664/// GcRef can freely implement [GcDirectWrite] for any (and all values),
665/// even though it's just a pointer.
666/// It's the final destination of all write barriers and is expected
667/// to internally handle the indirection.
668pub unsafe trait GcDirectBarrier<'gc, OwningRef>: Trace {
669 /// Trigger a write barrier,
670 /// before writing to one of the owning object's managed fields
671 ///
672 /// It is undefined behavior to mutate a garbage collected field
673 /// without inserting a write barrier before it.
674 ///
675 /// Generational, concurrent and incremental GCs need this to maintain
676 /// the tricolor invariant.
677 ///
678 /// ## Safety
679 /// The specified field offset must point to a valid field
680 /// in the source object.
681 ///
682 /// The type of this value must match the appropriate field
683 unsafe fn write_barrier(&self, owner: &OwningRef, field_offset: usize);
684}
685
686/// Indicates that a type can be safely allocated by a garbage collector.
687///
688/// ## Safety
689/// Custom destructors must never reference garbage collected pointers.
690/// The garbage collector may have already freed the other objects
691/// before calling this type's drop function.
692///
693/// Unlike java finalizers, this allows us to deallocate objects normally
694/// and avoids a second pass over the objects
695/// to check for resurrected objects.
696pub unsafe trait GcSafe: Trace {
697 /// If this type needs a destructor run
698 ///
699 /// This is usually equivalent to `std::mem::needs_drop`.
700 /// However procedurally derived code can sometimes provide
701 /// a no-op drop implementation (for safety),
702 /// which would lead to a false positive with `std::mem::needs_drop()`
703 const NEEDS_DROP: bool;
704
705 /// Assert this type is GC safe
706 ///
707 /// Only used by procedural derive
708 #[doc(hidden)]
709 fn assert_gc_safe() {}
710}
711/// Assert that a type implements Copy
712///
713/// Used by the derive code
714#[doc(hidden)]
715pub fn assert_copy<T: Copy>() {}
716
717/// A wrapper type that assumes its contents don't need to be traced
718#[repr(transparent)]
719#[derive(Copy, Clone, Debug)]
720pub struct AssumeNotTraced<T>(T);
721impl<T> AssumeNotTraced<T> {
722 /// Assume the specified value doesn't need to be traced
723 ///
724 /// ## Safety
725 /// Undefined behavior if the value contains anything that need to be traced
726 /// by a garbage collector.
727 #[inline]
728 pub unsafe fn new(value: T) -> Self {
729 AssumeNotTraced(value)
730 }
731 /// Unwrap the inner value of this wrapper
732 #[inline]
733 pub fn into_inner(self) -> T {
734 self.0
735 }
736}
737impl<T> Deref for AssumeNotTraced<T> {
738 type Target = T;
739
740 #[inline]
741 fn deref(&self) -> &Self::Target {
742 &self.0
743 }
744}
745impl<T> DerefMut for AssumeNotTraced<T> {
746 #[inline]
747 fn deref_mut(&mut self) -> &mut Self::Target {
748 &mut self.0
749 }
750}
751
752unsafe impl<T> Trace for AssumeNotTraced<T> {
753 const NEEDS_TRACE: bool = false;
754 #[inline(always)] // This method does nothing and is always a win to inline
755 fn visit<V: GcVisitor>(&mut self, _visitor: &mut V) -> Result<(), V::Err> {
756 Ok(())
757 }
758}
759unsafe impl<T> TraceImmutable for AssumeNotTraced<T> {
760 #[inline(always)]
761 fn visit_immutable<V: GcVisitor>(&self, _visitor: &mut V) -> Result<(), V::Err> {
762 Ok(())
763 }
764}
765unsafe impl<T> NullTrace for AssumeNotTraced<T> {}
766/// No tracing implies GcSafe
767unsafe impl<T> GcSafe for AssumeNotTraced<T> {
768 const NEEDS_DROP: bool = core::mem::needs_drop::<T>();
769}
770unsafe_gc_brand!(AssumeNotTraced, T);
771
772/// Changes all references to garbage
773/// collected objects to match `'new_gc`.
774///
775/// This indicates that its safe to transmute to the new `Branded` type
776/// and all that will change is the lifetimes.
777pub unsafe trait GcBrand<'new_gc, Id: CollectorId>: Trace {
778 /// This type with all garbage collected lifetimes
779 /// changed to `'new_gc`
780 ///
781 /// This must have the same in-memory repr as `Self`,
782 /// so that it's safe to transmute.
783 type Branded: Trace + 'new_gc;
784}
785
786/// Indicates that a type can be traced by a garbage collector.
787///
788/// This doesn't necessarily mean that the type is safe to allocate in a garbage collector ([GcSafe]).
789///
790/// ## Safety
791/// See the documentation of the `trace` method for more info.
792/// Essentially, this object must faithfully trace anything that
793/// could contain garbage collected pointers or other `Trace` items.
794pub unsafe trait Trace {
795 /// Whether this type needs to be traced by the garbage collector.
796 ///
797 /// Some primitive types don't need to be traced at all,
798 /// and can be simply ignored by the garbage collector.
799 ///
800 /// Collections should usually delegate this decision to their element type,
801 /// claiming the need for tracing only if their elements do.
802 /// For example, to decide `Vec<u32>::NEEDS_TRACE` you'd check whether `u32::NEEDS_TRACE` (false),
803 /// and so then `Vec<u32>` doesn't need to be traced.
804 /// By the same logic, `Vec<Gc<u32>>` does need to be traced,
805 /// since it contains a garbage collected pointer.
806 ///
807 /// If there are multiple types involved, you should check if any of them need tracing.
808 /// One perfect example of this is structure/tuple types which check
809 /// `field1::NEEDS_TRACE || field2::NEEDS_TRACE || field3::needs_trace`.
810 /// The fields which don't need tracing will always ignored by `GarbageCollector::trace`,
811 /// while the fields that do will be properly traced.
812 ///
813 /// False negatives will always result in completely undefined behavior.
814 /// False positives could result in un-necessary tracing, but are perfectly safe otherwise.
815 /// Therefore, when in doubt you always assume this is true.
816 ///
817 /// If this is true `NullTrace` should (but doesn't have to) be implemented.
818 const NEEDS_TRACE: bool;
819 /// Visit each field in this type
820 ///
821 /// Users should never invoke this method, and always call the `V::visit` instead.
822 /// Only the collector itself is premitted to call this method,
823 /// and **it is undefined behavior for the user to invoke this**.
824 ///
825 /// Structures should trace each of their fields,
826 /// and collections should trace each of their elements.
827 ///
828 /// ### Safety
829 /// Some types (like `Gc`) need special actions taken when they're traced,
830 /// but those are somewhat rare and are usually already provided by the garbage collector.
831 ///
832 /// Unless I explicitly document actions as legal I may decide to change i.
833 /// I am only bound by the constraints of [semantic versioning](http://semver.org/) in the trace function
834 /// if I explicitly document it as safe behavior in this method's documentation.
835 /// If you try something that isn't explicitly documented here as permitted behavior,
836 /// the collector may choose to override your memory with `0xDEADBEEF`.
837 /// ## Always Permitted
838 /// - Reading your own memory (includes iteration)
839 /// - Interior mutation is undefined behavior, even if you use `GcCell`
840 /// - Calling `GcVisitor::visit` with the specified collector
841 /// - `GarbageCollector::trace` already verifies that it owns the data, so you don't need to do that
842 /// - Panicking
843 /// - This should be reserved for cases where you are seriously screwed up,
844 /// and can't fulfill your contract to trace your interior properly.
845 /// - One example is `Gc<T>` which panics if the garbage collectors are mismatched
846 /// - This rule may change in future versions, depending on how we deal with multi-threading.
847 /// ## Never Permitted Behavior
848 /// - Forgetting a element of a collection, or field of a structure
849 /// - If you forget an element undefined behavior will result
850 /// - This is why we always prefer automatically derived implementations where possible.
851 /// - You will never trigger undefined behavior with an automatic implementation,
852 /// and it'll always be completely sufficient for safe code (aside from destructors).
853 /// - With an automatically derived implementation you will never miss a field
854 /// - It is undefined behavior to mutate any of your own data.
855 /// - The mutable `&mut self` is just so copying collectors can relocate GC pointers
856 /// - Invoking this function directly, without delegating to `GcVisitor`
857 fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err>;
858}
859/// A type that can be safely traced/relocated
860/// without having to use a mutable reference
861///
862/// Types with interior mutability (like `RefCell` or `Cell<Gc<T>>`)
863/// can safely implement this, since they allow safely relocating the pointer
864/// without a mutable reference.
865/// Likewise primitives (with new garbage collected data) can also
866/// implement this (since they have nothing to trace).
867pub unsafe trait TraceImmutable: Trace {
868 /// Visit an immutable reference to this type
869 ///
870 /// The visitor may want to relocate garbage collected pointers,
871 /// which this type must support.
872 fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), V::Err>;
873}
874
875/// Marker types for types that don't need to be traced
876///
877/// If this trait is implemented `Trace::NEEDS_TRACE` must be false
878pub unsafe trait NullTrace: Trace + TraceImmutable {}
879
880/// Visits garbage collected objects
881///
882/// This should only be used by a [GcSystem]
883pub unsafe trait GcVisitor: Sized {
884 /// The type of errors returned by this visitor
885 type Err: Debug;
886
887 /// Visit a reference to the specified value
888 #[inline(always)]
889 fn visit<T: Trace + ?Sized>(&mut self, value: &mut T) -> Result<(), Self::Err> {
890 value.visit(self)
891 }
892 /// Visit a reference to the specified value
893 #[inline(always)]
894 fn visit_immutable<T: TraceImmutable + ?Sized>(&mut self, value: &T) -> Result<(), Self::Err> {
895 value.visit_immutable(self)
896 }
897
898 /// Visit a garbage collected pointer
899 ///
900 /// ## Safety
901 /// Undefined behavior if the GC pointer isn't properly visited.
902 unsafe fn visit_gc<'gc, T: GcSafe + 'gc, Id: CollectorId>(
903 &mut self, gc: &mut Gc<'gc, T, Id>
904 ) -> Result<(), Self::Err>;
905}