@@ -5,18 +5,26 @@ pub fn expand(item: &syn::Item) -> Result<TokenStream> {
5
5
// Preprocess and validate the methods.
6
6
let mut methods = vec ! [ ] ;
7
7
8
- let ( ty, trait_) = match item {
8
+ let ( ty, generics , trait_) = match item {
9
9
syn:: Item :: Impl ( item) => {
10
10
for param in item. generics . params . iter ( ) {
11
- bail ! ( param, "tracked impl blocks cannot be generic" )
11
+ match param {
12
+ syn:: GenericParam :: Lifetime ( _) => { }
13
+ syn:: GenericParam :: Type ( _) => {
14
+ bail ! ( param, "tracked impl blocks cannot use type generics" )
15
+ }
16
+ syn:: GenericParam :: Const ( _) => {
17
+ bail ! ( param, "tracked impl blocks cannot use const generics" )
18
+ }
19
+ }
12
20
}
13
21
14
22
for item in & item. items {
15
23
methods. push ( prepare_impl_method ( & item) ?) ;
16
24
}
17
25
18
26
let ty = item. self_ty . as_ref ( ) . clone ( ) ;
19
- ( ty, None )
27
+ ( ty, & item . generics , None )
20
28
}
21
29
syn:: Item :: Trait ( item) => {
22
30
for param in item. generics . params . iter ( ) {
@@ -28,17 +36,14 @@ pub fn expand(item: &syn::Item) -> Result<TokenStream> {
28
36
}
29
37
30
38
let name = & item. ident ;
31
- let ty = parse_quote ! { dyn #name } ;
32
- ( ty, Some ( name. clone ( ) ) )
39
+ let ty = parse_quote ! { dyn #name + ' __comemo_dynamic } ;
40
+ ( ty, & item . generics , Some ( name. clone ( ) ) )
33
41
}
34
- _ => bail ! (
35
- item,
36
- "`track` can only be applied to impl blocks and traits"
37
- ) ,
42
+ _ => bail ! ( item, "`track` can only be applied to impl blocks and traits" ) ,
38
43
} ;
39
44
40
45
// Produce the necessary items for the type to become trackable.
41
- let scope = create ( & ty, trait_, & methods) ?;
46
+ let scope = create ( & ty, generics , trait_, & methods) ?;
42
47
43
48
Ok ( quote ! {
44
49
#item
@@ -172,104 +177,152 @@ fn prepare_method(vis: syn::Visibility, sig: &syn::Signature) -> Result<Method>
172
177
/// Produce the necessary items for a type to become trackable.
173
178
fn create (
174
179
ty : & syn:: Type ,
180
+ generics : & syn:: Generics ,
175
181
trait_ : Option < syn:: Ident > ,
176
182
methods : & [ Method ] ,
177
183
) -> Result < TokenStream > {
178
- let prefix = trait_. map ( |name| quote ! { #name for } ) ;
179
- let variants = methods. iter ( ) . map ( create_variant) ;
180
- let validations = methods. iter ( ) . map ( create_validation) ;
184
+ let t: syn:: GenericParam = parse_quote ! { ' __comemo_tracked } ;
185
+ let r: syn:: GenericParam = parse_quote ! { ' __comemo_retrack } ;
186
+ let d: syn:: GenericParam = parse_quote ! { ' __comemo_dynamic } ;
187
+ let maybe_cloned = if methods. iter ( ) . any ( |it| it. mutable ) {
188
+ quote ! { :: core:: clone:: Clone :: clone( self ) }
189
+ } else {
190
+ quote ! { self }
191
+ } ;
192
+
193
+ // Prepare generics.
194
+ let ( impl_gen, type_gen, where_clause) = generics. split_for_impl ( ) ;
195
+ let mut impl_params: syn:: Generics = parse_quote ! { #impl_gen } ;
196
+ let mut type_params: syn:: Generics = parse_quote ! { #type_gen } ;
197
+ if trait_. is_some ( ) {
198
+ impl_params. params . push ( d. clone ( ) ) ;
199
+ type_params. params . push ( d. clone ( ) ) ;
200
+ }
201
+
202
+ let mut impl_params_t: syn:: Generics = impl_params. clone ( ) ;
203
+ let mut type_params_t: syn:: Generics = type_params. clone ( ) ;
204
+ impl_params_t. params . push ( t. clone ( ) ) ;
205
+ type_params_t. params . push ( t. clone ( ) ) ;
206
+
207
+ // Prepare validations.
208
+ let prefix = trait_. as_ref ( ) . map ( |name| quote ! { #name for } ) ;
209
+ let validations: Vec < _ > = methods. iter ( ) . map ( create_validation) . collect ( ) ;
210
+ let validate = if !methods. is_empty ( ) {
211
+ quote ! {
212
+ let mut this = #maybe_cloned;
213
+ constraint. validate( |call| match & call. 0 { #( #validations, ) * } )
214
+ }
215
+ } else {
216
+ quote ! { true }
217
+ } ;
218
+ let validate_with_id = if !methods. is_empty ( ) {
219
+ quote ! {
220
+ let mut this = #maybe_cloned;
221
+ constraint. validate_with_id(
222
+ |call| match & call. 0 { #( #validations, ) * } ,
223
+ id,
224
+ )
225
+ }
226
+ } else {
227
+ quote ! { true }
228
+ } ;
229
+
230
+ // Prepare replying.
181
231
let replays = methods. iter ( ) . map ( create_replay) ;
232
+ let replay = methods. iter ( ) . any ( |m| m. mutable ) . then ( || {
233
+ quote ! {
234
+ constraint. replay( |call| match & call. 0 { #( #replays, ) * } ) ;
235
+ }
236
+ } ) ;
237
+
238
+ // Prepare variants and wrapper methods.
239
+ let variants = methods. iter ( ) . map ( create_variant) ;
182
240
let wrapper_methods = methods
183
241
. iter ( )
184
242
. filter ( |m| !m. mutable )
185
243
. map ( |m| create_wrapper ( m, false ) ) ;
186
244
let wrapper_methods_mut = methods. iter ( ) . map ( |m| create_wrapper ( m, true ) ) ;
187
- let maybe_cloned = if methods. iter ( ) . any ( |it| it. mutable ) {
188
- quote ! { :: std:: clone:: Clone :: clone( self ) }
189
- } else {
190
- quote ! { self }
191
- } ;
192
245
193
246
Ok ( quote ! {
194
- #[ derive( Clone , PartialEq ) ]
195
- pub struct __ComemoCall( __ComemoVariant) ;
247
+ impl #impl_params :: comemo:: Track for #ty #where_clause { }
196
248
197
- #[ derive( Clone , PartialEq ) ]
198
- #[ allow( non_camel_case_types) ]
199
- enum __ComemoVariant {
200
- #( #variants, ) *
201
- }
249
+ impl #impl_params :: comemo:: Validate for #ty #where_clause {
250
+ type Constraint = :: comemo:: internal:: Constraint <__ComemoCall>;
202
251
203
- impl :: comemo:: Track for #ty {
204
252
#[ inline]
205
- fn valid( & self , constraint: & :: comemo:: Constraint <Self >) -> bool {
206
- let mut this = #maybe_cloned;
207
- constraint. valid( |call| match & call. 0 { #( #validations, ) * } )
253
+ fn validate( & self , constraint: & Self :: Constraint ) -> bool {
254
+ #validate
208
255
}
209
- }
210
256
211
- #[ doc( hidden) ]
212
- impl :: comemo:: internal:: Trackable for #ty {
213
- type Call = __ComemoCall;
214
- type Surface = __ComemoSurfaceFamily;
215
- type SurfaceMut = __ComemoSurfaceMutFamily;
257
+ #[ inline]
258
+ fn validate_with_id( & self , constraint: & Self :: Constraint , id: usize ) -> bool {
259
+ #validate_with_id
260
+ }
216
261
217
262
#[ inline]
218
263
#[ allow( unused_variables) ]
219
- fn replay( & mut self , constraint: & :: comemo :: Constraint < Self > ) {
220
- constraint . replay ( |call| match & call . 0 { # ( #replays , ) * } ) ;
264
+ fn replay( & mut self , constraint: & Self :: Constraint ) {
265
+ #replay
221
266
}
267
+ }
268
+
269
+ #[ derive( Clone , PartialEq , Hash ) ]
270
+ pub struct __ComemoCall( __ComemoVariant) ;
271
+
272
+ #[ derive( Clone , PartialEq , Hash ) ]
273
+ #[ allow( non_camel_case_types) ]
274
+ enum __ComemoVariant {
275
+ #( #variants, ) *
276
+ }
277
+
278
+ #[ doc( hidden) ]
279
+ impl #impl_params :: comemo:: internal:: Surfaces for #ty #where_clause {
280
+ type Surface <#t> = __ComemoSurface #type_params_t where Self : #t;
281
+ type SurfaceMut <#t> = __ComemoSurfaceMut #type_params_t where Self : #t;
222
282
223
283
#[ inline]
224
- fn surface_ref<' a , ' r>(
225
- tracked: & ' r :: comemo:: Tracked <' a , Self >,
226
- ) -> & ' r __ComemoSurface< ' a > {
284
+ fn surface_ref<#t , # r>(
285
+ tracked: & # r :: comemo:: Tracked <#t , Self >,
286
+ ) -> & #r Self :: Surface <#t > {
227
287
// Safety: __ComemoSurface is repr(transparent).
228
288
unsafe { & * ( tracked as * const _ as * const _) }
229
289
}
230
290
231
291
#[ inline]
232
- fn surface_mut_ref<' a , ' r>(
233
- tracked: & ' r :: comemo:: TrackedMut <' a , Self >,
234
- ) -> & ' r __ComemoSurfaceMut< ' a > {
292
+ fn surface_mut_ref<#t , # r>(
293
+ tracked: & # r :: comemo:: TrackedMut <#t , Self >,
294
+ ) -> & #r Self :: SurfaceMut <#t > {
235
295
// Safety: __ComemoSurfaceMut is repr(transparent).
236
296
unsafe { & * ( tracked as * const _ as * const _) }
237
297
}
238
298
239
299
#[ inline]
240
- fn surface_mut_mut<' a , ' r>(
241
- tracked: & ' r mut :: comemo:: TrackedMut <' a , Self >,
242
- ) -> & ' r mut __ComemoSurfaceMut< ' a > {
300
+ fn surface_mut_mut<#t , # r>(
301
+ tracked: & # r mut :: comemo:: TrackedMut <#t , Self >,
302
+ ) -> & # r mut Self :: SurfaceMut <#t > {
243
303
// Safety: __ComemoSurfaceMut is repr(transparent).
244
304
unsafe { & mut * ( tracked as * mut _ as * mut _) }
245
305
}
246
306
}
247
307
248
308
#[ repr( transparent) ]
249
- pub struct __ComemoSurface<' a>( :: comemo:: Tracked <' a, #ty>) ;
309
+ pub struct __ComemoSurface #impl_params_t( :: comemo:: Tracked <#t, #ty>)
310
+ #where_clause;
250
311
251
312
#[ allow( dead_code) ]
252
- impl #prefix __ComemoSurface< ' _> {
313
+ impl #impl_params_t # prefix __ComemoSurface #type_params_t {
253
314
#( #wrapper_methods) *
254
315
}
255
316
256
- pub enum __ComemoSurfaceFamily { }
257
- impl <' a> :: comemo:: internal:: Family <' a> for __ComemoSurfaceFamily {
258
- type Out = __ComemoSurface<' a>;
259
- }
260
-
261
317
#[ repr( transparent) ]
262
- pub struct __ComemoSurfaceMut<' a>( :: comemo:: TrackedMut <' a, #ty>) ;
318
+ pub struct __ComemoSurfaceMut #impl_params_t( :: comemo:: TrackedMut <#t, #ty>)
319
+ #where_clause;
263
320
264
321
#[ allow( dead_code) ]
265
- impl #prefix __ComemoSurfaceMut< ' _> {
322
+ impl #impl_params_t # prefix __ComemoSurfaceMut #type_params_t {
266
323
#( #wrapper_methods_mut) *
267
324
}
268
325
269
- pub enum __ComemoSurfaceMutFamily { }
270
- impl <' a> :: comemo:: internal:: Family <' a> for __ComemoSurfaceMutFamily {
271
- type Out = __ComemoSurfaceMut<' a>;
272
- }
273
326
} )
274
327
}
275
328
@@ -328,12 +381,12 @@ fn create_wrapper(method: &Method, tracked_mut: bool) -> TokenStream {
328
381
#[ track_caller]
329
382
#[ inline]
330
383
#vis #sig {
331
- let call = __ComemoVariant:: #name( #( #args. to_owned( ) ) , * ) ;
332
- let ( value , constraint ) = :: comemo:: internal:: #to_parts;
333
- let output = value . #name( #( #args, ) * ) ;
334
- if let Some ( constraint) = constraint {
384
+ let __comemo_variant = __ComemoVariant:: #name( #( #args. to_owned( ) ) , * ) ;
385
+ let ( __comemo_value , __comemo_constraint ) = :: comemo:: internal:: #to_parts;
386
+ let output = __comemo_value . #name( #( #args, ) * ) ;
387
+ if let Some ( constraint) = __comemo_constraint {
335
388
constraint. push(
336
- __ComemoCall( call ) ,
389
+ __ComemoCall( __comemo_variant ) ,
337
390
:: comemo:: internal:: hash( & output) ,
338
391
#mutable,
339
392
) ;
0 commit comments