1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#![feature(external_doc)]
#![doc(include = "../README.md")]
extern crate proc_macro;
use syn;
use proc_macro::TokenStream;
use quote::quote;
#[proc_macro_attribute]
pub fn loose(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as syn::ItemFn);
let replica = quote! {
#input
};
let vis = &input.vis;
let constness = &input.constness;
let unsafety = &input.unsafety;
let ident = &input.ident;
let decl = &input.decl;
let _block = &input.block;
let generics = &decl.generics;
let inputs = &decl.inputs;
let output = &decl.output;
let ident_loose = format!("{}_loose", ident);
let ident_loose = syn::Ident::new(&ident_loose, ident.span());
let (pats, types): (Vec<_>, Vec<_>) = inputs
.iter()
.map(|fn_arg| {
match fn_arg {
syn::FnArg::SelfRef(_self_ref) => {
panic!("TODO FnArg::SelfRef");
}
syn::FnArg::SelfValue(_self_value) => {
panic!("TODO FnArg::SelfValue");
}
syn::FnArg::Captured(captured) => {
(&captured.pat, &captured.ty)
}
syn::FnArg::Inferred(_pat) => {
panic!("TODO FnArg::Inferred");
}
syn::FnArg::Ignored(_ty) => {
panic!("TODO FnArg::Ignored");
}
}
})
.unzip();
let args_into_tuple = {
let pats = pats.clone();
let types = types.clone();
quote! {
(#(#pats,)*): (#(#types,)*)
}
};
let loosened = quote! {
#[inline]
#vis #constness #unsafety fn #ident_loose #generics ( #args_into_tuple ) #output {
#ident(#(#pats),*)
}
};
let tokens = quote! {
#replica
#loosened
};
tokens.into()
}