Skip to content

Commit 42ef1e6

Browse files
committed
[derive] Use crate:: when deriving inside zerogc
This is the proc-macro equivelant of '$crate'
1 parent 952bd16 commit 42ef1e6

File tree

4 files changed

+101
-59
lines changed

4 files changed

+101
-59
lines changed

libs/derive/src/lib.rs

Lines changed: 66 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,24 @@ use std::io::Write;
1515

1616
mod macros;
1717

18+
/// Magic const that expands to either `::zerogc` or `crate::`
19+
/// depending on whether we are currently bootstraping (compiling `zerogc` itself)
20+
///
21+
/// This is equivalant to `$crate` for regular macros
22+
pub(crate) fn zerogc_crate() -> TokenStream {
23+
if is_bootstraping() {
24+
quote!(crate)
25+
} else {
26+
quote!(::zerogc)
27+
}
28+
}
29+
30+
/// If we are currently compiling the base crate `zerogc` itself
31+
pub(crate) fn is_bootstraping() -> bool {
32+
::proc_macro::tracked_env::var("CARGO_CRATE_NAME")
33+
.expect("Expected `CARGO_CRATE_NAME`") == "zerogc"
34+
}
35+
1836
struct MutableFieldOpts {
1937
public: bool
2038
}
@@ -410,14 +428,15 @@ fn impl_derive_trace(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
410428
}
411429

412430
fn trace_fields(fields: &Fields, access_ref: &mut dyn FnMut(Member) -> TokenStream) -> TokenStream {
431+
let zerogc_crate = zerogc_crate();
413432
// TODO: Detect if we're a unit struct and implement `NullTrace`
414433
let mut result = Vec::new();
415434
for (index, field) in fields.iter().enumerate() {
416435
let val = access_ref(match field.ident {
417436
Some(ref ident) => Member::Named(ident.clone()),
418437
None => Member::Unnamed(Index::from(index))
419438
});
420-
result.push(quote!(::zerogc::Trace::visit(#val, &mut *visitor)?));
439+
result.push(quote!(#zerogc_crate::Trace::visit(#val, &mut *visitor)?));
421440
}
422441
quote!(#(#result;)*)
423442
}
@@ -426,6 +445,7 @@ fn trace_fields(fields: &Fields, access_ref: &mut dyn FnMut(Member) -> TokenStre
426445
///
427446
/// 1. Implement setters for `GcCell` fields using a write barrier
428447
fn impl_extras(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
448+
let zerogc_crate = zerogc_crate();
429449
let name = &target.ident;
430450
let mut extra_items = Vec::new();
431451
let gc_lifetime = info.config.gc_lifetime();
@@ -482,13 +502,13 @@ fn impl_extras(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, E
482502
))
483503
};
484504
// NOTE: Specially quoted since we want to blame the field for errors
485-
let field_as_ptr = quote_spanned!(field.span() => GcCell::as_ptr(&(*self.value()).#original_name));
486-
let barrier = quote_spanned!(field.span() => ::zerogc::GcDirectBarrier::write_barrier(&value, &self, offset));
505+
let field_as_ptr = quote_spanned!(field.span() => #zerogc_crate::cell::GcCell::as_ptr(&(*self.value()).#original_name));
506+
let barrier = quote_spanned!(field.span() => #zerogc_crate::GcDirectBarrier::write_barrier(&value, &self, offset));
487507
extra_items.push(quote! {
488508
#[inline] // TODO: Implement `GcDirectBarrier` ourselves
489-
#mutator_vis fn #mutator_name<Id>(self: ::zerogc::Gc<#gc_lifetime, Self, Id>, value: #value_ref_type)
490-
where Id: ::zerogc::CollectorId,
491-
#value_ref_type: ::zerogc::GcDirectBarrier<#gc_lifetime, ::zerogc::Gc<#gc_lifetime, Self, Id>> {
509+
#mutator_vis fn #mutator_name<Id>(self: #zerogc_crate::Gc<#gc_lifetime, Self, Id>, value: #value_ref_type)
510+
where Id: #zerogc_crate::CollectorId,
511+
#value_ref_type: #zerogc_crate::GcDirectBarrier<#gc_lifetime, #zerogc_crate::Gc<#gc_lifetime, Self, Id>> {
492512
unsafe {
493513
let target_ptr = #field_as_ptr;
494514
let offset = target_ptr as usize - self.as_raw_ptr() as usize;
@@ -535,13 +555,14 @@ fn impl_extras(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, E
535555

536556

537557
fn impl_erase_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
558+
let zerogc_crate = zerogc_crate();
538559
let name = &target.ident;
539560
let mut generics: Generics = target.generics.clone();
540561
for param in &mut generics.params {
541562
match param {
542563
GenericParam::Type(ref mut type_param) => {
543564
// Require all params are NullTrace
544-
type_param.bounds.push(parse_quote!(::zerogc::NullTrace));
565+
type_param.bounds.push(parse_quote!(#zerogc_crate::NullTrace));
545566
},
546567
GenericParam::Lifetime(ref mut l) => {
547568
if l.lifetime == info.config.gc_lifetime() {
@@ -568,28 +589,29 @@ fn impl_erase_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream
568589
let collector_id = match info.config.collector_id {
569590
Some(ref id) => id.clone(),
570591
None => {
571-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
592+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
572593
parse_quote!(Id)
573594
}
574595
};
575596
// Require that `Self: NullTrace`
576597
impl_generics.make_where_clause().predicates.push(WherePredicate::Type(PredicateType {
577598
lifetimes: None,
578599
bounded_ty: parse_quote!(Self),
579-
bounds: parse_quote!(::zerogc::NullTrace),
600+
bounds: parse_quote!(#zerogc_crate::NullTrace),
580601
colon_token: Default::default()
581602
}));
582603
let (_, ty_generics, _) = generics.split_for_impl();
583604
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
584605
Ok(quote! {
585-
unsafe impl #impl_generics ::zerogc::GcErase<'min, #collector_id>
606+
unsafe impl #impl_generics #zerogc_crate::GcErase<'min, #collector_id>
586607
for #name #ty_generics #where_clause {
587608
// We can pass-through because we are NullTrace
588609
type Erased = Self;
589610
}
590611
})
591612
}
592613
fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
614+
let zerogc_crate = zerogc_crate();
593615
let name = &target.ident;
594616
let mut generics: Generics = target.generics.clone();
595617
let mut rewritten_params = Vec::new();
@@ -603,10 +625,10 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
603625
match param {
604626
GenericParam::Type(ref mut type_param) => {
605627
let original_bounds = type_param.bounds.iter().cloned().collect::<Vec<_>>();
606-
type_param.bounds.push(parse_quote!(::zerogc::GcErase<'min, #collector_id>));
628+
type_param.bounds.push(parse_quote!(#zerogc_crate::GcErase<'min, #collector_id>));
607629
type_param.bounds.push(parse_quote!('min));
608630
let param_name = &type_param.ident;
609-
let rewritten_type: Type = parse_quote!(<#param_name as ::zerogc::GcErase<'min, #collector_id>>::Erased);
631+
let rewritten_type: Type = parse_quote!(<#param_name as #zerogc_crate::GcErase<'min, #collector_id>>::Erased);
610632
rewritten_restrictions.push(WherePredicate::Type(PredicateType {
611633
lifetimes: None,
612634
bounded_ty: rewritten_type.clone(),
@@ -654,17 +676,17 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
654676
let mut impl_generics = generics.clone();
655677
impl_generics.params.push(GenericParam::Lifetime(parse_quote!('min)));
656678
if info.config.collector_id.is_none() {
657-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
679+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
658680
}
659681
impl_generics.make_where_clause().predicates.extend(rewritten_restrictions);
660682
let (_, ty_generics, _) = generics.split_for_impl();
661683
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
662684
let assert_erase = field_types.iter().map(|field_type| {
663685
let span = field_type.span();
664-
quote_spanned!(span => <#field_type as ::zerogc::GcErase<'min, #collector_id>>::assert_erase();)
686+
quote_spanned!(span => <#field_type as #zerogc_crate::GcErase<'min, #collector_id>>::assert_erase();)
665687
}).collect::<Vec<_>>();
666688
Ok(quote! {
667-
unsafe impl #impl_generics ::zerogc::GcErase<'min, #collector_id>
689+
unsafe impl #impl_generics #zerogc_crate::GcErase<'min, #collector_id>
668690
for #name #ty_generics #where_clause {
669691
type Erased = #name::<#(#rewritten_params),*>;
670692

@@ -677,13 +699,14 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
677699

678700

679701
fn impl_rebrand_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
702+
let zerogc_crate = zerogc_crate();
680703
let name = &target.ident;
681704
let mut generics: Generics = target.generics.clone();
682705
for param in &mut generics.params {
683706
match param {
684707
GenericParam::Type(ref mut type_param) => {
685708
// Require all params are NullTrace
686-
type_param.bounds.push(parse_quote!(::zerogc::NullTrace));
709+
type_param.bounds.push(parse_quote!(#zerogc_crate::NullTrace));
687710
},
688711
GenericParam::Lifetime(ref mut l) => {
689712
if l.lifetime == info.config.gc_lifetime() {
@@ -710,28 +733,29 @@ fn impl_rebrand_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStre
710733
let collector_id = match info.config.collector_id {
711734
Some(ref id) => id.clone(),
712735
None => {
713-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
736+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
714737
parse_quote!(Id)
715738
}
716739
};
717740
// Require that `Self: NullTrace`
718741
impl_generics.make_where_clause().predicates.push(WherePredicate::Type(PredicateType {
719742
lifetimes: None,
720743
bounded_ty: parse_quote!(Self),
721-
bounds: parse_quote!(::zerogc::NullTrace),
744+
bounds: parse_quote!(#zerogc_crate::NullTrace),
722745
colon_token: Default::default()
723746
}));
724747
let (_, ty_generics, _) = generics.split_for_impl();
725748
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
726749
Ok(quote! {
727-
unsafe impl #impl_generics ::zerogc::GcRebrand<'new_gc, #collector_id>
750+
unsafe impl #impl_generics #zerogc_crate::GcRebrand<'new_gc, #collector_id>
728751
for #name #ty_generics #where_clause {
729752
// We can pass-through because we are NullTrace
730753
type Branded = Self;
731754
}
732755
})
733756
}
734757
fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
758+
let zerogc_crate = zerogc_crate();
735759
let name = &target.ident;
736760
let mut generics: Generics = target.generics.clone();
737761
let mut rewritten_params = Vec::new();
@@ -745,9 +769,9 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
745769
match param {
746770
GenericParam::Type(ref mut type_param) => {
747771
let original_bounds = type_param.bounds.iter().cloned().collect::<Vec<_>>();
748-
type_param.bounds.push(parse_quote!(::zerogc::GcRebrand<'new_gc, #collector_id>));
772+
type_param.bounds.push(parse_quote!(#zerogc_crate::GcRebrand<'new_gc, #collector_id>));
749773
let param_name = &type_param.ident;
750-
let rewritten_type: Type = parse_quote!(<#param_name as ::zerogc::GcRebrand<'new_gc, #collector_id>>::Branded);
774+
let rewritten_type: Type = parse_quote!(<#param_name as #zerogc_crate::GcRebrand<'new_gc, #collector_id>>::Branded);
751775
rewritten_restrictions.push(WherePredicate::Type(PredicateType {
752776
lifetimes: None,
753777
bounded_ty: rewritten_type.clone(),
@@ -795,17 +819,17 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
795819
let mut impl_generics = generics.clone();
796820
impl_generics.params.push(GenericParam::Lifetime(parse_quote!('new_gc)));
797821
if info.config.collector_id.is_none() {
798-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
822+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
799823
}
800824
let assert_rebrand = field_types.iter().map(|field_type| {
801825
let span = field_type.span();
802-
quote_spanned!(span => <#field_type as ::zerogc::GcRebrand<'new_gc, #collector_id>>::assert_rebrand();)
826+
quote_spanned!(span => <#field_type as #zerogc_crate::GcRebrand<'new_gc, #collector_id>>::assert_rebrand();)
803827
}).collect::<Vec<_>>();
804828
impl_generics.make_where_clause().predicates.extend(rewritten_restrictions);
805829
let (_, ty_generics, _) = generics.split_for_impl();
806830
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
807831
Ok(quote! {
808-
unsafe impl #impl_generics ::zerogc::GcRebrand<'new_gc, #collector_id>
832+
unsafe impl #impl_generics #zerogc_crate::GcRebrand<'new_gc, #collector_id>
809833
for #name #ty_generics #where_clause {
810834
type Branded = #name::<#(#rewritten_params),*>;
811835

@@ -816,6 +840,7 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
816840
})
817841
}
818842
fn impl_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
843+
let zerogc_crate = zerogc_crate();
819844
let name = &target.ident;
820845
let generics = add_trait_bounds_except(
821846
&target.generics, parse_quote!(zerogc::Trace),
@@ -884,26 +909,27 @@ fn impl_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
884909
},
885910
}
886911
Ok(quote! {
887-
unsafe impl #impl_generics ::zerogc::Trace for #name #ty_generics #where_clause {
888-
const NEEDS_TRACE: bool = false #(|| <#field_types as ::zerogc::Trace>::NEEDS_TRACE)*;
912+
unsafe impl #impl_generics #zerogc_crate::Trace for #name #ty_generics #where_clause {
913+
const NEEDS_TRACE: bool = false #(|| <#field_types as #zerogc_crate::Trace>::NEEDS_TRACE)*;
889914

890915
/*
891916
* The inline annotation adds this function's MIR to the metadata.
892917
* Without it cross-crate inlining is impossible (without LTO).
893918
*/
894919
#[inline]
895-
fn visit<V: ::zerogc::GcVisitor>(&mut self, #[allow(unused)] visitor: &mut V) -> Result<(), V::Err> {
920+
fn visit<Visitor: #zerogc_crate::GcVisitor + ?Sized>(&mut self, #[allow(unused)] visitor: &mut Visitor) -> Result<(), Visitor::Err> {
896921
#trace_impl
897922
Ok(())
898923
}
899924
}
900925
})
901926
}
902927
fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
928+
let zerogc_crate = zerogc_crate();
903929
let name = &target.ident;
904930
let collector_id = &info.config.collector_id;
905931
let generics = add_trait_bounds_except(
906-
&target.generics, parse_quote!(zerogc::GcSafe),
932+
&target.generics, parse_quote!(#zerogc_crate::GcSafe),
907933
&info.config.ignore_params,
908934
Some(&mut |other: &Ident| {
909935
if let Some(ref collector_id) = *collector_id {
@@ -936,7 +962,7 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
936962
quote!(false)
937963
} else {
938964
// We need to be dropped if any of our fields need to be dropped
939-
quote!(false #(|| <#field_types as ::zerogc::GcSafe>::NEEDS_DROP)*)
965+
quote!(false #(|| <#field_types as #zerogc_crate::GcSafe>::NEEDS_DROP)*)
940966
};
941967
let fake_drop_impl = if info.config.is_copy {
942968
/*
@@ -959,12 +985,12 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
959985
})
960986
};
961987
let verify_gc_safe = if info.config.is_copy {
962-
quote!(::zerogc::assert_copy::<Self>())
988+
quote!(#zerogc_crate::assert_copy::<Self>())
963989
} else {
964-
quote!(#(<#field_types as GcSafe>::assert_gc_safe();)*)
990+
quote!(#(<#field_types as #zerogc_crate::GcSafe>::assert_gc_safe();)*)
965991
};
966992
Ok(quote! {
967-
unsafe impl #impl_generics ::zerogc::GcSafe
993+
unsafe impl #impl_generics #zerogc_crate::GcSafe
968994
for #name #ty_generics #where_clause {
969995
const NEEDS_DROP: bool = #does_need_drop;
970996

@@ -978,9 +1004,10 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
9781004

9791005

9801006
fn impl_nop_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
1007+
let zerogc_crate = zerogc_crate();
9811008
let name = &target.ident;
9821009
let generics = add_trait_bounds_except(
983-
&target.generics, parse_quote!(zerogc::Trace),
1010+
&target.generics, parse_quote!(#zerogc_crate::Trace),
9841011
&info.config.ignore_params, None
9851012
)?;
9861013
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
@@ -1007,30 +1034,30 @@ fn impl_nop_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream
10071034
let ty_span = t.span();
10081035
quote_spanned! { ty_span =>
10091036
assert!(
1010-
!<#t as Trace>::NEEDS_TRACE,
1037+
!<#t as #zerogc_crate::Trace>::NEEDS_TRACE,
10111038
"Can't #[derive(NullTrace) with {}",
10121039
stringify!(#t)
10131040
);
10141041
}
10151042
}).collect::<Vec<_>>();
10161043
Ok(quote! {
1017-
unsafe impl #impl_generics ::zerogc::Trace for #name #ty_generics #where_clause {
1044+
unsafe impl #impl_generics #zerogc_crate::Trace for #name #ty_generics #where_clause {
10181045
const NEEDS_TRACE: bool = false;
10191046

10201047
#[inline] // Should be const-folded away
1021-
fn visit<V: ::zerogc::GcVisitor>(&mut self, #[allow(unused)] visitor: &mut V) -> Result<(), V::Err> {
1048+
fn visit<Visitor: #zerogc_crate::GcVisitor + ?Sized>(&mut self, #[allow(unused)] visitor: &mut Visitor) -> Result<(), Visitor::Err> {
10221049
#(#trace_assertions)*
10231050
Ok(())
10241051
}
10251052
}
1026-
unsafe impl #impl_generics ::zerogc::TraceImmutable for #name #ty_generics #where_clause {
1053+
unsafe impl #impl_generics #zerogc_crate::TraceImmutable for #name #ty_generics #where_clause {
10271054
#[inline] // Should be const-folded away
1028-
fn visit_immutable<V: ::zerogc::GcVisitor>(&self, #[allow(unused)] visitor: &mut V) -> Result<(), V::Err> {
1055+
fn visit_immutable<Visitor: #zerogc_crate::GcVisitor + ?Sized>(&self, #[allow(unused)] visitor: &mut Visitor) -> Result<(), Visitor::Err> {
10291056
#(#trace_assertions)*
10301057
Ok(())
10311058
}
10321059
}
1033-
unsafe impl #impl_generics ::zerogc::NullTrace for #name #ty_generics #where_clause {}
1060+
unsafe impl #impl_generics #zerogc_crate::NullTrace for #name #ty_generics #where_clause {}
10341061
})
10351062
}
10361063

0 commit comments

Comments
 (0)