diff --git a/src/gc-arena/src/arena.rs b/src/gc-arena/src/arena.rs index 7c33339..e2fb79a 100644 --- a/src/gc-arena/src/arena.rs +++ b/src/gc-arena/src/arena.rs @@ -97,18 +97,14 @@ impl ArenaParameters { /// pointers and manually ensuring that invariants are held. #[macro_export] macro_rules! make_arena { - ($arena:ident, $root:ident) => { - make_arena!(pub(self) $arena, $root); - }; - - ($vis:vis $arena:ident, $root:ident) => { + ($vis:vis $arena:ident $(( $($arena_gen:tt)* ))?, $root:ident $(( $($root_gen:tt)* ))?) => { // Instead of generating an impl of `RootProvider`, we use a trait object. // The projection `>::Root` is used to obtain the root // type with the lifetime `'gc` applied // By using a trait object, we avoid the need to generate a new type for each // invocation of this macro, which would lead to name conflicts if the macro was // used multiple times in the same scope. - $vis type $arena = $crate::Arena $crate::RootProvider<'a, Root = $root<'a>>>; + $vis type $arena $( <$($arena_gen)*> )? = $crate::Arena $crate::RootProvider<'gc, Root = $root<'gc, $( $($root_gen)* )?>>>; }; } diff --git a/src/gc-arena/tests/tests.rs b/src/gc-arena/tests/tests.rs index c59d576..d788dbf 100644 --- a/src/gc-arena/tests/tests.rs +++ b/src/gc-arena/tests/tests.rs @@ -251,6 +251,27 @@ fn derive_collect() { assert_eq!(Test8::needs_trace(), false); } +#[test] +fn generic_make_arena() { + #[derive(Collect)] + #[collect(no_drop)] + struct Test<'gc, T: 'gc + Collect, const N: usize, U: 'gc + Collect>(Gc<'gc, T>, [(); N], U); + make_arena!(TestArena(T, const N: usize, U), Test((T, T), N, Gc<'gc, U>)); + + fn test( + v: T, + x: U, + ) -> ((T, T), usize, U) { + let arena = TestArena::::new(Default::default(), |mc| { + Test(Gc::allocate(mc, (v, v)), [(); N], Gc::allocate(mc, x)) + }); + arena.mutate(|_, arena| (*arena.0, arena.1.len(), *arena.2)) + } + + assert_eq!(test::<12, _, _>(34, 12i8), ((34, 34), 12, 12i8)); + assert_eq!(test::<7, _, _>(false, -6i64), ((false, false), 7, -6i64)); +} + #[test] fn ui() { let t = trybuild::TestCases::new();