Skip to content

Commit f3fc420

Browse files
committed
[derive] Use crate:: when deriving inside zerogc
This is the proc-macro equivelant of
1 parent 3e57453 commit f3fc420

File tree

2 files changed

+99
-57
lines changed

2 files changed

+99
-57
lines changed

libs/derive/src/lib.rs

+65-39
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
}
@@ -482,13 +501,13 @@ fn impl_extras(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, E
482501
))
483502
};
484503
// 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));
504+
let field_as_ptr = quote_spanned!(field.span() => ZEROGC_CRATE::GcCell::as_ptr(&(*self.value()).#original_name));
505+
let barrier = quote_spanned!(field.span() => ZEROGC_CRATE::GcDirectBarrier::write_barrier(&value, &self, offset));
487506
extra_items.push(quote! {
488507
#[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>> {
508+
#mutator_vis fn #mutator_name<Id>(self: ZEROGC_CRATE::Gc<#gc_lifetime, Self, Id>, value: #value_ref_type)
509+
where Id: ZEROGC_CRATE::CollectorId,
510+
#value_ref_type: ZEROGC_CRATE::GcDirectBarrier<#gc_lifetime, ZEROGC_CRATE::Gc<#gc_lifetime, Self, Id>> {
492511
unsafe {
493512
let target_ptr = #field_as_ptr;
494513
let offset = target_ptr as usize - self.as_raw_ptr() as usize;
@@ -535,13 +554,14 @@ fn impl_extras(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, E
535554

536555

537556
fn impl_erase_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
557+
let zerogc_crate = zerogc_crate();
538558
let name = &target.ident;
539559
let mut generics: Generics = target.generics.clone();
540560
for param in &mut generics.params {
541561
match param {
542562
GenericParam::Type(ref mut type_param) => {
543563
// Require all params are NullTrace
544-
type_param.bounds.push(parse_quote!(::zerogc::NullTrace));
564+
type_param.bounds.push(parse_quote!(ZEROGC_CRATE::NullTrace));
545565
},
546566
GenericParam::Lifetime(ref mut l) => {
547567
if l.lifetime == info.config.gc_lifetime() {
@@ -568,28 +588,29 @@ fn impl_erase_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream
568588
let collector_id = match info.config.collector_id {
569589
Some(ref id) => id.clone(),
570590
None => {
571-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
591+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
572592
parse_quote!(Id)
573593
}
574594
};
575595
// Require that `Self: NullTrace`
576596
impl_generics.make_where_clause().predicates.push(WherePredicate::Type(PredicateType {
577597
lifetimes: None,
578598
bounded_ty: parse_quote!(Self),
579-
bounds: parse_quote!(::zerogc::NullTrace),
599+
bounds: parse_quote!(#zerogc_crate::NullTrace),
580600
colon_token: Default::default()
581601
}));
582602
let (_, ty_generics, _) = generics.split_for_impl();
583603
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
584604
Ok(quote! {
585-
unsafe impl #impl_generics ::zerogc::GcErase<'min, #collector_id>
605+
unsafe impl #impl_generics #zerogc_crate::GcErase<'min, #collector_id>
586606
for #name #ty_generics #where_clause {
587607
// We can pass-through because we are NullTrace
588608
type Erased = Self;
589609
}
590610
})
591611
}
592612
fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
613+
let zerogc_crate = zerogc_crate();
593614
let name = &target.ident;
594615
let mut generics: Generics = target.generics.clone();
595616
let mut rewritten_params = Vec::new();
@@ -603,10 +624,10 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
603624
match param {
604625
GenericParam::Type(ref mut type_param) => {
605626
let original_bounds = type_param.bounds.iter().cloned().collect::<Vec<_>>();
606-
type_param.bounds.push(parse_quote!(::zerogc::GcErase<'min, #collector_id>));
627+
type_param.bounds.push(parse_quote!(#zerogc_crate::GcErase<'min, #collector_id>));
607628
type_param.bounds.push(parse_quote!('min));
608629
let param_name = &type_param.ident;
609-
let rewritten_type: Type = parse_quote!(<#param_name as ::zerogc::GcErase<'min, #collector_id>>::Erased);
630+
let rewritten_type: Type = parse_quote!(<#param_name as #zerogc_crate::GcErase<'min, #collector_id>>::Erased);
610631
rewritten_restrictions.push(WherePredicate::Type(PredicateType {
611632
lifetimes: None,
612633
bounded_ty: rewritten_type.clone(),
@@ -654,17 +675,17 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
654675
let mut impl_generics = generics.clone();
655676
impl_generics.params.push(GenericParam::Lifetime(parse_quote!('min)));
656677
if info.config.collector_id.is_none() {
657-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
678+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
658679
}
659680
impl_generics.make_where_clause().predicates.extend(rewritten_restrictions);
660681
let (_, ty_generics, _) = generics.split_for_impl();
661682
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
662683
let assert_erase = field_types.iter().map(|field_type| {
663684
let span = field_type.span();
664-
quote_spanned!(span => <#field_type as ::zerogc::GcErase<'min, #collector_id>>::assert_erase();)
685+
quote_spanned!(span => <#field_type as #zerogc_crate::GcErase<'min, #collector_id>>::assert_erase();)
665686
}).collect::<Vec<_>>();
666687
Ok(quote! {
667-
unsafe impl #impl_generics ::zerogc::GcErase<'min, #collector_id>
688+
unsafe impl #impl_generics #zerogc_crate::GcErase<'min, #collector_id>
668689
for #name #ty_generics #where_clause {
669690
type Erased = #name::<#(#rewritten_params),*>;
670691

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

678699

679700
fn impl_rebrand_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
701+
let zerogc_crate = zerogc_crate();
680702
let name = &target.ident;
681703
let mut generics: Generics = target.generics.clone();
682704
for param in &mut generics.params {
683705
match param {
684706
GenericParam::Type(ref mut type_param) => {
685707
// Require all params are NullTrace
686-
type_param.bounds.push(parse_quote!(::zerogc::NullTrace));
708+
type_param.bounds.push(parse_quote!(#zerogc_crate::NullTrace));
687709
},
688710
GenericParam::Lifetime(ref mut l) => {
689711
if l.lifetime == info.config.gc_lifetime() {
@@ -710,28 +732,29 @@ fn impl_rebrand_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStre
710732
let collector_id = match info.config.collector_id {
711733
Some(ref id) => id.clone(),
712734
None => {
713-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
735+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
714736
parse_quote!(Id)
715737
}
716738
};
717739
// Require that `Self: NullTrace`
718740
impl_generics.make_where_clause().predicates.push(WherePredicate::Type(PredicateType {
719741
lifetimes: None,
720742
bounded_ty: parse_quote!(Self),
721-
bounds: parse_quote!(::zerogc::NullTrace),
743+
bounds: parse_quote!(#zerogc_crate::NullTrace),
722744
colon_token: Default::default()
723745
}));
724746
let (_, ty_generics, _) = generics.split_for_impl();
725747
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
726748
Ok(quote! {
727-
unsafe impl #impl_generics ::zerogc::GcRebrand<'new_gc, #collector_id>
749+
unsafe impl #impl_generics #zerogc_crate::GcRebrand<'new_gc, #collector_id>
728750
for #name #ty_generics #where_clause {
729751
// We can pass-through because we are NullTrace
730752
type Branded = Self;
731753
}
732754
})
733755
}
734756
fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
757+
let zerogc_crate = zerogc_crate();
735758
let name = &target.ident;
736759
let mut generics: Generics = target.generics.clone();
737760
let mut rewritten_params = Vec::new();
@@ -745,9 +768,9 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
745768
match param {
746769
GenericParam::Type(ref mut type_param) => {
747770
let original_bounds = type_param.bounds.iter().cloned().collect::<Vec<_>>();
748-
type_param.bounds.push(parse_quote!(::zerogc::GcRebrand<'new_gc, #collector_id>));
771+
type_param.bounds.push(parse_quote!(#zerogc_crate::GcRebrand<'new_gc, #collector_id>));
749772
let param_name = &type_param.ident;
750-
let rewritten_type: Type = parse_quote!(<#param_name as ::zerogc::GcRebrand<'new_gc, #collector_id>>::Branded);
773+
let rewritten_type: Type = parse_quote!(<#param_name as #zerogc_crate::GcRebrand<'new_gc, #collector_id>>::Branded);
751774
rewritten_restrictions.push(WherePredicate::Type(PredicateType {
752775
lifetimes: None,
753776
bounded_ty: rewritten_type.clone(),
@@ -795,17 +818,17 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
795818
let mut impl_generics = generics.clone();
796819
impl_generics.params.push(GenericParam::Lifetime(parse_quote!('new_gc)));
797820
if info.config.collector_id.is_none() {
798-
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: ::zerogc::CollectorId)));
821+
impl_generics.params.push(GenericParam::Type(parse_quote!(Id: #zerogc_crate::CollectorId)));
799822
}
800823
let assert_rebrand = field_types.iter().map(|field_type| {
801824
let span = field_type.span();
802-
quote_spanned!(span => <#field_type as ::zerogc::GcRebrand<'new_gc, #collector_id>>::assert_rebrand();)
825+
quote_spanned!(span => <#field_type as #zerogc_crate::GcRebrand<'new_gc, #collector_id>>::assert_rebrand();)
803826
}).collect::<Vec<_>>();
804827
impl_generics.make_where_clause().predicates.extend(rewritten_restrictions);
805828
let (_, ty_generics, _) = generics.split_for_impl();
806829
let (impl_generics, _, where_clause) = impl_generics.split_for_impl();
807830
Ok(quote! {
808-
unsafe impl #impl_generics ::zerogc::GcRebrand<'new_gc, #collector_id>
831+
unsafe impl #impl_generics #zerogc_crate::GcRebrand<'new_gc, #collector_id>
809832
for #name #ty_generics #where_clause {
810833
type Branded = #name::<#(#rewritten_params),*>;
811834

@@ -816,6 +839,7 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
816839
})
817840
}
818841
fn impl_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
842+
let zerogc_crate = zerogc_crate();
819843
let name = &target.ident;
820844
let generics = add_trait_bounds_except(
821845
&target.generics, parse_quote!(zerogc::Trace),
@@ -884,26 +908,27 @@ fn impl_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
884908
},
885909
}
886910
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)*;
911+
unsafe impl #impl_generics #zerogc_crate::Trace for #name #ty_generics #where_clause {
912+
const NEEDS_TRACE: bool = false #(|| <#field_types as #zerogc_crate::Trace>::NEEDS_TRACE)*;
889913

890914
/*
891915
* The inline annotation adds this function's MIR to the metadata.
892916
* Without it cross-crate inlining is impossible (without LTO).
893917
*/
894918
#[inline]
895-
fn visit<V: ::zerogc::GcVisitor>(&mut self, #[allow(unused)] visitor: &mut V) -> Result<(), V::Err> {
919+
fn visit<Visitor: #zerogc_crate::GcVisitor + ?Sized>(&mut self, #[allow(unused)] visitor: &mut Visitor) -> Result<(), Visitor::Err> {
896920
#trace_impl
897921
Ok(())
898922
}
899923
}
900924
})
901925
}
902926
fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
927+
let zerogc_crate = zerogc_crate();
903928
let name = &target.ident;
904929
let collector_id = &info.config.collector_id;
905930
let generics = add_trait_bounds_except(
906-
&target.generics, parse_quote!(zerogc::GcSafe),
931+
&target.generics, parse_quote!(#zerogc_crate::GcSafe),
907932
&info.config.ignore_params,
908933
Some(&mut |other: &Ident| {
909934
if let Some(ref collector_id) = *collector_id {
@@ -936,7 +961,7 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
936961
quote!(false)
937962
} else {
938963
// We need to be dropped if any of our fields need to be dropped
939-
quote!(false #(|| <#field_types as ::zerogc::GcSafe>::NEEDS_DROP)*)
964+
quote!(false #(|| <#field_types as #zerogc_crate::GcSafe>::NEEDS_DROP)*)
940965
};
941966
let fake_drop_impl = if info.config.is_copy {
942967
/*
@@ -959,12 +984,12 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
959984
})
960985
};
961986
let verify_gc_safe = if info.config.is_copy {
962-
quote!(::zerogc::assert_copy::<Self>())
987+
quote!(#zerogc_crate::assert_copy::<Self>())
963988
} else {
964-
quote!(#(<#field_types as GcSafe>::assert_gc_safe();)*)
989+
quote!(#(<#field_types as #zerogc_crate::GcSafe>::assert_gc_safe();)*)
965990
};
966991
Ok(quote! {
967-
unsafe impl #impl_generics ::zerogc::GcSafe
992+
unsafe impl #impl_generics #zerogc_crate::GcSafe
968993
for #name #ty_generics #where_clause {
969994
const NEEDS_DROP: bool = #does_need_drop;
970995

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

9791004

9801005
fn impl_nop_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Error> {
1006+
let zerogc_crate = zerogc_crate();
9811007
let name = &target.ident;
9821008
let generics = add_trait_bounds_except(
983-
&target.generics, parse_quote!(zerogc::Trace),
1009+
&target.generics, parse_quote!(#zerogc_crate::Trace),
9841010
&info.config.ignore_params, None
9851011
)?;
9861012
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
@@ -1007,30 +1033,30 @@ fn impl_nop_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream
10071033
let ty_span = t.span();
10081034
quote_spanned! { ty_span =>
10091035
assert!(
1010-
!<#t as Trace>::NEEDS_TRACE,
1036+
!<#t as #zerogc_crate::Trace>::NEEDS_TRACE,
10111037
"Can't #[derive(NullTrace) with {}",
10121038
stringify!(#t)
10131039
);
10141040
}
10151041
}).collect::<Vec<_>>();
10161042
Ok(quote! {
1017-
unsafe impl #impl_generics ::zerogc::Trace for #name #ty_generics #where_clause {
1043+
unsafe impl #impl_generics #zerogc_crate::Trace for #name #ty_generics #where_clause {
10181044
const NEEDS_TRACE: bool = false;
10191045

10201046
#[inline] // Should be const-folded away
1021-
fn visit<V: ::zerogc::GcVisitor>(&mut self, #[allow(unused)] visitor: &mut V) -> Result<(), V::Err> {
1047+
fn visit<Visitor: #zerogc_crate::GcVisitor + ?Sized>(&mut self, #[allow(unused)] visitor: &mut Visitor) -> Result<(), Visitor::Err> {
10221048
#(#trace_assertions)*
10231049
Ok(())
10241050
}
10251051
}
1026-
unsafe impl #impl_generics ::zerogc::TraceImmutable for #name #ty_generics #where_clause {
1052+
unsafe impl #impl_generics #zerogc_crate::TraceImmutable for #name #ty_generics #where_clause {
10271053
#[inline] // Should be const-folded away
1028-
fn visit_immutable<V: ::zerogc::GcVisitor>(&self, #[allow(unused)] visitor: &mut V) -> Result<(), V::Err> {
1054+
fn visit_immutable<Visitor: #zerogc_crate::GcVisitor + ?Sized>(&self, #[allow(unused)] visitor: &mut Visitor) -> Result<(), Visitor::Err> {
10291055
#(#trace_assertions)*
10301056
Ok(())
10311057
}
10321058
}
1033-
unsafe impl #impl_generics ::zerogc::NullTrace for #name #ty_generics #where_clause {}
1059+
unsafe impl #impl_generics #zerogc_crate::NullTrace for #name #ty_generics #where_clause {}
10341060
})
10351061
}
10361062

0 commit comments

Comments
 (0)