#[repr(transparent)]pub struct Gc<'gc, T: ?Sized, Id: CollectorId> { /* private fields */ }
Expand description
A garbage collected pointer to a value.
This is the equivalent of a garbage collected smart-pointer.
It’s so smart, you can even coerce it to a reference bound to the lifetime of the GarbageCollectorRef
.
However, all those references are invalidated by the borrow checker as soon as
your reference to the collector reaches a safepoint.
The objects can only survive garbage collection if they live in this smart-pointer.
The smart pointer is simply a guarantee to the garbage collector that this points to a garbage collected object with the correct header, and not some arbitrary bits that you’ve decided to heap allocate.
Safety
A Gc
can be safely transmuted back and forth from its corresponding pointer.
Unsafe code can rely on a pointer always dereferencing to the same value in between safepoints. This is true even for copying/moving collectors.
Lifetime
The borrow does not refer to the value &'gc T
.
Instead, it refers to the context &'gc Id::Context
This is necessary because T
may have borrowed interior data
with a shorter lifetime 'a < 'gc
, making &'gc T
invalid
(because that would imply ’gc: ’a, which is false).
This ownership can be thought of in terms of the following (simpler) system.
struct GcContext {
values: Vec<Box<dyn GcSafe>>
}
struct Gc<'gc, T: GcSafe> {
index: usize,
marker: PhantomData<T>,
ctx: &'gc GcContext
}
In this system, safepoints can be thought of mutations
that remove dead values from the Vec
.
This ownership equivalency is also the justification for why
the 'gc
lifetime can be covariant
The only difference is that the real Gc
structure
uses pointers instead of indices.
Implementations
sourceimpl<'gc, T: GcSafe<'gc, Id> + ?Sized, Id: CollectorId> Gc<'gc, T, Id>
impl<'gc, T: GcSafe<'gc, Id> + ?Sized, Id: CollectorId> Gc<'gc, T, Id>
sourcepub unsafe fn from_raw(value: NonNull<T>) -> Self
pub unsafe fn from_raw(value: NonNull<T>) -> Self
Create a GC pointer from a raw pointer
Safety
Undefined behavior if the underlying pointer is not valid and doesn’t correspond to the appropriate id.
sourcepub fn create_handle(&self) -> Id::Handle where
Id: HandleCollectorId,
T: GcRebrand<'static, Id>,
pub fn create_handle(&self) -> Id::Handle where
Id: HandleCollectorId,
T: GcRebrand<'static, Id>,
Create a GcHandle referencing this object, allowing it to be used without a context and referenced across safepoints.
Requires that the collector supports handles
sourcepub fn system(&self) -> &Id::System
pub fn system(&self) -> &Id::System
Get a reference to the system
Safety
This is based on the assumption that a GcSystem must outlive all of the pointers it owns. Although it could be restricted to the lifetime of the CollectorId (in theory that may have an internal pointer) it will still live for ‘&self’.
sourceimpl<'gc, T: ?Sized, Id: CollectorId> Gc<'gc, T, Id>
impl<'gc, T: ?Sized, Id: CollectorId> Gc<'gc, T, Id>
sourcepub unsafe fn as_raw_ptr(&self) -> *mut T
pub unsafe fn as_raw_ptr(&self) -> *mut T
Cast this reference to a raw pointer
Safety
It’s undefined behavior to mutate the value. The pointer is only valid as long as the reference is.
sourcepub fn collector_id(&self) -> &Id
pub fn collector_id(&self) -> &Id
Get a reference to the collector’s id
The underlying collector it points to is not necessarily always valid
Trait Implementations
sourceimpl<'gc, T: ?Sized, Id: CollectorId> Clone for Gc<'gc, T, Id>
impl<'gc, T: ?Sized, Id: CollectorId> Clone for Gc<'gc, T, Id>
sourceimpl<'gc, O, V, Id> GcDirectBarrier<'gc, Gc<'gc, O, Id>> for Gc<'gc, V, Id> where
O: GcSafe<'gc, Id> + 'gc,
V: GcSafe<'gc, Id> + 'gc,
Id: CollectorId,
impl<'gc, O, V, Id> GcDirectBarrier<'gc, Gc<'gc, O, Id>> for Gc<'gc, V, Id> where
O: GcSafe<'gc, Id> + 'gc,
V: GcSafe<'gc, Id> + 'gc,
Id: CollectorId,
sourceunsafe fn write_barrier(&self, owner: &Gc<'gc, O, Id>, field_offset: usize)
unsafe fn write_barrier(&self, owner: &Gc<'gc, O, Id>, field_offset: usize)
Trigger a write barrier, before writing to one of the owning object’s managed fields Read more
sourceimpl<'gc, 'new_gc, T, Id> GcRebrand<'new_gc, Id> for Gc<'gc, T, Id> where
T: GcSafe<'gc, Id> + ?Sized + GcRebrand<'new_gc, Id>,
Id: CollectorId,
Self: Trace,
impl<'gc, 'new_gc, T, Id> GcRebrand<'new_gc, Id> for Gc<'gc, T, Id> where
T: GcSafe<'gc, Id> + ?Sized + GcRebrand<'new_gc, Id>,
Id: CollectorId,
Self: Trace,
Rebrand
sourceimpl<'gc, T: GcSafe<'gc, Id> + Ord, Id: CollectorId> Ord for Gc<'gc, T, Id>
impl<'gc, T: GcSafe<'gc, Id> + Ord, Id: CollectorId> Ord for Gc<'gc, T, Id>
sourceimpl<'gc, T: GcSafe<'gc, Id> + PartialEq, Id: CollectorId> PartialEq<Gc<'gc, T, Id>> for Gc<'gc, T, Id>
impl<'gc, T: GcSafe<'gc, Id> + PartialEq, Id: CollectorId> PartialEq<Gc<'gc, T, Id>> for Gc<'gc, T, Id>
sourceimpl<'gc, T: GcSafe<'gc, Id> + PartialOrd, Id: CollectorId> PartialOrd<Gc<'gc, T, Id>> for Gc<'gc, T, Id>
impl<'gc, T: GcSafe<'gc, Id> + PartialOrd, Id: CollectorId> PartialOrd<Gc<'gc, T, Id>> for Gc<'gc, T, Id>
sourcefn partial_cmp(&self, other: &Self) -> Option<Ordering>
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
This method returns an ordering between self
and other
values if one exists. Read more
1.0.0 · sourcefn lt(&self, other: &Rhs) -> bool
fn lt(&self, other: &Rhs) -> bool
This method tests less than (for self
and other
) and is used by the <
operator. Read more
1.0.0 · sourcefn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
sourceimpl<'gc, T: GcSafe<'gc, Id> + PartialOrd, Id: CollectorId> PartialOrd<T> for Gc<'gc, T, Id>
impl<'gc, T: GcSafe<'gc, Id> + PartialOrd, Id: CollectorId> PartialOrd<T> for Gc<'gc, T, Id>
sourcefn partial_cmp(&self, other: &T) -> Option<Ordering>
fn partial_cmp(&self, other: &T) -> Option<Ordering>
This method returns an ordering between self
and other
values if one exists. Read more
1.0.0 · sourcefn lt(&self, other: &Rhs) -> bool
fn lt(&self, other: &Rhs) -> bool
This method tests less than (for self
and other
) and is used by the <
operator. Read more
1.0.0 · sourcefn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
impl<'gc, T, U, Id> CoerceUnsized<Gc<'gc, U, Id>> for Gc<'gc, T, Id> where
T: ?Sized + GcSafe<'gc, Id> + Unsize<U>,
U: ?Sized + GcSafe<'gc, Id>,
Id: CollectorId,
impl<'gc, T: ?Sized, Id: CollectorId> Copy for Gc<'gc, T, Id>
impl<'gc, T: GcSafe<'gc, Id> + Eq, Id: CollectorId> Eq for Gc<'gc, T, Id>
impl<'gc, T, Id> Send for Gc<'gc, T, Id> where
T: GcSafe<'gc, Id> + ?Sized + Sync,
Id: CollectorId + Sync,
In order to send references between threads, the underlying type must be sync.
This is the same reason that Arc<T>: Send
requires T: Sync
impl<'gc, T, Id> Sync for Gc<'gc, T, Id> where
T: GcSafe<'gc, Id> + ?Sized + Sync,
Id: CollectorId + Sync,
If the underlying type is Sync
, it’s safe
to share garbage collected references between threads.
The safety of the collector itself depends on whether CollectorId is Sync. If it is, the whole garbage collection implementation should be as well.
impl<'gc, T: ?Sized + GcSafe<'gc, Id>, Id: CollectorId> TrustedDrop for Gc<'gc, T, Id>
Double-indirection is completely safe
Auto Trait Implementations
impl<'gc, T: ?Sized, Id> RefUnwindSafe for Gc<'gc, T, Id> where
T: RefUnwindSafe,
<Id as CollectorId>::Context: RefUnwindSafe,
impl<'gc, T: ?Sized, Id> Unpin for Gc<'gc, T, Id>
impl<'gc, T: ?Sized, Id> UnwindSafe for Gc<'gc, T, Id> where
T: RefUnwindSafe,
<Id as CollectorId>::Context: RefUnwindSafe,
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcepub fn borrow_mut(&mut self) -> &mut T
pub fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> ToOwned for T where
T: Clone,
impl<T> ToOwned for T where
T: Clone,
type Owned = T
type Owned = T
The resulting type after obtaining ownership.
sourcepub fn to_owned(&self) -> T
pub fn to_owned(&self) -> T
Creates owned data from borrowed data, usually by cloning. Read more
sourcepub fn clone_into(&self, target: &mut T)
pub fn clone_into(&self, target: &mut T)
toowned_clone_into
)Uses borrowed data to replace owned data, usually by cloning. Read more