@@ -15,6 +15,24 @@ use std::io::Write;
1515
1616mod 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+
1836struct MutableFieldOpts {
1937 public : bool
2038}
@@ -410,14 +428,15 @@ fn impl_derive_trace(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
410428}
411429
412430fn 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
428447fn 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 :: 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
537557fn 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}
592613fn 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
679701fn 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}
734757fn 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}
818842fn 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}
902927fn 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
9801006fn 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