hax_lib_macros/
dummy.rs

1mod hax_paths;
2
3use hax_paths::*;
4use proc_macro::{TokenStream, TokenTree};
5use quote::quote;
6use syn::{visit_mut::VisitMut, *};
7
8macro_rules! identity_proc_macro_attribute {
9    ($($name:ident),*$(,)?) => {
10        $(
11            #[proc_macro_attribute]
12            pub fn $name(_attr: TokenStream, item: TokenStream) -> TokenStream {
13                item
14            }
15        )*
16    }
17}
18
19identity_proc_macro_attribute!(
20    fstar_options,
21    fstar_verification_status,
22    include,
23    exclude,
24    requires,
25    ensures,
26    decreases,
27    pv_handwritten,
28    pv_constructor,
29    protocol_messages,
30    process_init,
31    process_write,
32    process_read,
33    opaque,
34    opaque_type,
35    transparent,
36    refinement_type,
37    fstar_replace,
38    coq_replace,
39    lean_replace,
40    proverif_replace,
41    fstar_replace_body,
42    coq_replace_body,
43    lean_replace_body,
44    proverif_replace_body,
45    fstar_before,
46    coq_before,
47    lean_before,
48    proverif_before,
49    fstar_after,
50    coq_after,
51    lean_after,
52    proverif_after,
53    fstar_smt_pat,
54    fstar_postprocess_with,
55    lean_proof,
56);
57
58#[proc_macro]
59pub fn fstar_expr(_payload: TokenStream) -> TokenStream {
60    quote! { () }.into()
61}
62#[proc_macro]
63pub fn coq_expr(_payload: TokenStream) -> TokenStream {
64    quote! { () }.into()
65}
66#[proc_macro]
67pub fn lean_expr(_payload: TokenStream) -> TokenStream {
68    quote! { () }.into()
69}
70#[proc_macro]
71pub fn proverif_expr(_payload: TokenStream) -> TokenStream {
72    quote! { () }.into()
73}
74
75#[proc_macro_attribute]
76pub fn lemma(_attr: TokenStream, _item: TokenStream) -> TokenStream {
77    quote! {}.into()
78}
79
80fn unsafe_expr() -> TokenStream {
81    // `*_unsafe_expr("<code>")` are macro generating a Rust expression of any type, that will be replaced by `<code>` in the backends.
82    // This should be used solely in hax-only contextes.
83    // If this macro is used, that means the user broke this rule.
84    quote! { ::std::compile_error!("`hax_lib::unsafe_expr` has no meaning outside of hax extraction, please use it solely on hax-only places.") }.into()
85}
86
87#[proc_macro]
88pub fn fstar_unsafe_expr(_payload: TokenStream) -> TokenStream {
89    unsafe_expr()
90}
91#[proc_macro]
92pub fn coq_unsafe_expr(_payload: TokenStream) -> TokenStream {
93    unsafe_expr()
94}
95#[proc_macro]
96pub fn lean_unsafe_expr(_payload: TokenStream) -> TokenStream {
97    unsafe_expr()
98}
99#[proc_macro]
100pub fn proverif_unsafe_expr(_payload: TokenStream) -> TokenStream {
101    unsafe_expr()
102}
103
104#[proc_macro]
105pub fn fstar_prop_expr(_payload: TokenStream) -> TokenStream {
106    quote! {::hax_lib::Prop::from_bool(true)}.into()
107}
108#[proc_macro]
109pub fn coq_prop_expr(_payload: TokenStream) -> TokenStream {
110    quote! {::hax_lib::Prop::from_bool(true)}.into()
111}
112#[proc_macro]
113pub fn lean_prop_expr(_payload: TokenStream) -> TokenStream {
114    quote! {::hax_lib::Prop::from_bool(true)}.into()
115}
116#[proc_macro]
117pub fn proverif_prop_expr(_payload: TokenStream) -> TokenStream {
118    quote! {::hax_lib::Prop::from_bool(true)}.into()
119}
120
121fn not_hax_attribute(attr: &syn::Attribute) -> bool {
122    if let Meta::List(ml) = &attr.meta {
123        !matches!(expects_path_decoration(&ml.path), Ok(Some(_)))
124    } else {
125        true
126    }
127}
128
129fn not_field_attribute(attr: &syn::Attribute) -> bool {
130    if let Meta::List(ml) = &attr.meta {
131        !(matches!(expects_refine(&ml.path), Ok(Some(_)))
132            || matches!(expects_order(&ml.path), Ok(Some(_))))
133    } else {
134        true
135    }
136}
137
138#[proc_macro_attribute]
139pub fn attributes(_attr: TokenStream, item: TokenStream) -> TokenStream {
140    let item: Item = parse_macro_input!(item);
141
142    struct AttrVisitor;
143
144    use syn::visit_mut;
145    impl VisitMut for AttrVisitor {
146        fn visit_item_trait_mut(&mut self, item: &mut ItemTrait) {
147            for ti in item.items.iter_mut() {
148                if let TraitItem::Fn(fun) = ti {
149                    fun.attrs.retain(not_hax_attribute)
150                }
151            }
152            visit_mut::visit_item_trait_mut(self, item);
153        }
154        fn visit_type_mut(&mut self, _type: &mut Type) {}
155        fn visit_item_impl_mut(&mut self, item: &mut ItemImpl) {
156            for ii in item.items.iter_mut() {
157                if let ImplItem::Fn(fun) = ii {
158                    fun.attrs.retain(not_hax_attribute)
159                }
160            }
161            visit_mut::visit_item_impl_mut(self, item);
162        }
163        fn visit_item_mut(&mut self, item: &mut Item) {
164            visit_mut::visit_item_mut(self, item);
165
166            match item {
167                Item::Struct(s) => {
168                    for field in s.fields.iter_mut() {
169                        field.attrs.retain(not_field_attribute)
170                    }
171                }
172                _ => (),
173            }
174        }
175    }
176
177    let mut item = item;
178    AttrVisitor.visit_item_mut(&mut item);
179
180    quote! { #item }.into()
181}
182
183#[proc_macro]
184pub fn int(payload: TokenStream) -> TokenStream {
185    let mut tokens = payload.into_iter().peekable();
186    let negative = matches!(tokens.peek(), Some(TokenTree::Punct(p)) if p.as_char() == '-');
187    if negative {
188        tokens.next();
189    }
190    let [lit @ TokenTree::Literal(_)] = &tokens.collect::<Vec<_>>()[..] else {
191        return quote! { ::std::compile_error!("Expected exactly one numeric literal") }.into();
192    };
193    let lit: proc_macro2::TokenStream = TokenStream::from(lit.clone()).into();
194    quote! {::hax_lib::int::Int(#lit)}.into()
195}
196
197#[proc_macro_attribute]
198pub fn impl_fn_decoration(_attr: TokenStream, _item: TokenStream) -> TokenStream {
199    quote! { ::std::compile_error!("`impl_fn_decoration` is an internal macro and should never be used directly.") }.into()
200}
201
202#[proc_macro_attribute]
203pub fn trait_fn_decoration(_attr: TokenStream, _item: TokenStream) -> TokenStream {
204    quote! { ::std::compile_error!("`trait_fn_decoration` is an internal macro and should never be used directly.") }.into()
205}
206
207#[proc_macro]
208pub fn loop_invariant(_predicate: TokenStream) -> TokenStream {
209    quote! {}.into()
210}
211
212#[proc_macro]
213pub fn loop_decreases(_predicate: TokenStream) -> TokenStream {
214    quote! {}.into()
215}