Skip to content

Commit de6f5d7

Browse files
committed
Fix duplicate 'Id' generics with #[zerogc(mutable)]
Add unit tests to ensure this doesn't happen again
1 parent 3c308f7 commit de6f5d7

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

libs/derive/src/lib.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,11 +599,26 @@ fn impl_extras(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, E
599599
// NOTE: Specially quoted since we want to blame the field for errors
600600
let field_as_ptr = quote_spanned!(field.span() => #zerogc_crate::cell::GcCell::as_ptr(&(*self.value()).#original_name));
601601
let barrier = quote_spanned!(field.span() => #zerogc_crate::GcDirectBarrier::write_barrier(&value, &self, offset));
602+
let id_name = info.config.collector_id.as_ref().cloned()
603+
.unwrap_or_else(|| parse_quote!(Id));
604+
let mut id_generics: Generics = if let Some(ref id_name) = info.config.collector_id {
605+
let mut generics = Generics::default();
606+
generics.make_where_clause().predicates.push(parse_quote!(#id_name: CollectorId));
607+
generics
608+
} else {
609+
parse_quote!(<Id: CollectorId>)
610+
};
611+
id_generics.make_where_clause().predicates.push(parse_quote!(
612+
#value_ref_type: #zerogc_crate::GcDirectBarrier<
613+
#gc_lifetime,
614+
#zerogc_crate::Gc<#gc_lifetime, Self, #id_name>
615+
>
616+
));
617+
let where_clause = &id_generics.where_clause;
602618
extra_items.push(quote! {
603619
#[inline] // TODO: Implement `GcDirectBarrier` ourselves
604-
#mutator_vis fn #mutator_name<Id>(self: #zerogc_crate::Gc<#gc_lifetime, Self, Id>, value: #value_ref_type)
605-
where Id: #zerogc_crate::CollectorId,
606-
#value_ref_type: #zerogc_crate::GcDirectBarrier<#gc_lifetime, #zerogc_crate::Gc<#gc_lifetime, Self, Id>> {
620+
#mutator_vis fn #mutator_name #id_generics(self: #zerogc_crate::Gc<#gc_lifetime, Self, #id_name>, value: #value_ref_type)
621+
#where_clause {
607622
unsafe {
608623
let target_ptr = #field_as_ptr;
609624
let offset = target_ptr as usize - self.as_raw_ptr() as usize;

libs/derive/tests/basic.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1+
#![feature(
2+
arbitrary_self_types, // Used for `zerogc(mutable)`
3+
)]
14
use zerogc::{Gc, CollectorId, Trace, GcSafe, NullTrace, dummy_impl::{self, DummyCollectorId}};
25

36
use zerogc_derive::{Trace, NullTrace};
7+
use zerogc::cell::GcCell;
48

59
#[derive(Trace)]
610
#[zerogc(collector_id(DummyCollectorId))]
711
pub struct SpecificCollector<'gc> {
812
gc: Gc<'gc, i32, DummyCollectorId>,
9-
rec: Gc<'gc, SpecificCollector<'gc>, DummyCollectorId>
13+
rec: Gc<'gc, SpecificCollector<'gc>, DummyCollectorId>,
14+
#[zerogc(mutable)]
15+
cell: GcCell<Gc<'gc, SpecificCollector<'gc>, DummyCollectorId>>
1016
}
1117

1218
#[derive(Trace)]
1319
#[zerogc(collector_id(Id))]
1420
pub struct Basic<'gc, Id: CollectorId> {
1521
parent: Option<Gc<'gc, Basic<'gc, Id>, Id>>,
1622
children: Vec<Gc<'gc, Basic<'gc, Id>, Id>>,
17-
value: String
23+
value: String,
24+
#[zerogc(mutable)]
25+
cell: GcCell<Option<Gc<'gc, Basic<'gc, Id>, Id>>>
1826
}
1927

2028
#[derive(Copy, Clone, Trace)]
@@ -110,7 +118,8 @@ fn basic<'gc>() {
110118
let _b = Basic::<dummy_impl::DummyCollectorId> {
111119
value: String::new(),
112120
parent: None,
113-
children: vec![]
121+
children: vec![],
122+
cell: GcCell::new(None)
114123
};
115124
assert!(<Basic::<dummy_impl::DummyCollectorId> as Trace>::NEEDS_TRACE);
116125
assert!(<BasicCopy::<dummy_impl::DummyCollectorId> as Trace>::NEEDS_TRACE);

0 commit comments

Comments
 (0)