1
1
use super :: * ;
2
2
3
3
/// Memoize a function.
4
- pub fn expand ( item : & syn:: ItemFn ) -> Result < proc_macro2:: TokenStream > {
4
+ pub fn expand ( item : & syn:: Item ) -> Result < proc_macro2:: TokenStream > {
5
+ let item = match item {
6
+ syn:: Item :: Fn ( item) => item,
7
+ _ => bail ! (
8
+ item,
9
+ "`memoize` can only be applied to functions and methods"
10
+ ) ,
11
+ } ;
12
+
5
13
// Preprocess and validate the function.
6
14
let function = prepare ( & item) ?;
7
15
@@ -37,43 +45,7 @@ fn prepare(function: &syn::ItemFn) -> Result<Function> {
37
45
let mut args = vec ! [ ] ;
38
46
39
47
for input in & function. sig . inputs {
40
- match input {
41
- syn:: FnArg :: Receiver ( recv) => {
42
- if recv. mutability . is_some ( ) {
43
- bail ! ( recv, "memoized functions cannot have mutable parameters" ) ;
44
- }
45
-
46
- args. push ( Argument :: Receiver ( recv. self_token ) ) ;
47
- }
48
- syn:: FnArg :: Typed ( typed) => {
49
- let name = match typed. pat . as_ref ( ) {
50
- syn:: Pat :: Ident ( syn:: PatIdent {
51
- by_ref : None ,
52
- mutability : None ,
53
- ident,
54
- subpat : None ,
55
- ..
56
- } ) => ident. clone ( ) ,
57
- pat => bail ! ( pat, "only simple identifiers are supported" ) ,
58
- } ;
59
-
60
- let ty = typed. ty . as_ref ( ) . clone ( ) ;
61
- match ty {
62
- syn:: Type :: Reference ( syn:: TypeReference {
63
- mutability : Some ( _) ,
64
- ..
65
- } ) => {
66
- bail ! (
67
- typed. ty,
68
- "memoized functions cannot have mutable parameters"
69
- )
70
- }
71
- _ => { }
72
- }
73
-
74
- args. push ( Argument :: Ident ( name) ) ;
75
- }
76
- }
48
+ args. push ( prepare_arg ( input) ?) ;
77
49
}
78
50
79
51
let output = match & function. sig . output {
@@ -91,6 +63,46 @@ fn prepare(function: &syn::ItemFn) -> Result<Function> {
91
63
} )
92
64
}
93
65
66
+ /// Preprocess a function argument.
67
+ fn prepare_arg ( input : & syn:: FnArg ) -> Result < Argument > {
68
+ Ok ( match input {
69
+ syn:: FnArg :: Receiver ( recv) => {
70
+ if recv. mutability . is_some ( ) {
71
+ bail ! ( recv, "memoized functions cannot have mutable parameters" ) ;
72
+ }
73
+
74
+ Argument :: Receiver ( recv. self_token )
75
+ }
76
+ syn:: FnArg :: Typed ( typed) => {
77
+ let name = match typed. pat . as_ref ( ) {
78
+ syn:: Pat :: Ident ( syn:: PatIdent {
79
+ by_ref : None ,
80
+ mutability : None ,
81
+ ident,
82
+ subpat : None ,
83
+ ..
84
+ } ) => ident. clone ( ) ,
85
+ pat => bail ! ( pat, "only simple identifiers are supported" ) ,
86
+ } ;
87
+
88
+ let ty = typed. ty . as_ref ( ) . clone ( ) ;
89
+ match ty {
90
+ syn:: Type :: Reference ( syn:: TypeReference {
91
+ mutability : Some ( _) , ..
92
+ } ) => {
93
+ bail ! (
94
+ typed. ty,
95
+ "memoized functions cannot have mutable parameters"
96
+ )
97
+ }
98
+ _ => { }
99
+ }
100
+
101
+ Argument :: Ident ( name)
102
+ }
103
+ } )
104
+ }
105
+
94
106
/// Rewrite a function's body to memoize it.
95
107
fn process ( function : & Function ) -> Result < TokenStream > {
96
108
// Construct assertions that the arguments fulfill the necessary bounds.
@@ -124,12 +136,14 @@ fn process(function: &Function) -> Result<TokenStream> {
124
136
// Adjust the function's body.
125
137
let mut wrapped = function. item . clone ( ) ;
126
138
let name = function. name . to_string ( ) ;
139
+ let unique = quote ! { __ComemoUnique } ;
140
+
127
141
wrapped. block = parse_quote ! { {
128
- struct __ComemoUnique ;
142
+ struct #unique ;
129
143
#( #bounds; ) *
130
144
:: comemo:: internal:: memoized(
131
145
#name,
132
- :: core:: any:: TypeId :: of:: <__ComemoUnique >( ) ,
146
+ :: core:: any:: TypeId :: of:: <#unique >( ) ,
133
147
:: comemo:: internal:: Args ( #arg_tuple) ,
134
148
#closure,
135
149
)
0 commit comments