jrsonnet_gc_derive/
lib.rs1use quote::quote;
2use synstructure::{decl_derive, AddBounds, BindStyle, Structure};
3
4decl_derive!([Trace, attributes(unsafe_ignore_trace, trivially_drop)] => derive_trace);
5
6fn derive_trace(mut s: Structure<'_>) -> proc_macro2::TokenStream {
7 let is_trivially_drop = s
8 .ast()
9 .attrs
10 .iter()
11 .any(|attr| attr.path.is_ident("trivially_drop"));
12 s.filter(|bi| {
13 !bi.ast()
14 .attrs
15 .iter()
16 .any(|attr| attr.path.is_ident("unsafe_ignore_trace"))
17 });
18 let trace_body = s.each(|bi| quote!(mark(#bi)));
19
20 s.add_bounds(AddBounds::Fields);
21 let trace_impl = s.unsafe_bound_impl(
22 quote!(::jrsonnet_gc::Trace),
23 quote! {
24 #[inline] unsafe fn trace(&self) {
25 #[allow(dead_code)]
26 #[inline]
27 unsafe fn mark<T: ::jrsonnet_gc::Trace + ?Sized>(it: &T) {
28 ::jrsonnet_gc::Trace::trace(it);
29 }
30 match *self { #trace_body }
31 }
32 #[inline] unsafe fn root(&self) {
33 #[allow(dead_code)]
34 #[inline]
35 unsafe fn mark<T: ::jrsonnet_gc::Trace + ?Sized>(it: &T) {
36 ::jrsonnet_gc::Trace::root(it);
37 }
38 match *self { #trace_body }
39 }
40 #[inline] unsafe fn unroot(&self) {
41 #[allow(dead_code)]
42 #[inline]
43 unsafe fn mark<T: ::jrsonnet_gc::Trace + ?Sized>(it: &T) {
44 ::jrsonnet_gc::Trace::unroot(it);
45 }
46 match *self { #trace_body }
47 }
48 #[inline] fn finalize_glue(&self) {
49 ::jrsonnet_gc::Finalize::finalize(self);
50 #[allow(dead_code)]
51 #[inline]
52 fn mark<T: ::jrsonnet_gc::Trace + ?Sized>(it: &T) {
53 ::jrsonnet_gc::Trace::finalize_glue(it);
54 }
55 match *self { #trace_body }
56 }
57 },
58 );
59
60 if !is_trivially_drop {
61 let drop_impl = s.unbound_impl(
65 quote!(::std::ops::Drop),
66 quote! {
67 fn drop(&mut self) {
68 if ::jrsonnet_gc::finalizer_safe() {
69 ::jrsonnet_gc::Finalize::finalize(self);
70 }
71 }
72 },
73 );
74
75 quote! {
76 #trace_impl
77 #drop_impl
78 }
79 } else {
80 s.bind_with(|_| BindStyle::Move);
81 let trivially_drop_body = s.each(|_| quote! {});
82 let finalize_impl = s.bound_impl(
83 quote!(::jrsonnet_gc::Finalize),
84 quote!(
85 fn finalize(&self) {
86 let _trivially_drop = |t: Self| match t { #trivially_drop_body };
87 }
88 ),
89 );
90
91 quote! {
92 #trace_impl
93 #finalize_impl
94 }
95 }
96}
97
98decl_derive!([Finalize] => derive_finalize);
99
100fn derive_finalize(s: Structure<'_>) -> proc_macro2::TokenStream {
101 s.unbound_impl(quote!(::jrsonnet_gc::Finalize), quote!())
102}