diff --git a/src/gc-arena/src/arena.rs b/src/gc-arena/src/arena.rs index 4a4c1511..b1256a07 100644 --- a/src/gc-arena/src/arena.rs +++ b/src/gc-arena/src/arena.rs @@ -66,7 +66,7 @@ impl ArenaParameters { /// `Rootable<'a>` for *any* possible `'a`. This is necessary so that the `Root` types can be /// branded by the unique, invariant lifetimes that makes an `Arena` sound. pub trait Rootable<'a> { - type Root: Collect + 'a; + type Root: ?Sized + Collect + 'a; } /// A convenience macro for quickly creating type that implements of `Rootable`. @@ -139,13 +139,19 @@ pub type Root<'a, R> = >::Root; /// this way, incremental garbage collection can be achieved (assuming "sufficiently small" calls /// to `mutate`) that is both extremely safe and zero overhead vs what you would write in C with raw /// pointers and manually ensuring that invariants are held. -pub struct Arena Rootable<'a> + ?Sized> { +pub struct Arena Rootable<'a> + ?Sized> +where + Root<'static, R>: Sized, +{ // We rely on the implicit drop order here, `root` *must* be dropped before `context`! root: Root<'static, R>, context: Context, } -impl Rootable<'a> + ?Sized> Arena { +impl Rootable<'a> + ?Sized> Arena +where + Root<'static, R>: Sized, +{ /// Create a new arena with the given garbage collector tuning parameters. You must provide a /// closure that accepts a `MutationContext` and returns the appropriate root. pub fn new(arena_parameters: ArenaParameters, f: F) -> Arena @@ -216,7 +222,10 @@ impl Rootable<'a> + ?Sized> Arena { pub fn map_root Rootable<'a> + ?Sized>( self, f: impl for<'gc> FnOnce(MutationContext<'gc, '_>, Root<'gc, R>) -> Root<'gc, R2>, - ) -> Arena { + ) -> Arena + where + Root<'static, R2>: Sized, + { self.context.root_barrier(); let new_root: Root<'static, R2> = unsafe { f(self.context.mutation_context(), self.root) }; Arena { @@ -229,7 +238,10 @@ impl Rootable<'a> + ?Sized> Arena { pub fn try_map_root Rootable<'a> + ?Sized, E>( self, f: impl for<'gc> FnOnce(MutationContext<'gc, '_>, Root<'gc, R>) -> Result, E>, - ) -> Result, E> { + ) -> Result, E> + where + Root<'static, R2>: Sized, + { self.context.root_barrier(); let new_root: Root<'static, R2> = unsafe { f(self.context.mutation_context(), self.root)? }; Ok(Arena { diff --git a/src/gc-arena/tests/tests.rs b/src/gc-arena/tests/tests.rs index 0d0aae44..4574ca0e 100644 --- a/src/gc-arena/tests/tests.rs +++ b/src/gc-arena/tests/tests.rs @@ -415,6 +415,10 @@ fn test_dynamic_roots() { ) }); + let root3 = arena.mutate(|mc, root_set| { + root_set.stash::(mc, unsize!(Gc::allocate(mc, [1, 2, 3]) => [u8])) + }); + arena.collect_all(); arena.collect_all(); @@ -427,10 +431,14 @@ fn test_dynamic_roots() { let root2 = root_set.fetch(&root2); assert_eq!(*root2.0, 27); assert_eq!(*root2.1, true); + + let root3 = root_set.fetch::(&root3); + assert_eq!(*root3, [1, 2, 3]); }); drop(root1); drop(root2); + drop(root3); arena.collect_all(); arena.collect_all();