From 259412a92ddf6d59227f2bedaa115f9f9170cfa2 Mon Sep 17 00:00:00 2001 From: shruti2522 Date: Tue, 16 Jun 2026 23:18:31 +0000 Subject: [PATCH 1/2] implement null collector for lifetime branded GC --- oscars/Cargo.toml | 1 + oscars/src/collectors/mod.rs | 4 +- .../collectors/null_collector_branded/cell.rs | 68 ++++++ .../null_collector_branded/ephemeron.rs | 45 ++++ .../collectors/null_collector_branded/gc.rs | 55 +++++ .../null_collector_branded/gc_box.rs | 22 ++ .../collectors/null_collector_branded/mod.rs | 127 ++++++++++ .../null_collector_branded/mutation_ctx.rs | 66 +++++ .../collectors/null_collector_branded/root.rs | 34 +++ .../null_collector_branded/trace.rs | 225 ++++++++++++++++++ .../collectors/null_collector_branded/weak.rs | 42 ++++ 11 files changed, 688 insertions(+), 1 deletion(-) create mode 100644 oscars/src/collectors/null_collector_branded/cell.rs create mode 100644 oscars/src/collectors/null_collector_branded/ephemeron.rs create mode 100644 oscars/src/collectors/null_collector_branded/gc.rs create mode 100644 oscars/src/collectors/null_collector_branded/gc_box.rs create mode 100644 oscars/src/collectors/null_collector_branded/mod.rs create mode 100644 oscars/src/collectors/null_collector_branded/mutation_ctx.rs create mode 100644 oscars/src/collectors/null_collector_branded/root.rs create mode 100644 oscars/src/collectors/null_collector_branded/trace.rs create mode 100644 oscars/src/collectors/null_collector_branded/weak.rs diff --git a/oscars/Cargo.toml b/oscars/Cargo.toml index 26ce262..37d6221 100644 --- a/oscars/Cargo.toml +++ b/oscars/Cargo.toml @@ -37,4 +37,5 @@ mark_sweep = [] mark_sweep2 = ["mark_sweep"] mark_sweep_branded = ["mark_sweep"] null_collector = ["mark_sweep"] +null_collector_branded = ["mark_sweep"] thin-vec = ["dep:thin-vec", "mark_sweep"] diff --git a/oscars/src/collectors/mod.rs b/oscars/src/collectors/mod.rs index e465841..f704e84 100644 --- a/oscars/src/collectors/mod.rs +++ b/oscars/src/collectors/mod.rs @@ -8,6 +8,8 @@ pub mod mark_sweep_arena2; #[cfg(feature = "null_collector")] pub mod null_collector; -// TODO: Implement a null collector for the branded API as well +#[cfg(feature = "null_collector_branded")] +pub mod null_collector_branded; + #[cfg(feature = "mark_sweep_branded")] pub mod mark_sweep_branded; diff --git a/oscars/src/collectors/null_collector_branded/cell.rs b/oscars/src/collectors/null_collector_branded/cell.rs new file mode 100644 index 0000000..3490aa9 --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/cell.rs @@ -0,0 +1,68 @@ +use crate::collectors::null_collector_branded::trace::{Finalize, Trace, Tracer}; +use core::cell::{Ref, RefCell, RefMut}; +use core::ops::{Deref, DerefMut}; + +/// GC aware wrapper around [`RefCell`] +pub struct GcRefCell { + inner: RefCell, +} + +impl GcRefCell { + pub fn new(value: T) -> Self { + Self { + inner: RefCell::new(value), + } + } + + /// Acquires a shared borrow of the inner value. + /// + /// # Panics + /// + /// Panics if the value is currently mutably borrowed. + pub fn borrow(&self) -> GcRef<'_, T> { + GcRef(self.inner.borrow()) + } + + /// Acquires a mutable borrow of the inner value. + /// + /// # Panics + /// + /// Panics if the value is currently borrowed. + pub fn borrow_mut(&self) -> GcRefMut<'_, T> { + GcRefMut(self.inner.borrow_mut()) + } +} + +/// Shared borrow guard returned by [`GcRefCell::borrow`] +pub struct GcRef<'a, T: Trace>(Ref<'a, T>); + +impl Deref for GcRef<'_, T> { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + +/// A mutable borrow guard returned by [`GcRefCell::borrow_mut`] +pub struct GcRefMut<'a, T: Trace>(RefMut<'a, T>); + +impl Deref for GcRefMut<'_, T> { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + +impl DerefMut for GcRefMut<'_, T> { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +impl Finalize for GcRefCell {} + +impl Trace for GcRefCell { + fn trace(&mut self, tracer: &mut Tracer) { + self.inner.get_mut().trace(tracer); + } +} diff --git a/oscars/src/collectors/null_collector_branded/ephemeron.rs b/oscars/src/collectors/null_collector_branded/ephemeron.rs new file mode 100644 index 0000000..2548e22 --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/ephemeron.rs @@ -0,0 +1,45 @@ +use crate::{ + alloc::mempool3::PoolPointer, + collectors::null_collector_branded::{ + gc::Gc, + gc_box::GcBox, + mutation_ctx::MutationContext, + trace::{Finalize, Trace, Tracer}, + }, +}; +use core::marker::PhantomData; + +pub struct Ephemeron<'id, K: Trace, V: Trace> { + pub(crate) key_ptr: Option>>, + pub(crate) value_ptr: PoolPointer<'static, GcBox>, + pub(crate) _marker: PhantomData<*mut &'id ()>, +} + +impl<'id, K: Trace, V: Trace> Ephemeron<'id, K, V> { + /// Returns the value if the key is alive. + pub fn get_value<'gc>(&self, _cx: &MutationContext<'id, 'gc>) -> Option> { + // In the null collector, everything stays alive until context drops. + if self.key_ptr.is_some() { + Some(Gc { + ptr: self.value_ptr, + _marker: PhantomData, + }) + } else { + None + } + } +} + +impl<'id, K: Trace, V: Trace> Clone for Ephemeron<'id, K, V> { + fn clone(&self) -> Self { + *self + } +} + +impl<'id, K: Trace, V: Trace> Copy for Ephemeron<'id, K, V> {} + +impl<'id, K: Trace, V: Trace> Finalize for Ephemeron<'id, K, V> {} + +impl<'id, K: Trace, V: Trace> Trace for Ephemeron<'id, K, V> { + fn trace(&mut self, _tracer: &mut Tracer) {} +} diff --git a/oscars/src/collectors/null_collector_branded/gc.rs b/oscars/src/collectors/null_collector_branded/gc.rs new file mode 100644 index 0000000..11a19ef --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/gc.rs @@ -0,0 +1,55 @@ +//! Core pointer types. + +use crate::{ + alloc::mempool3::PoolPointer, + collectors::null_collector_branded::{ + gc_box::GcBox, + trace::{Finalize, Trace}, + }, +}; +use core::fmt; +use core::marker::PhantomData; +use core::ops::Deref; + +/// Transient pointer to a GC managed value. +#[derive(Debug)] +pub struct Gc<'gc, T: Trace + ?Sized + 'gc> { + pub(crate) ptr: PoolPointer<'static, GcBox>, + pub(crate) _marker: PhantomData<(&'gc T, *const ())>, +} + +impl<'gc, T: Trace + ?Sized + 'gc> Copy for Gc<'gc, T> {} +impl<'gc, T: Trace + ?Sized + 'gc> Clone for Gc<'gc, T> { + fn clone(&self) -> Self { + *self + } +} + +impl<'gc, T: Trace + 'gc> Gc<'gc, T> { + /// Returns a shared reference to the value. + #[inline] + pub fn get(&self) -> &T { + // SAFETY: `ptr` is non-null and valid for `'gc` by construction. + unsafe { &(*self.ptr.as_ptr().as_ptr()).0.value } + } +} + +impl<'gc, T: Trace + fmt::Display + 'gc> fmt::Display for Gc<'gc, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.get(), f) + } +} + +impl<'gc, T: Trace + 'gc> Deref for Gc<'gc, T> { + type Target = T; + fn deref(&self) -> &T { + self.get() + } +} + +impl Finalize for Gc<'_, T> {} +impl Trace for Gc<'_, T> { + fn trace(&mut self, tracer: &mut crate::collectors::null_collector_branded::trace::Tracer) { + tracer.mark(self); + } +} diff --git a/oscars/src/collectors/null_collector_branded/gc_box.rs b/oscars/src/collectors/null_collector_branded/gc_box.rs new file mode 100644 index 0000000..867a023 --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/gc_box.rs @@ -0,0 +1,22 @@ +use core::ptr::NonNull; + +use crate::alloc::mempool3::{PoolAllocator, PoolItem}; + +pub(crate) type DropFn = unsafe fn(&mut PoolAllocator<'static>, NonNull); + +/// Heap wrapper for a garbage collected value. +/// +/// Allocated via [`PoolAllocator`] +pub(crate) struct GcBox { + /// Type erased finalize and free fn + pub(crate) drop_fn: DropFn, + /// User value + pub(crate) value: T, +} + +impl GcBox { + /// Create a [`GcBox`] for `value` + pub(crate) fn new(value: T, drop_fn: DropFn) -> Self { + Self { drop_fn, value } + } +} diff --git a/oscars/src/collectors/null_collector_branded/mod.rs b/oscars/src/collectors/null_collector_branded/mod.rs new file mode 100644 index 0000000..5e72c7c --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/mod.rs @@ -0,0 +1,127 @@ +//! Lifetime branded null GC +#![cfg_attr(not(any(test, feature = "std")), allow(unused_imports))] + +pub mod cell; +pub mod ephemeron; +pub mod gc; +pub mod gc_box; +pub mod mutation_ctx; +pub mod root; +pub mod trace; +pub mod weak; + +pub use cell::GcRefCell; +pub use ephemeron::Ephemeron; +pub use gc::Gc; +pub use mutation_ctx::MutationContext; +pub use root::Root; +pub use trace::{Finalize, Trace, Tracer}; +pub use weak::WeakGc; + +use crate::alloc::mempool3::{PoolAllocError, PoolAllocator, PoolPointer}; +use core::cell::RefCell; +use core::marker::PhantomData; +use core::ptr::NonNull; +use gc_box::{DropFn, GcBox}; +use rust_alloc::vec::Vec; + +pub(crate) struct Collector { + // SAFETY: We use 'static here because the PoolAllocator owns its memory, + // and we ensure that `Gc` objects and pool allocations do not outlive + // the `Collector` instance + pub(crate) pool: RefCell>, +} + +impl Collector { + fn new() -> Self { + Self { + pool: RefCell::new(PoolAllocator::default()), + } + } + + /// Allocates a value from the pool. + pub(crate) fn try_alloc<'gc, T: trace::Trace + trace::Finalize + 'gc>( + &'gc self, + value: T, + ) -> Result, PoolAllocError> { + unsafe fn drop_and_free( + pool: &mut PoolAllocator<'static>, + ptr: NonNull, + ) { + use crate::alloc::mempool3::PoolItem; + unsafe { + let typed_ptr = ptr.cast::>>(); + (*typed_ptr.as_ptr()).0.value.finalize(); + core::ptr::drop_in_place(typed_ptr.as_ptr()); + pool.free_slot(ptr); + } + } + + let mut pool = self.pool.borrow_mut(); + let ptr = pool.try_alloc(GcBox::new(value, drop_and_free::))?; + + drop(pool); + + Ok(Gc { + ptr: unsafe { ptr.extend_lifetime() }, + _marker: PhantomData, + }) + } + + /// Runs a collection cycle (no-op for null collector) + pub(crate) fn collect(&self) {} +} + +impl Drop for Collector { + /// Frees all remaining allocations + fn drop(&mut self) { + use crate::alloc::mempool3::PoolItem; + + // Free all GC allocations + let all: Vec<(NonNull, DropFn)> = self + .pool + .borrow() + .iter_live_slots() + .map(|ptr| unsafe { + let drop_fn = (*ptr.cast::>>().as_ptr()).0.drop_fn; + (ptr, drop_fn) + }) + .collect(); + let mut pool = self.pool.borrow_mut(); + for (ptr, drop_fn) in all { + unsafe { + (drop_fn)(&mut pool, ptr); + } + } + } +} + +/// Owns the GC and carries the `'id` context brand +pub struct GcContext<'id> { + collector: Collector, + _marker: PhantomData<*mut &'id ()>, +} + +impl<'id> GcContext<'id> { + /// Opens a mutation window and passes a [`MutationContext`] to `f` + /// Triggers a gc cycle + pub fn collect(&self) { + self.collector.collect(); + } + + pub fn mutate(&self, f: impl for<'gc> FnOnce(&MutationContext<'id, 'gc>) -> R) -> R { + let cx = MutationContext { + collector: &self.collector, + _marker: PhantomData, + }; + f(&cx) + } +} + +/// Create new GC context +pub fn with_gc FnOnce(GcContext<'id>) -> R>(f: F) -> R { + f(GcContext { + collector: Collector::new(), + _marker: PhantomData, + }) +} diff --git a/oscars/src/collectors/null_collector_branded/mutation_ctx.rs b/oscars/src/collectors/null_collector_branded/mutation_ctx.rs new file mode 100644 index 0000000..33b7376 --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/mutation_ctx.rs @@ -0,0 +1,66 @@ +use crate::{ + alloc::mempool3::{PoolAllocError, PoolPointer}, + collectors::null_collector_branded::{ + Collector, + ephemeron::Ephemeron, + gc::Gc, + root::Root, + trace::{Finalize, Trace}, + weak::WeakGc, + }, +}; +use core::marker::PhantomData; + +/// Handle for GC allocations +pub struct MutationContext<'id, 'gc> { + pub(crate) collector: &'gc Collector, + pub(crate) _marker: PhantomData<*mut &'id ()>, +} + +impl<'id, 'gc> MutationContext<'id, 'gc> { + /// Allocates a value on the GC heap + pub fn try_alloc( + &self, + value: T, + ) -> Result, PoolAllocError> { + self.collector.try_alloc(value) + } + + /// Downgrades a `Gc` into weak reference + pub fn alloc_weak(&self, gc: Gc<'gc, T>) -> WeakGc<'id, T> { + WeakGc { + ptr: gc.ptr, + _marker: PhantomData, + } + } + + pub fn root( + &self, + gc: Gc<'gc, T>, + ) -> Result, PoolAllocError> { + Ok(Root::new(self, gc)) + } + + /// Creates an ephemeron binding `key` to `value` + /// + /// The value is kept alive by the collector as long as the key remains + /// reachable from a root. Once the key is collected, `get_value` returns + /// `None` and the value is eligible for collection on next cycle. + pub fn alloc_ephemeron( + &self, + key: Gc<'gc, K>, + value: Gc<'gc, V>, + ) -> Ephemeron<'id, K, V> { + // In the null collector, ephemerons don't need to be registered + // since the collector never collects. + Ephemeron { + key_ptr: Some(key.ptr), + value_ptr: value.ptr, + _marker: core::marker::PhantomData, + } + } + + pub fn collect(&self) { + self.collector.collect(); + } +} diff --git a/oscars/src/collectors/null_collector_branded/root.rs b/oscars/src/collectors/null_collector_branded/root.rs new file mode 100644 index 0000000..c3baa68 --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/root.rs @@ -0,0 +1,34 @@ +//! In the null collector, roots are a zero cost abstraction because nothing is ever collected +//! before the entire context is dropped. + +use crate::{ + alloc::mempool3::PoolPointer, + collectors::null_collector_branded::{ + gc::Gc, gc_box::GcBox, mutation_ctx::MutationContext, trace::Trace, + }, +}; +use core::marker::PhantomData; + +#[must_use = "dropping a root unregisters it from the GC"] +pub struct Root<'id, T: Trace> { + gc_ptr: PoolPointer<'static, GcBox>, + _marker: PhantomData<*mut &'id ()>, +} + +impl<'id, T: Trace> Root<'id, T> { + /// Creates a new root from a Gc pointer + pub fn new(_mc: &MutationContext<'id, '_>, value: Gc<'_, T>) -> Self { + Self { + gc_ptr: value.ptr, + _marker: PhantomData, + } + } + + /// Converts this root into a `Gc` pointer + pub fn get<'gc>(&self, _cx: &MutationContext<'id, 'gc>) -> Gc<'gc, T> { + Gc { + ptr: self.gc_ptr, + _marker: PhantomData, + } + } +} diff --git a/oscars/src/collectors/null_collector_branded/trace.rs b/oscars/src/collectors/null_collector_branded/trace.rs new file mode 100644 index 0000000..3dfa628 --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/trace.rs @@ -0,0 +1,225 @@ +//! Trace and Finalize traits for the lifetime branded GC +pub use crate::collectors::common::Finalize; + +use core::cell::{Cell, OnceCell}; +use core::marker::PhantomData; +use rust_alloc::borrow::{Cow, ToOwned}; +use rust_alloc::boxed::Box; +use rust_alloc::collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}; +use rust_alloc::string::String; +use rust_alloc::vec::Vec; + +/// Trait for tracing garbage collected values. +/// +/// In the null collector, tracing is a no-op. +pub trait Trace { + /// Marks all Gc pointers reachable from `self`. + fn trace(&mut self, tracer: &mut Tracer); +} + +/// Dummy tracer for the null collector +pub struct Tracer<'a> { + pub(crate) _marker: PhantomData<&'a ()>, +} + +impl<'a> Tracer<'a> { + #[inline] + pub fn mark( + &mut self, + _gc: &crate::collectors::null_collector_branded::gc::Gc<'_, T>, + ) { + } +} + +impl Trace for &T { + #[inline] + fn trace(&mut self, _tracer: &mut Tracer) {} +} + +macro_rules! empty_trace { + ($($T:ty),* $(,)?) => { + $( + impl Trace for $T { + #[inline] + fn trace(&mut self, _tracer: &mut Tracer) {} + } + )* + }; +} + +empty_trace![ + (), + bool, + isize, + usize, + i8, + u8, + i16, + u16, + i32, + u32, + i64, + u64, + i128, + u128, + f32, + f64, + char, + String, + core::num::NonZeroIsize, + core::num::NonZeroUsize, + core::num::NonZeroI8, + core::num::NonZeroU8, + core::num::NonZeroI16, + core::num::NonZeroU16, + core::num::NonZeroI32, + core::num::NonZeroU32, + core::num::NonZeroI64, + core::num::NonZeroU64, + core::num::NonZeroI128, + core::num::NonZeroU128, +]; + +impl Trace for [T; N] { + fn trace(&mut self, tracer: &mut Tracer) { + for v in self.iter_mut() { + v.trace(tracer); + } + } +} + +impl Trace for Box { + fn trace(&mut self, tracer: &mut Tracer) { + (**self).trace(tracer); + } +} + +impl Trace for Option { + fn trace(&mut self, tracer: &mut Tracer) { + if let Some(v) = self { + v.trace(tracer); + } + } +} + +impl Trace for Result { + fn trace(&mut self, tracer: &mut Tracer) { + match self { + Ok(v) => v.trace(tracer), + Err(e) => e.trace(tracer), + } + } +} + +impl Trace for Vec { + fn trace(&mut self, tracer: &mut Tracer) { + for v in self.iter_mut() { + v.trace(tracer); + } + } +} + +impl Trace for VecDeque { + fn trace(&mut self, tracer: &mut Tracer) { + for v in self.iter_mut() { + v.trace(tracer); + } + } +} + +impl Trace for LinkedList { + fn trace(&mut self, tracer: &mut Tracer) { + for v in self.iter_mut() { + v.trace(tracer); + } + } +} + +impl Trace for PhantomData { + #[inline] + fn trace(&mut self, _tracer: &mut Tracer) {} +} + +impl Trace for Cell> { + fn trace(&mut self, tracer: &mut Tracer) { + if let Some(mut v) = self.get() { + v.trace(tracer); + } + } +} + +impl Trace for OnceCell { + fn trace(&mut self, tracer: &mut Tracer) { + if let Some(v) = self.get_mut() { + v.trace(tracer); + } + } +} + +impl Trace for Cow<'static, T> +where + T::Owned: Trace, +{ + fn trace(&mut self, tracer: &mut Tracer) { + if let Cow::Owned(v) = self { + v.trace(tracer); + } + } +} + +impl Trace for (A,) { + #[inline] + fn trace(&mut self, tracer: &mut Tracer) { + self.0.trace(tracer); + } +} + +impl Trace for (A, B) { + #[inline] + fn trace(&mut self, tracer: &mut Tracer) { + self.0.trace(tracer); + self.1.trace(tracer); + } +} + +impl Trace for (A, B, C) { + #[inline] + fn trace(&mut self, tracer: &mut Tracer) { + self.0.trace(tracer); + self.1.trace(tracer); + self.2.trace(tracer); + } +} + +impl Trace for (A, B, C, D) { + #[inline] + fn trace(&mut self, tracer: &mut Tracer) { + self.0.trace(tracer); + self.1.trace(tracer); + self.2.trace(tracer); + self.3.trace(tracer); + } +} + +impl Trace for rust_alloc::rc::Rc { + #[inline] + fn trace(&mut self, _tracer: &mut Tracer) {} +} + +impl Trace for rust_alloc::sync::Arc { + #[inline] + fn trace(&mut self, _tracer: &mut Tracer) {} +} + +impl Trace for BTreeMap { + fn trace(&mut self, tracer: &mut Tracer) { + for v in self.values_mut() { + v.trace(tracer); + } + } +} + +impl Trace for BTreeSet { + #[inline] + fn trace(&mut self, _tracer: &mut Tracer) {} +} diff --git a/oscars/src/collectors/null_collector_branded/weak.rs b/oscars/src/collectors/null_collector_branded/weak.rs new file mode 100644 index 0000000..1d8ef28 --- /dev/null +++ b/oscars/src/collectors/null_collector_branded/weak.rs @@ -0,0 +1,42 @@ +use crate::{ + alloc::mempool3::PoolPointer, + collectors::null_collector_branded::{ + gc::Gc, + gc_box::GcBox, + trace::{Finalize, Trace}, + }, +}; +use core::marker::PhantomData; + +/// A weak reference to a GC managed value +pub struct WeakGc<'id, T: Trace + ?Sized> { + pub(crate) ptr: PoolPointer<'static, GcBox>, + pub(crate) _marker: PhantomData<*mut &'id ()>, +} + +impl<'id, T: Trace> WeakGc<'id, T> { + /// Attempts to upgrade to a strong `Gc<'gc, T>` + pub fn upgrade<'gc>( + &self, + _cx: &crate::collectors::null_collector_branded::MutationContext<'id, 'gc>, + ) -> Option> { + // In the null collector, everything stays alive until context drops. + Some(Gc { + ptr: self.ptr, + _marker: PhantomData, + }) + } +} + +impl<'id, T: Trace + ?Sized> Clone for WeakGc<'id, T> { + fn clone(&self) -> Self { + *self + } +} + +impl<'id, T: Trace + ?Sized> Copy for WeakGc<'id, T> {} + +impl<'id, T: Trace> Finalize for WeakGc<'id, T> {} +impl<'id, T: Trace> Trace for WeakGc<'id, T> { + fn trace(&mut self, _tracer: &mut crate::collectors::null_collector_branded::trace::Tracer) {} +} From a795bf1e2f7c6769c8d3478b4e96121d66957446 Mon Sep 17 00:00:00 2001 From: shruti2522 Date: Wed, 17 Jun 2026 16:08:21 +0000 Subject: [PATCH 2/2] fix ci --- .../tests/ui/gc_cannot_escape_mutate.stderr | 2 +- .../mark_sweep_branded/tests/ui/root_cross_context.stderr | 4 ++-- oscars/src/collectors/null_collector_branded/gc_box.rs | 2 +- oscars/src/collectors/null_collector_branded/mod.rs | 2 +- oscars/src/collectors/null_collector_branded/mutation_ctx.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/oscars/src/collectors/mark_sweep_branded/tests/ui/gc_cannot_escape_mutate.stderr b/oscars/src/collectors/mark_sweep_branded/tests/ui/gc_cannot_escape_mutate.stderr index 5c677b2..eb9acb7 100644 --- a/oscars/src/collectors/mark_sweep_branded/tests/ui/gc_cannot_escape_mutate.stderr +++ b/oscars/src/collectors/mark_sweep_branded/tests/ui/gc_cannot_escape_mutate.stderr @@ -4,6 +4,6 @@ error: lifetime may not live long enough 14 | let _escaped = ctx.mutate(|cx| { | --- return type of closure is oscars::collectors::mark_sweep_branded::Gc<'2, i32> | | - | has type `&MutationContext<'_, '1>` + | has type `&oscars::collectors::mark_sweep_branded::MutationContext<'_, '1>` 15 | cx.try_alloc(42i32).unwrap() // ERROR: Gc<'gc, i32> cannot escape mutate() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` diff --git a/oscars/src/collectors/mark_sweep_branded/tests/ui/root_cross_context.stderr b/oscars/src/collectors/mark_sweep_branded/tests/ui/root_cross_context.stderr index e4dc38e..ea3bb1a 100644 --- a/oscars/src/collectors/mark_sweep_branded/tests/ui/root_cross_context.stderr +++ b/oscars/src/collectors/mark_sweep_branded/tests/ui/root_cross_context.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough 13 | with_gc(|ctx1| { | ---- lifetime `'2` appears in the type of `ctx1` 14 | with_gc(|ctx2| { - | ---- has type `GcContext<'1>` + | ---- has type `oscars::collectors::mark_sweep_branded::GcContext<'1>` 15 | // root carries 'id of ctx1 16 | let root = ctx1.mutate(|cx| cx.root(cx.try_alloc(123i32).unwrap()).unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` @@ -13,7 +13,7 @@ error: lifetime may not live long enough --> src/collectors/mark_sweep_branded/tests/ui/root_cross_context.rs:16:41 | 13 | with_gc(|ctx1| { - | ---- has type `GcContext<'1>` + | ---- has type `oscars::collectors::mark_sweep_branded::GcContext<'1>` ... 16 | let root = ctx1.mutate(|cx| cx.root(cx.try_alloc(123i32).unwrap()).unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` diff --git a/oscars/src/collectors/null_collector_branded/gc_box.rs b/oscars/src/collectors/null_collector_branded/gc_box.rs index 867a023..97f806e 100644 --- a/oscars/src/collectors/null_collector_branded/gc_box.rs +++ b/oscars/src/collectors/null_collector_branded/gc_box.rs @@ -1,6 +1,6 @@ use core::ptr::NonNull; -use crate::alloc::mempool3::{PoolAllocator, PoolItem}; +use crate::alloc::mempool3::PoolAllocator; pub(crate) type DropFn = unsafe fn(&mut PoolAllocator<'static>, NonNull); diff --git a/oscars/src/collectors/null_collector_branded/mod.rs b/oscars/src/collectors/null_collector_branded/mod.rs index 5e72c7c..b16f027 100644 --- a/oscars/src/collectors/null_collector_branded/mod.rs +++ b/oscars/src/collectors/null_collector_branded/mod.rs @@ -18,7 +18,7 @@ pub use root::Root; pub use trace::{Finalize, Trace, Tracer}; pub use weak::WeakGc; -use crate::alloc::mempool3::{PoolAllocError, PoolAllocator, PoolPointer}; +use crate::alloc::mempool3::{PoolAllocError, PoolAllocator}; use core::cell::RefCell; use core::marker::PhantomData; use core::ptr::NonNull; diff --git a/oscars/src/collectors/null_collector_branded/mutation_ctx.rs b/oscars/src/collectors/null_collector_branded/mutation_ctx.rs index 33b7376..952db1c 100644 --- a/oscars/src/collectors/null_collector_branded/mutation_ctx.rs +++ b/oscars/src/collectors/null_collector_branded/mutation_ctx.rs @@ -1,5 +1,5 @@ use crate::{ - alloc::mempool3::{PoolAllocError, PoolPointer}, + alloc::mempool3::PoolAllocError, collectors::null_collector_branded::{ Collector, ephemeron::Ephemeron,