@@ -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;
@@ -508,7 +509,7 @@ impl<'a> LoweringContext<'a> {
508509 }
509510 }
510511
511- fn lower_ty_param ( & mut self , tp : & TyParam ) -> hir:: TyParam {
512+ fn lower_ty_param ( & mut self , tp : & TyParam , add_bounds : & [ TyParamBound ] ) -> hir:: TyParam {
512513 let mut name = tp. ident . name ;
513514
514515 // Don't expose `Self` (recovered "keyword used as ident" parse error).
@@ -518,18 +519,26 @@ impl<'a> LoweringContext<'a> {
518519 name = Symbol :: gensym ( "Self" ) ;
519520 }
520521
522+ let mut bounds = self . lower_bounds ( & tp. bounds ) ;
523+ if !add_bounds. is_empty ( ) {
524+ bounds = bounds. into_iter ( ) . chain ( self . lower_bounds ( add_bounds) . into_iter ( ) ) . collect ( ) ;
525+ }
526+
521527 hir:: TyParam {
522528 id : tp. id ,
523529 name : name,
524- bounds : self . lower_bounds ( & tp . bounds ) ,
530+ bounds : bounds,
525531 default : tp. default . as_ref ( ) . map ( |x| self . lower_ty ( x) ) ,
526532 span : tp. span ,
527533 pure_wrt_drop : tp. attrs . iter ( ) . any ( |attr| attr. check_name ( "may_dangle" ) ) ,
528534 }
529535 }
530536
531- fn lower_ty_params ( & mut self , tps : & P < [ TyParam ] > ) -> hir:: HirVec < hir:: TyParam > {
532- tps. iter ( ) . map ( |tp| self . lower_ty_param ( tp) ) . collect ( )
537+ fn lower_ty_params ( & mut self , tps : & P < [ TyParam ] > , add_bounds : & NodeMap < Vec < TyParamBound > > )
538+ -> hir:: HirVec < hir:: TyParam > {
539+ tps. iter ( ) . map ( |tp| {
540+ self . lower_ty_param ( tp, add_bounds. get ( & tp. id ) . map_or ( & [ ] [ ..] , |x| & x) )
541+ } ) . collect ( )
533542 }
534543
535544 fn lower_lifetime ( & mut self , l : & Lifetime ) -> hir:: Lifetime {
@@ -561,8 +570,47 @@ impl<'a> LoweringContext<'a> {
561570 }
562571
563572 fn lower_generics ( & mut self , g : & Generics ) -> hir:: Generics {
573+ // Collect `?Trait` bounds in where clause and move them to parameter definitions.
574+ let mut add_bounds = NodeMap ( ) ;
575+ for pred in & g. where_clause . predicates {
576+ if let WherePredicate :: BoundPredicate ( ref bound_pred) = * pred {
577+ ' next_bound: for bound in & bound_pred. bounds {
578+ if let TraitTyParamBound ( _, TraitBoundModifier :: Maybe ) = * bound {
579+ let report_error = |this : & mut Self | {
580+ this. diagnostic ( ) . span_err ( bound_pred. bounded_ty . span ,
581+ "`?Trait` bounds are only permitted at the \
582+ point where a type parameter is declared") ;
583+ } ;
584+ // Check if the where clause type is a plain type parameter.
585+ match bound_pred. bounded_ty . node {
586+ TyKind :: Path ( None , ref path)
587+ if !path. global && path. segments . len ( ) == 1 &&
588+ bound_pred. bound_lifetimes . is_empty ( ) => {
589+ if let Some ( Def :: TyParam ( def_id) ) =
590+ self . resolver . get_resolution ( bound_pred. bounded_ty . id )
591+ . map ( |d| d. base_def ) {
592+ if let Some ( node_id) =
593+ self . resolver . definitions ( ) . as_local_node_id ( def_id) {
594+ for ty_param in & g. ty_params {
595+ if node_id == ty_param. id {
596+ add_bounds. entry ( ty_param. id ) . or_insert ( Vec :: new ( ) )
597+ . push ( bound. clone ( ) ) ;
598+ continue ' next_bound;
599+ }
600+ }
601+ }
602+ }
603+ report_error ( self )
604+ }
605+ _ => report_error ( self )
606+ }
607+ }
608+ }
609+ }
610+ }
611+
564612 hir:: Generics {
565- ty_params : self . lower_ty_params ( & g. ty_params ) ,
613+ ty_params : self . lower_ty_params ( & g. ty_params , & add_bounds ) ,
566614 lifetimes : self . lower_lifetime_defs ( & g. lifetimes ) ,
567615 where_clause : self . lower_where_clause ( & g. where_clause ) ,
568616 span : g. span ,
@@ -588,7 +636,11 @@ impl<'a> LoweringContext<'a> {
588636 hir:: WherePredicate :: BoundPredicate ( hir:: WhereBoundPredicate {
589637 bound_lifetimes : self . lower_lifetime_defs ( bound_lifetimes) ,
590638 bounded_ty : self . lower_ty ( bounded_ty) ,
591- bounds : bounds. iter ( ) . map ( |x| self . lower_ty_param_bound ( x) ) . collect ( ) ,
639+ bounds : bounds. iter ( ) . filter_map ( |bound| match * bound {
640+ // Ignore `?Trait` bounds, they were copied into type parameters already.
641+ TraitTyParamBound ( _, TraitBoundModifier :: Maybe ) => None ,
642+ _ => Some ( self . lower_ty_param_bound ( bound) )
643+ } ) . collect ( ) ,
592644 span : span,
593645 } )
594646 }
@@ -677,7 +729,7 @@ impl<'a> LoweringContext<'a> {
677729 }
678730 }
679731
680- fn lower_bounds ( & mut self , bounds : & TyParamBounds ) -> hir:: TyParamBounds {
732+ fn lower_bounds ( & mut self , bounds : & [ TyParamBound ] ) -> hir:: TyParamBounds {
681733 bounds. iter ( ) . map ( |bound| self . lower_ty_param_bound ( bound) ) . collect ( )
682734 }
683735
0 commit comments