@@ -15,6 +15,24 @@ use std::io::Write;
15
15
16
16
mod macros;
17
17
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
+
18
36
struct MutableFieldOpts {
19
37
public : bool
20
38
}
@@ -410,14 +428,15 @@ fn impl_derive_trace(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
410
428
}
411
429
412
430
fn trace_fields ( fields : & Fields , access_ref : & mut dyn FnMut ( Member ) -> TokenStream ) -> TokenStream {
431
+ let zerogc_crate = zerogc_crate ( ) ;
413
432
// TODO: Detect if we're a unit struct and implement `NullTrace`
414
433
let mut result = Vec :: new ( ) ;
415
434
for ( index, field) in fields. iter ( ) . enumerate ( ) {
416
435
let val = access_ref ( match field. ident {
417
436
Some ( ref ident) => Member :: Named ( ident. clone ( ) ) ,
418
437
None => Member :: Unnamed ( Index :: from ( index) )
419
438
} ) ;
420
- result. push ( quote ! ( :: zerogc :: Trace :: visit( #val, & mut * visitor) ?) ) ;
439
+ result. push ( quote ! ( #zerogc_crate :: Trace :: visit( #val, & mut * visitor) ?) ) ;
421
440
}
422
441
quote ! ( #( #result; ) * )
423
442
}
@@ -426,6 +445,7 @@ fn trace_fields(fields: &Fields, access_ref: &mut dyn FnMut(Member) -> TokenStre
426
445
///
427
446
/// 1. Implement setters for `GcCell` fields using a write barrier
428
447
fn impl_extras ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
448
+ let zerogc_crate = zerogc_crate ( ) ;
429
449
let name = & target. ident ;
430
450
let mut extra_items = Vec :: new ( ) ;
431
451
let gc_lifetime = info. config . gc_lifetime ( ) ;
@@ -482,13 +502,13 @@ fn impl_extras(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, E
482
502
) )
483
503
} ;
484
504
// 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) ) ;
487
507
extra_items. push ( quote ! {
488
508
#[ 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 >> {
492
512
unsafe {
493
513
let target_ptr = #field_as_ptr;
494
514
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
535
555
536
556
537
557
fn impl_erase_nop ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
558
+ let zerogc_crate = zerogc_crate ( ) ;
538
559
let name = & target. ident ;
539
560
let mut generics: Generics = target. generics . clone ( ) ;
540
561
for param in & mut generics. params {
541
562
match param {
542
563
GenericParam :: Type ( ref mut type_param) => {
543
564
// Require all params are NullTrace
544
- type_param. bounds . push ( parse_quote ! ( :: zerogc :: NullTrace ) ) ;
565
+ type_param. bounds . push ( parse_quote ! ( #zerogc_crate :: NullTrace ) ) ;
545
566
} ,
546
567
GenericParam :: Lifetime ( ref mut l) => {
547
568
if l. lifetime == info. config . gc_lifetime ( ) {
@@ -568,28 +589,29 @@ fn impl_erase_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream
568
589
let collector_id = match info. config . collector_id {
569
590
Some ( ref id) => id. clone ( ) ,
570
591
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 ) ) ) ;
572
593
parse_quote ! ( Id )
573
594
}
574
595
} ;
575
596
// Require that `Self: NullTrace`
576
597
impl_generics. make_where_clause ( ) . predicates . push ( WherePredicate :: Type ( PredicateType {
577
598
lifetimes : None ,
578
599
bounded_ty : parse_quote ! ( Self ) ,
579
- bounds : parse_quote ! ( :: zerogc :: NullTrace ) ,
600
+ bounds : parse_quote ! ( #zerogc_crate :: NullTrace ) ,
580
601
colon_token : Default :: default ( )
581
602
} ) ) ;
582
603
let ( _, ty_generics, _) = generics. split_for_impl ( ) ;
583
604
let ( impl_generics, _, where_clause) = impl_generics. split_for_impl ( ) ;
584
605
Ok ( quote ! {
585
- unsafe impl #impl_generics :: zerogc :: GcErase <' min, #collector_id>
606
+ unsafe impl #impl_generics #zerogc_crate :: GcErase <' min, #collector_id>
586
607
for #name #ty_generics #where_clause {
587
608
// We can pass-through because we are NullTrace
588
609
type Erased = Self ;
589
610
}
590
611
} )
591
612
}
592
613
fn impl_erase ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
614
+ let zerogc_crate = zerogc_crate ( ) ;
593
615
let name = & target. ident ;
594
616
let mut generics: Generics = target. generics . clone ( ) ;
595
617
let mut rewritten_params = Vec :: new ( ) ;
@@ -603,10 +625,10 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
603
625
match param {
604
626
GenericParam :: Type ( ref mut type_param) => {
605
627
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>) ) ;
607
629
type_param. bounds . push ( parse_quote ! ( ' min) ) ;
608
630
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 ) ;
610
632
rewritten_restrictions. push ( WherePredicate :: Type ( PredicateType {
611
633
lifetimes : None ,
612
634
bounded_ty : rewritten_type. clone ( ) ,
@@ -654,17 +676,17 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
654
676
let mut impl_generics = generics. clone ( ) ;
655
677
impl_generics. params . push ( GenericParam :: Lifetime ( parse_quote ! ( ' min) ) ) ;
656
678
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 ) ) ) ;
658
680
}
659
681
impl_generics. make_where_clause ( ) . predicates . extend ( rewritten_restrictions) ;
660
682
let ( _, ty_generics, _) = generics. split_for_impl ( ) ;
661
683
let ( impl_generics, _, where_clause) = impl_generics. split_for_impl ( ) ;
662
684
let assert_erase = field_types. iter ( ) . map ( |field_type| {
663
685
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( ) ; )
665
687
} ) . collect :: < Vec < _ > > ( ) ;
666
688
Ok ( quote ! {
667
- unsafe impl #impl_generics :: zerogc :: GcErase <' min, #collector_id>
689
+ unsafe impl #impl_generics #zerogc_crate :: GcErase <' min, #collector_id>
668
690
for #name #ty_generics #where_clause {
669
691
type Erased = #name:: <#( #rewritten_params) , * >;
670
692
@@ -677,13 +699,14 @@ fn impl_erase(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
677
699
678
700
679
701
fn impl_rebrand_nop ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
702
+ let zerogc_crate = zerogc_crate ( ) ;
680
703
let name = & target. ident ;
681
704
let mut generics: Generics = target. generics . clone ( ) ;
682
705
for param in & mut generics. params {
683
706
match param {
684
707
GenericParam :: Type ( ref mut type_param) => {
685
708
// Require all params are NullTrace
686
- type_param. bounds . push ( parse_quote ! ( :: zerogc :: NullTrace ) ) ;
709
+ type_param. bounds . push ( parse_quote ! ( #zerogc_crate :: NullTrace ) ) ;
687
710
} ,
688
711
GenericParam :: Lifetime ( ref mut l) => {
689
712
if l. lifetime == info. config . gc_lifetime ( ) {
@@ -710,28 +733,29 @@ fn impl_rebrand_nop(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStre
710
733
let collector_id = match info. config . collector_id {
711
734
Some ( ref id) => id. clone ( ) ,
712
735
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 ) ) ) ;
714
737
parse_quote ! ( Id )
715
738
}
716
739
} ;
717
740
// Require that `Self: NullTrace`
718
741
impl_generics. make_where_clause ( ) . predicates . push ( WherePredicate :: Type ( PredicateType {
719
742
lifetimes : None ,
720
743
bounded_ty : parse_quote ! ( Self ) ,
721
- bounds : parse_quote ! ( :: zerogc :: NullTrace ) ,
744
+ bounds : parse_quote ! ( #zerogc_crate :: NullTrace ) ,
722
745
colon_token : Default :: default ( )
723
746
} ) ) ;
724
747
let ( _, ty_generics, _) = generics. split_for_impl ( ) ;
725
748
let ( impl_generics, _, where_clause) = impl_generics. split_for_impl ( ) ;
726
749
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>
728
751
for #name #ty_generics #where_clause {
729
752
// We can pass-through because we are NullTrace
730
753
type Branded = Self ;
731
754
}
732
755
} )
733
756
}
734
757
fn impl_rebrand ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
758
+ let zerogc_crate = zerogc_crate ( ) ;
735
759
let name = & target. ident ;
736
760
let mut generics: Generics = target. generics . clone ( ) ;
737
761
let mut rewritten_params = Vec :: new ( ) ;
@@ -745,9 +769,9 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
745
769
match param {
746
770
GenericParam :: Type ( ref mut type_param) => {
747
771
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>) ) ;
749
773
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 ) ;
751
775
rewritten_restrictions. push ( WherePredicate :: Type ( PredicateType {
752
776
lifetimes : None ,
753
777
bounded_ty : rewritten_type. clone ( ) ,
@@ -795,17 +819,17 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
795
819
let mut impl_generics = generics. clone ( ) ;
796
820
impl_generics. params . push ( GenericParam :: Lifetime ( parse_quote ! ( ' new_gc) ) ) ;
797
821
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 ) ) ) ;
799
823
}
800
824
let assert_rebrand = field_types. iter ( ) . map ( |field_type| {
801
825
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( ) ; )
803
827
} ) . collect :: < Vec < _ > > ( ) ;
804
828
impl_generics. make_where_clause ( ) . predicates . extend ( rewritten_restrictions) ;
805
829
let ( _, ty_generics, _) = generics. split_for_impl ( ) ;
806
830
let ( impl_generics, _, where_clause) = impl_generics. split_for_impl ( ) ;
807
831
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>
809
833
for #name #ty_generics #where_clause {
810
834
type Branded = #name:: <#( #rewritten_params) , * >;
811
835
@@ -816,6 +840,7 @@ fn impl_rebrand(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
816
840
} )
817
841
}
818
842
fn impl_trace ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
843
+ let zerogc_crate = zerogc_crate ( ) ;
819
844
let name = & target. ident ;
820
845
let generics = add_trait_bounds_except (
821
846
& target. generics , parse_quote ! ( zerogc:: Trace ) ,
@@ -884,26 +909,27 @@ fn impl_trace(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream, Er
884
909
} ,
885
910
}
886
911
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 ) * ;
889
914
890
915
/*
891
916
* The inline annotation adds this function's MIR to the metadata.
892
917
* Without it cross-crate inlining is impossible (without LTO).
893
918
*/
894
919
#[ 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 > {
896
921
#trace_impl
897
922
Ok ( ( ) )
898
923
}
899
924
}
900
925
} )
901
926
}
902
927
fn impl_gc_safe ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
928
+ let zerogc_crate = zerogc_crate ( ) ;
903
929
let name = & target. ident ;
904
930
let collector_id = & info. config . collector_id ;
905
931
let generics = add_trait_bounds_except (
906
- & target. generics , parse_quote ! ( zerogc :: GcSafe ) ,
932
+ & target. generics , parse_quote ! ( #zerogc_crate :: GcSafe ) ,
907
933
& info. config . ignore_params ,
908
934
Some ( & mut |other : & Ident | {
909
935
if let Some ( ref collector_id) = * collector_id {
@@ -936,7 +962,7 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
936
962
quote ! ( false )
937
963
} else {
938
964
// 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 ) * )
940
966
} ;
941
967
let fake_drop_impl = if info. config . is_copy {
942
968
/*
@@ -959,12 +985,12 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
959
985
} )
960
986
} ;
961
987
let verify_gc_safe = if info. config . is_copy {
962
- quote ! ( :: zerogc :: assert_copy:: <Self >( ) )
988
+ quote ! ( #zerogc_crate :: assert_copy:: <Self >( ) )
963
989
} else {
964
- quote ! ( #( <#field_types as GcSafe >:: assert_gc_safe( ) ; ) * )
990
+ quote ! ( #( <#field_types as #zerogc_crate :: GcSafe >:: assert_gc_safe( ) ; ) * )
965
991
} ;
966
992
Ok ( quote ! {
967
- unsafe impl #impl_generics :: zerogc :: GcSafe
993
+ unsafe impl #impl_generics #zerogc_crate :: GcSafe
968
994
for #name #ty_generics #where_clause {
969
995
const NEEDS_DROP : bool = #does_need_drop;
970
996
@@ -978,9 +1004,10 @@ fn impl_gc_safe(target: &DeriveInput, info: &GcTypeInfo) -> Result<TokenStream,
978
1004
979
1005
980
1006
fn impl_nop_trace ( target : & DeriveInput , info : & GcTypeInfo ) -> Result < TokenStream , Error > {
1007
+ let zerogc_crate = zerogc_crate ( ) ;
981
1008
let name = & target. ident ;
982
1009
let generics = add_trait_bounds_except (
983
- & target. generics , parse_quote ! ( zerogc :: Trace ) ,
1010
+ & target. generics , parse_quote ! ( #zerogc_crate :: Trace ) ,
984
1011
& info. config . ignore_params , None
985
1012
) ?;
986
1013
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
1007
1034
let ty_span = t. span ( ) ;
1008
1035
quote_spanned ! { ty_span =>
1009
1036
assert!(
1010
- !<#t as Trace >:: NEEDS_TRACE ,
1037
+ !<#t as #zerogc_crate :: Trace >:: NEEDS_TRACE ,
1011
1038
"Can't #[derive(NullTrace) with {}" ,
1012
1039
stringify!( #t)
1013
1040
) ;
1014
1041
}
1015
1042
} ) . collect :: < Vec < _ > > ( ) ;
1016
1043
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 {
1018
1045
const NEEDS_TRACE : bool = false ;
1019
1046
1020
1047
#[ 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 > {
1022
1049
#( #trace_assertions) *
1023
1050
Ok ( ( ) )
1024
1051
}
1025
1052
}
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 {
1027
1054
#[ 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 > {
1029
1056
#( #trace_assertions) *
1030
1057
Ok ( ( ) )
1031
1058
}
1032
1059
}
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 { }
1034
1061
} )
1035
1062
}
1036
1063
0 commit comments