@@ -46,6 +46,7 @@ use hir::map::definitions::DefPathData;
46
46
use hir:: def_id:: { DefIndex , DefId } ;
47
47
use hir:: def:: { Def , PathResolution } ;
48
48
use session:: Session ;
49
+ use util:: nodemap:: NodeMap ;
49
50
50
51
use std:: collections:: BTreeMap ;
51
52
use std:: iter;
@@ -508,7 +509,7 @@ impl<'a> LoweringContext<'a> {
508
509
}
509
510
}
510
511
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 {
512
513
let mut name = tp. ident . name ;
513
514
514
515
// Don't expose `Self` (recovered "keyword used as ident" parse error).
@@ -518,18 +519,26 @@ impl<'a> LoweringContext<'a> {
518
519
name = Symbol :: gensym ( "Self" ) ;
519
520
}
520
521
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
+
521
527
hir:: TyParam {
522
528
id : tp. id ,
523
529
name : name,
524
- bounds : self . lower_bounds ( & tp . bounds ) ,
530
+ bounds : bounds,
525
531
default : tp. default . as_ref ( ) . map ( |x| self . lower_ty ( x) ) ,
526
532
span : tp. span ,
527
533
pure_wrt_drop : tp. attrs . iter ( ) . any ( |attr| attr. check_name ( "may_dangle" ) ) ,
528
534
}
529
535
}
530
536
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 ( )
533
542
}
534
543
535
544
fn lower_lifetime ( & mut self , l : & Lifetime ) -> hir:: Lifetime {
@@ -561,8 +570,47 @@ impl<'a> LoweringContext<'a> {
561
570
}
562
571
563
572
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
+
564
612
hir:: Generics {
565
- ty_params : self . lower_ty_params ( & g. ty_params ) ,
613
+ ty_params : self . lower_ty_params ( & g. ty_params , & add_bounds ) ,
566
614
lifetimes : self . lower_lifetime_defs ( & g. lifetimes ) ,
567
615
where_clause : self . lower_where_clause ( & g. where_clause ) ,
568
616
span : g. span ,
@@ -588,7 +636,11 @@ impl<'a> LoweringContext<'a> {
588
636
hir:: WherePredicate :: BoundPredicate ( hir:: WhereBoundPredicate {
589
637
bound_lifetimes : self . lower_lifetime_defs ( bound_lifetimes) ,
590
638
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 ( ) ,
592
644
span : span,
593
645
} )
594
646
}
@@ -677,7 +729,7 @@ impl<'a> LoweringContext<'a> {
677
729
}
678
730
}
679
731
680
- fn lower_bounds ( & mut self , bounds : & TyParamBounds ) -> hir:: TyParamBounds {
732
+ fn lower_bounds ( & mut self , bounds : & [ TyParamBound ] ) -> hir:: TyParamBounds {
681
733
bounds. iter ( ) . map ( |bound| self . lower_ty_param_bound ( bound) ) . collect ( )
682
734
}
683
735
0 commit comments