@@ -332,44 +332,74 @@ pub fn combine_substructure(
332
332
RefCell :: new ( f)
333
333
}
334
334
335
+ struct TypeParameter {
336
+ bound_generic_params : Vec < ast:: GenericParam > ,
337
+ ty : P < ast:: Ty > ,
338
+ }
339
+
335
340
/// This method helps to extract all the type parameters referenced from a
336
341
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
337
342
/// is not global and starts with `T`, or a `TyQPath`.
343
+ /// Also include bound generic params from the input type.
338
344
fn find_type_parameters (
339
345
ty : & ast:: Ty ,
340
346
ty_param_names : & [ Symbol ] ,
341
347
cx : & ExtCtxt < ' _ > ,
342
- ) -> Vec < P < ast :: Ty > > {
348
+ ) -> Vec < TypeParameter > {
343
349
use rustc_ast:: visit;
344
350
345
351
struct Visitor < ' a , ' b > {
346
352
cx : & ' a ExtCtxt < ' b > ,
347
353
ty_param_names : & ' a [ Symbol ] ,
348
- types : Vec < P < ast:: Ty > > ,
354
+ bound_generic_params_stack : Vec < ast:: GenericParam > ,
355
+ type_params : Vec < TypeParameter > ,
349
356
}
350
357
351
358
impl < ' a , ' b > visit:: Visitor < ' a > for Visitor < ' a , ' b > {
352
359
fn visit_ty ( & mut self , ty : & ' a ast:: Ty ) {
353
360
if let ast:: TyKind :: Path ( _, ref path) = ty. kind {
354
361
if let Some ( segment) = path. segments . first ( ) {
355
362
if self . ty_param_names . contains ( & segment. ident . name ) {
356
- self . types . push ( P ( ty. clone ( ) ) ) ;
363
+ self . type_params . push ( TypeParameter {
364
+ bound_generic_params : self . bound_generic_params_stack . clone ( ) ,
365
+ ty : P ( ty. clone ( ) ) ,
366
+ } ) ;
357
367
}
358
368
}
359
369
}
360
370
361
371
visit:: walk_ty ( self , ty)
362
372
}
363
373
374
+ // Place bound generic params on a stack, to extract them when a type is encountered.
375
+ fn visit_poly_trait_ref (
376
+ & mut self ,
377
+ trait_ref : & ' a ast:: PolyTraitRef ,
378
+ modifier : & ' a ast:: TraitBoundModifier ,
379
+ ) {
380
+ let stack_len = self . bound_generic_params_stack . len ( ) ;
381
+ self . bound_generic_params_stack
382
+ . extend ( trait_ref. bound_generic_params . clone ( ) . into_iter ( ) ) ;
383
+
384
+ visit:: walk_poly_trait_ref ( self , trait_ref, modifier) ;
385
+
386
+ self . bound_generic_params_stack . truncate ( stack_len) ;
387
+ }
388
+
364
389
fn visit_mac_call ( & mut self , mac : & ast:: MacCall ) {
365
390
self . cx . span_err ( mac. span ( ) , "`derive` cannot be used on items with type macros" ) ;
366
391
}
367
392
}
368
393
369
- let mut visitor = Visitor { cx, ty_param_names, types : Vec :: new ( ) } ;
394
+ let mut visitor = Visitor {
395
+ cx,
396
+ ty_param_names,
397
+ bound_generic_params_stack : Vec :: new ( ) ,
398
+ type_params : Vec :: new ( ) ,
399
+ } ;
370
400
visit:: Visitor :: visit_ty ( & mut visitor, ty) ;
371
401
372
- visitor. types
402
+ visitor. type_params
373
403
}
374
404
375
405
impl < ' a > TraitDef < ' a > {
@@ -617,11 +647,11 @@ impl<'a> TraitDef<'a> {
617
647
ty_params. map ( |ty_param| ty_param. ident . name ) . collect ( ) ;
618
648
619
649
for field_ty in field_tys {
620
- let tys = find_type_parameters ( & field_ty, & ty_param_names, cx) ;
650
+ let field_ty_params = find_type_parameters ( & field_ty, & ty_param_names, cx) ;
621
651
622
- for ty in tys {
652
+ for field_ty_param in field_ty_params {
623
653
// if we have already handled this type, skip it
624
- if let ast:: TyKind :: Path ( _, ref p) = ty. kind {
654
+ if let ast:: TyKind :: Path ( _, ref p) = field_ty_param . ty . kind {
625
655
if p. segments . len ( ) == 1
626
656
&& ty_param_names. contains ( & p. segments [ 0 ] . ident . name )
627
657
{
@@ -639,8 +669,8 @@ impl<'a> TraitDef<'a> {
639
669
640
670
let predicate = ast:: WhereBoundPredicate {
641
671
span : self . span ,
642
- bound_generic_params : Vec :: new ( ) ,
643
- bounded_ty : ty,
672
+ bound_generic_params : field_ty_param . bound_generic_params ,
673
+ bounded_ty : field_ty_param . ty ,
644
674
bounds,
645
675
} ;
646
676
0 commit comments