@@ -345,29 +345,53 @@ fn derive_hashed_label(
345
345
path
346
346
} ;
347
347
348
- let boxed_ty = quote ! { :: std:: boxed:: Box :: <dyn #downcast_debug_path + :: std:: marker:: Send + :: std:: marker:: Sync > } ;
348
+ // If the type is generic, we need to box it before interning it.
349
+ // Since Rust does not currently allow us to have generic types with associated statics,
350
+ // all of the labels for any generic type must be interned in the same global.
351
+ let is_generic = !input. generics . params . is_empty ( ) ;
352
+
353
+ let interner_generics = if !is_generic {
354
+ quote ! { <u64 , #ident> }
355
+ } else {
356
+ let boxed_ty = quote ! { :: std:: boxed:: Box :: <dyn #downcast_debug_path + :: std:: marker:: Send + :: std:: marker:: Sync > } ;
357
+ quote ! { <( u64 , :: std:: any:: TypeId ) , #boxed_ty> }
358
+ } ;
359
+
360
+ let mut clone_expr = quote ! { :: std:: clone:: Clone :: clone( self ) } ;
361
+ if is_generic {
362
+ clone_expr = quote ! { :: std:: boxed:: Box :: new( #clone_expr) } ;
363
+ }
364
+
365
+ let key_expr = if !is_generic {
366
+ quote ! { hash }
367
+ } else {
368
+ quote ! { ( hash, :: std:: any:: TypeId :: of:: <Self >( ) ) }
369
+ } ;
370
+
371
+ let mut get_expr = quote ! { #interner_ident . get( #key_expr) } ;
372
+ if is_generic {
373
+ let try_map = quote ! { <#guard_type_path<_>>:: try_map } ;
374
+ let downcast = quote ! { <dyn #downcast_debug_path>:: downcast_ref } ;
375
+ get_expr = quote ! {
376
+ #try_map( #get_expr?, |val| #downcast:: <Self >( & * * val) ) . ok( )
377
+ } ;
378
+ }
349
379
350
380
quote ! {
351
- // NOTE: We need to box the interned objects in order to deal with generics.
352
- // Unfortunately, we cannot associate data with generic impls, so they all must be
353
- // stored together.
354
- // FIXME: Make this concrete for types without generics.
355
381
static #interner_ident
356
- : #interner_type_path < ( u64 , :: std :: any :: TypeId ) , #boxed_ty>
382
+ : #interner_type_path #interner_generics
357
383
= #interner_type_path:: new( ) ;
358
384
359
385
impl #impl_generics #trait_path for #ident #ty_generics #where_clause {
360
386
#[ inline]
361
387
fn data( & self ) -> u64 {
362
388
let hash = #compute_hash_path( self ) ;
363
- let key = ( hash, :: std:: any:: TypeId :: of:: <Self >( ) ) ;
364
- #interner_ident . intern( key, || :: std:: boxed:: Box :: new( :: std:: clone:: Clone :: clone( self ) ) ) ;
389
+ #interner_ident . intern( #key_expr, || #clone_expr) ;
365
390
hash
366
391
}
367
392
fn fmt( hash: u64 , f: & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
368
- let key = ( hash, :: std:: any:: TypeId :: of:: <Self >( ) ) ;
369
393
#interner_ident
370
- . scope( key , |val| :: std:: fmt:: Debug :: fmt( val, f) )
394
+ . scope( #key_expr , |val| :: std:: fmt:: Debug :: fmt( val, f) )
371
395
. ok_or( :: std:: fmt:: Error ) ?
372
396
}
373
397
}
@@ -376,11 +400,7 @@ fn derive_hashed_label(
376
400
type Output = #guard_type_path <' static , Self >;
377
401
fn downcast_from( label: #id_path) -> Option <Self :: Output > {
378
402
let hash = <#id_path as #trait_path>:: data( & label) ;
379
- let key = ( hash, :: std:: any:: TypeId :: of:: <Self >( ) ) ;
380
- <#guard_type_path<_>>:: try_map(
381
- #interner_ident . get( key) ?,
382
- |val| <dyn #downcast_debug_path>:: downcast_ref:: <Self >( & * * val) ,
383
- ) . ok( )
403
+ #get_expr
384
404
}
385
405
}
386
406
}
0 commit comments