@@ -2400,6 +2400,16 @@ mod generics_search {
2400
2400
pub ( crate ) consts : HashSet < & ' s syn:: Ident > ,
2401
2401
}
2402
2402
2403
+ impl < ' s > From < & ' s syn:: Generics > for GenericsSearch < ' s > {
2404
+ fn from ( value : & ' s syn:: Generics ) -> Self {
2405
+ Self {
2406
+ types : value. type_params ( ) . map ( |p| & p. ident ) . collect ( ) ,
2407
+ lifetimes : value. lifetimes ( ) . map ( |p| & p. lifetime . ident ) . collect ( ) ,
2408
+ consts : value. const_params ( ) . map ( |p| & p. ident ) . collect ( ) ,
2409
+ }
2410
+ }
2411
+ }
2412
+
2403
2413
impl GenericsSearch < ' _ > {
2404
2414
/// Checks the provided [`syn::Type`] to contain anything from this [`GenericsSearch`].
2405
2415
pub ( crate ) fn any_in ( & self , ty : & syn:: Type ) -> bool {
@@ -2422,27 +2432,139 @@ mod generics_search {
2422
2432
}
2423
2433
2424
2434
impl < ' ast > Visit < ' ast > for Visitor < ' _ > {
2435
+ fn visit_expr_path ( & mut self , ep : & ' ast syn:: ExprPath ) {
2436
+ self . found |= ep
2437
+ . path
2438
+ . get_ident ( )
2439
+ . is_some_and ( |ident| self . search . consts . contains ( ident) ) ;
2440
+
2441
+ if !self . found {
2442
+ syn:: visit:: visit_expr_path ( self , ep) ;
2443
+ }
2444
+ }
2445
+
2446
+ fn visit_lifetime ( & mut self , lf : & ' ast syn:: Lifetime ) {
2447
+ self . found |= self . search . lifetimes . contains ( & lf. ident ) ;
2448
+
2449
+ if !self . found {
2450
+ syn:: visit:: visit_lifetime ( self , lf) ;
2451
+ }
2452
+ }
2453
+
2425
2454
fn visit_type_path ( & mut self , tp : & ' ast syn:: TypePath ) {
2426
2455
self . found |= tp. path . get_ident ( ) . is_some_and ( |ident| {
2427
2456
self . search . types . contains ( ident) || self . search . consts . contains ( ident)
2428
2457
} ) ;
2429
2458
2430
- syn:: visit:: visit_type_path ( self , tp)
2431
- }
2459
+ if !self . found {
2460
+ // `TypeParam::AssocType` case.
2461
+ self . found |= tp. path . segments . first ( ) . is_some_and ( |segment| {
2462
+ matches ! ( segment. arguments, syn:: PathArguments :: None )
2463
+ && self . search . types . contains ( & segment. ident )
2464
+ } ) ;
2465
+ }
2432
2466
2433
- fn visit_lifetime ( & mut self , lf : & ' ast syn:: Lifetime ) {
2434
- self . found |= self . search . lifetimes . contains ( & lf. ident ) ;
2467
+ if !self . found {
2468
+ syn:: visit:: visit_type_path ( self , tp)
2469
+ }
2470
+ }
2471
+ }
2435
2472
2436
- syn:: visit:: visit_lifetime ( self , lf)
2473
+ #[ cfg( test) ]
2474
+ mod spec {
2475
+ use quote:: ToTokens as _;
2476
+ use syn:: parse_quote;
2477
+
2478
+ use super :: GenericsSearch ;
2479
+
2480
+ #[ test]
2481
+ fn types ( ) {
2482
+ let generics: syn:: Generics = parse_quote ! { <T > } ;
2483
+ let search = GenericsSearch :: from ( & generics) ;
2484
+
2485
+ for input in [
2486
+ parse_quote ! { T } ,
2487
+ parse_quote ! { & T } ,
2488
+ parse_quote ! { & ' a T } ,
2489
+ parse_quote ! { &&' a T } ,
2490
+ parse_quote ! { Type <' a, T > } ,
2491
+ parse_quote ! { path:: Type <T , ' a> } ,
2492
+ parse_quote ! { path:: <' a, T >:: Type } ,
2493
+ parse_quote ! { <Self as Trait <' a, T >>:: Type } ,
2494
+ parse_quote ! { <Self as Trait >:: Type <T , ' a> } ,
2495
+ parse_quote ! { T :: Type } ,
2496
+ parse_quote ! { <T as Trait >:: Type } ,
2497
+ parse_quote ! { [ T ] } ,
2498
+ parse_quote ! { [ T ; 3 ] } ,
2499
+ parse_quote ! { [ T ; _] } ,
2500
+ parse_quote ! { ( T ) } ,
2501
+ parse_quote ! { ( T , ) } ,
2502
+ parse_quote ! { ( T , u8 ) } ,
2503
+ parse_quote ! { ( u8 , T ) } ,
2504
+ parse_quote ! { fn ( T ) } ,
2505
+ parse_quote ! { fn ( u8 , T ) } ,
2506
+ parse_quote ! { fn ( _) -> T } ,
2507
+ parse_quote ! { fn ( _) -> ( u8 , T ) } ,
2508
+ ] {
2509
+ assert ! (
2510
+ search. any_in( & input) ,
2511
+ "cannot find type parameter `T` in type `{}`" ,
2512
+ input. into_token_stream( ) ,
2513
+ ) ;
2514
+ }
2437
2515
}
2438
2516
2439
- fn visit_expr_path ( & mut self , ep : & ' ast syn:: ExprPath ) {
2440
- self . found |= ep
2441
- . path
2442
- . get_ident ( )
2443
- . is_some_and ( |ident| self . search . consts . contains ( ident) ) ;
2517
+ #[ test]
2518
+ fn lifetimes ( ) {
2519
+ let generics: syn:: Generics = parse_quote ! { <' a> } ;
2520
+ let search = GenericsSearch :: from ( & generics) ;
2521
+
2522
+ for input in [
2523
+ parse_quote ! { & ' a T } ,
2524
+ parse_quote ! { &&' a T } ,
2525
+ parse_quote ! { Type <' a> } ,
2526
+ parse_quote ! { path:: Type <' a> } ,
2527
+ parse_quote ! { path:: <' a>:: Type } ,
2528
+ parse_quote ! { <Self as Trait <' a>>:: Type } ,
2529
+ parse_quote ! { <Self as Trait >:: Type <' a> } ,
2530
+ ] {
2531
+ assert ! (
2532
+ search. any_in( & input) ,
2533
+ "cannot find lifetime parameter `'a` in type `{}`" ,
2534
+ input. into_token_stream( ) ,
2535
+ ) ;
2536
+ }
2537
+ }
2444
2538
2445
- syn:: visit:: visit_expr_path ( self , ep)
2539
+ #[ test]
2540
+ fn consts ( ) {
2541
+ let generics: syn:: Generics = parse_quote ! { <const N : usize > } ;
2542
+ let search = GenericsSearch :: from ( & generics) ;
2543
+
2544
+ for input in [
2545
+ parse_quote ! { [ _; N ] } ,
2546
+ parse_quote ! { Type <N > } ,
2547
+ #[ cfg( feature = "testing-helpers" ) ] // requires `syn/full`
2548
+ parse_quote ! { Type <{ N } > } ,
2549
+ parse_quote ! { path:: Type <N > } ,
2550
+ #[ cfg( feature = "testing-helpers" ) ] // requires `syn/full`
2551
+ parse_quote ! { path:: Type <{ N } > } ,
2552
+ parse_quote ! { path:: <N >:: Type } ,
2553
+ #[ cfg( feature = "testing-helpers" ) ] // requires `syn/full`
2554
+ parse_quote ! { path:: <{ N } >:: Type } ,
2555
+ parse_quote ! { <Self as Trait <N >>:: Type } ,
2556
+ #[ cfg( feature = "testing-helpers" ) ] // requires `syn/full`
2557
+ parse_quote ! { <Self as Trait <{ N } >>:: Type } ,
2558
+ parse_quote ! { <Self as Trait >:: Type <N > } ,
2559
+ #[ cfg( feature = "testing-helpers" ) ] // requires `syn/full`
2560
+ parse_quote ! { <Self as Trait >:: Type <{ N } > } ,
2561
+ ] {
2562
+ assert ! (
2563
+ search. any_in( & input) ,
2564
+ "cannot find const parameter `N` in type `{}`" ,
2565
+ input. into_token_stream( ) ,
2566
+ ) ;
2567
+ }
2446
2568
}
2447
2569
}
2448
2570
}
0 commit comments