@@ -332,44 +332,74 @@ pub fn combine_substructure(
332332 RefCell :: new ( f)
333333}
334334
335+ struct TypeParameter {
336+ bound_generic_params : Vec < ast:: GenericParam > ,
337+ ty : P < ast:: Ty > ,
338+ }
339+
335340/// This method helps to extract all the type parameters referenced from a
336341/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
337342/// is not global and starts with `T`, or a `TyQPath`.
343+ /// Also include bound generic params from the input type.
338344fn find_type_parameters (
339345 ty : & ast:: Ty ,
340346 ty_param_names : & [ Symbol ] ,
341347 cx : & ExtCtxt < ' _ > ,
342- ) -> Vec < P < ast :: Ty > > {
348+ ) -> Vec < TypeParameter > {
343349 use rustc_ast:: visit;
344350
345351 struct Visitor < ' a , ' b > {
346352 cx : & ' a ExtCtxt < ' b > ,
347353 ty_param_names : & ' a [ Symbol ] ,
348- types : Vec < P < ast:: Ty > > ,
354+ bound_generic_params_stack : Vec < ast:: GenericParam > ,
355+ type_params : Vec < TypeParameter > ,
349356 }
350357
351358 impl < ' a , ' b > visit:: Visitor < ' a > for Visitor < ' a , ' b > {
352359 fn visit_ty ( & mut self , ty : & ' a ast:: Ty ) {
353360 if let ast:: TyKind :: Path ( _, ref path) = ty. kind {
354361 if let Some ( segment) = path. segments . first ( ) {
355362 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+ } ) ;
357367 }
358368 }
359369 }
360370
361371 visit:: walk_ty ( self , ty)
362372 }
363373
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+
364389 fn visit_mac_call ( & mut self , mac : & ast:: MacCall ) {
365390 self . cx . span_err ( mac. span ( ) , "`derive` cannot be used on items with type macros" ) ;
366391 }
367392 }
368393
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+ } ;
370400 visit:: Visitor :: visit_ty ( & mut visitor, ty) ;
371401
372- visitor. types
402+ visitor. type_params
373403}
374404
375405impl < ' a > TraitDef < ' a > {
@@ -617,11 +647,11 @@ impl<'a> TraitDef<'a> {
617647 ty_params. map ( |ty_param| ty_param. ident . name ) . collect ( ) ;
618648
619649 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) ;
621651
622- for ty in tys {
652+ for field_ty_param in field_ty_params {
623653 // 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 {
625655 if p. segments . len ( ) == 1
626656 && ty_param_names. contains ( & p. segments [ 0 ] . ident . name )
627657 {
@@ -639,8 +669,8 @@ impl<'a> TraitDef<'a> {
639669
640670 let predicate = ast:: WhereBoundPredicate {
641671 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 ,
644674 bounds,
645675 } ;
646676
0 commit comments