@@ -46,6 +46,7 @@ use hir::map::definitions::DefPathData;
4646use hir:: def_id:: { DefIndex , DefId } ;
4747use hir:: def:: { Def , PathResolution } ;
4848use session:: Session ;
49+ use util:: nodemap:: NodeMap ;
4950
5051use std:: collections:: BTreeMap ;
5152use std:: iter;
@@ -394,7 +395,7 @@ impl<'a> LoweringContext<'a> {
394395 }
395396 }
396397
397- fn lower_ty_param ( & mut self , tp : & TyParam ) -> hir:: TyParam {
398+ fn lower_ty_param ( & mut self , tp : & TyParam , add_bounds : & [ TyParamBound ] ) -> hir:: TyParam {
398399 let mut name = tp. ident . name ;
399400
400401 // Don't expose `Self` (recovered "keyword used as ident" parse error).
@@ -404,18 +405,26 @@ impl<'a> LoweringContext<'a> {
404405 name = Symbol :: gensym ( "Self" ) ;
405406 }
406407
408+ let mut bounds = self . lower_bounds ( & tp. bounds ) ;
409+ if !add_bounds. is_empty ( ) {
410+ bounds = bounds. into_iter ( ) . chain ( self . lower_bounds ( add_bounds) . into_iter ( ) ) . collect ( ) ;
411+ }
412+
407413 hir:: TyParam {
408414 id : tp. id ,
409415 name : name,
410- bounds : self . lower_bounds ( & tp . bounds ) ,
416+ bounds : bounds,
411417 default : tp. default . as_ref ( ) . map ( |x| self . lower_ty ( x) ) ,
412418 span : tp. span ,
413419 pure_wrt_drop : tp. attrs . iter ( ) . any ( |attr| attr. check_name ( "may_dangle" ) ) ,
414420 }
415421 }
416422
417- fn lower_ty_params ( & mut self , tps : & P < [ TyParam ] > ) -> hir:: HirVec < hir:: TyParam > {
418- tps. iter ( ) . map ( |tp| self . lower_ty_param ( tp) ) . collect ( )
423+ fn lower_ty_params ( & mut self , tps : & P < [ TyParam ] > , add_bounds : & NodeMap < Vec < TyParamBound > > )
424+ -> hir:: HirVec < hir:: TyParam > {
425+ tps. iter ( ) . map ( |tp| {
426+ self . lower_ty_param ( tp, add_bounds. get ( & tp. id ) . map_or ( & [ ] [ ..] , |x| & x) )
427+ } ) . collect ( )
419428 }
420429
421430 fn lower_lifetime ( & mut self , l : & Lifetime ) -> hir:: Lifetime {
@@ -447,8 +456,47 @@ impl<'a> LoweringContext<'a> {
447456 }
448457
449458 fn lower_generics ( & mut self , g : & Generics ) -> hir:: Generics {
459+ // Collect `?Trait` bounds in where clause and move them to parameter definitions.
460+ let mut add_bounds = NodeMap ( ) ;
461+ for pred in & g. where_clause . predicates {
462+ if let WherePredicate :: BoundPredicate ( ref bound_pred) = * pred {
463+ ' next_bound: for bound in & bound_pred. bounds {
464+ if let TraitTyParamBound ( _, TraitBoundModifier :: Maybe ) = * bound {
465+ let report_error = |this : & mut Self | {
466+ this. diagnostic ( ) . span_err ( bound_pred. bounded_ty . span ,
467+ "`?Trait` bounds are only permitted at the \
468+ point where a type parameter is declared") ;
469+ } ;
470+ // Check if the where clause type is a plain type parameter.
471+ match bound_pred. bounded_ty . node {
472+ TyKind :: Path ( None , ref path)
473+ if !path. global && path. segments . len ( ) == 1 &&
474+ bound_pred. bound_lifetimes . is_empty ( ) => {
475+ if let Some ( Def :: TyParam ( def_id) ) =
476+ self . resolver . get_resolution ( bound_pred. bounded_ty . id )
477+ . map ( |d| d. base_def ) {
478+ if let Some ( node_id) =
479+ self . resolver . definitions ( ) . as_local_node_id ( def_id) {
480+ for ty_param in & g. ty_params {
481+ if node_id == ty_param. id {
482+ add_bounds. entry ( ty_param. id ) . or_insert ( Vec :: new ( ) )
483+ . push ( bound. clone ( ) ) ;
484+ continue ' next_bound;
485+ }
486+ }
487+ }
488+ }
489+ report_error ( self )
490+ }
491+ _ => report_error ( self )
492+ }
493+ }
494+ }
495+ }
496+ }
497+
450498 hir:: Generics {
451- ty_params : self . lower_ty_params ( & g. ty_params ) ,
499+ ty_params : self . lower_ty_params ( & g. ty_params , & add_bounds ) ,
452500 lifetimes : self . lower_lifetime_defs ( & g. lifetimes ) ,
453501 where_clause : self . lower_where_clause ( & g. where_clause ) ,
454502 span : g. span ,
@@ -474,7 +522,11 @@ impl<'a> LoweringContext<'a> {
474522 hir:: WherePredicate :: BoundPredicate ( hir:: WhereBoundPredicate {
475523 bound_lifetimes : self . lower_lifetime_defs ( bound_lifetimes) ,
476524 bounded_ty : self . lower_ty ( bounded_ty) ,
477- bounds : bounds. iter ( ) . map ( |x| self . lower_ty_param_bound ( x) ) . collect ( ) ,
525+ bounds : bounds. iter ( ) . filter_map ( |bound| match * bound {
526+ // Ignore `?Trait` bounds, they were copied into type parameters already.
527+ TraitTyParamBound ( _, TraitBoundModifier :: Maybe ) => None ,
528+ _ => Some ( self . lower_ty_param_bound ( bound) )
529+ } ) . collect ( ) ,
478530 span : span,
479531 } )
480532 }
@@ -563,7 +615,7 @@ impl<'a> LoweringContext<'a> {
563615 }
564616 }
565617
566- fn lower_bounds ( & mut self , bounds : & TyParamBounds ) -> hir:: TyParamBounds {
618+ fn lower_bounds ( & mut self , bounds : & [ TyParamBound ] ) -> hir:: TyParamBounds {
567619 bounds. iter ( ) . map ( |bound| self . lower_ty_param_bound ( bound) ) . collect ( )
568620 }
569621
0 commit comments