@@ -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;
@@ -394,7 +395,7 @@ impl<'a> LoweringContext<'a> {
394
395
}
395
396
}
396
397
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 {
398
399
let mut name = tp. ident . name ;
399
400
400
401
// Don't expose `Self` (recovered "keyword used as ident" parse error).
@@ -404,18 +405,26 @@ impl<'a> LoweringContext<'a> {
404
405
name = Symbol :: gensym ( "Self" ) ;
405
406
}
406
407
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
+
407
413
hir:: TyParam {
408
414
id : tp. id ,
409
415
name : name,
410
- bounds : self . lower_bounds ( & tp . bounds ) ,
416
+ bounds : bounds,
411
417
default : tp. default . as_ref ( ) . map ( |x| self . lower_ty ( x) ) ,
412
418
span : tp. span ,
413
419
pure_wrt_drop : tp. attrs . iter ( ) . any ( |attr| attr. check_name ( "may_dangle" ) ) ,
414
420
}
415
421
}
416
422
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 ( )
419
428
}
420
429
421
430
fn lower_lifetime ( & mut self , l : & Lifetime ) -> hir:: Lifetime {
@@ -447,8 +456,47 @@ impl<'a> LoweringContext<'a> {
447
456
}
448
457
449
458
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
+
450
498
hir:: Generics {
451
- ty_params : self . lower_ty_params ( & g. ty_params ) ,
499
+ ty_params : self . lower_ty_params ( & g. ty_params , & add_bounds ) ,
452
500
lifetimes : self . lower_lifetime_defs ( & g. lifetimes ) ,
453
501
where_clause : self . lower_where_clause ( & g. where_clause ) ,
454
502
span : g. span ,
@@ -474,7 +522,11 @@ impl<'a> LoweringContext<'a> {
474
522
hir:: WherePredicate :: BoundPredicate ( hir:: WhereBoundPredicate {
475
523
bound_lifetimes : self . lower_lifetime_defs ( bound_lifetimes) ,
476
524
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 ( ) ,
478
530
span : span,
479
531
} )
480
532
}
@@ -563,7 +615,7 @@ impl<'a> LoweringContext<'a> {
563
615
}
564
616
}
565
617
566
- fn lower_bounds ( & mut self , bounds : & TyParamBounds ) -> hir:: TyParamBounds {
618
+ fn lower_bounds ( & mut self , bounds : & [ TyParamBound ] ) -> hir:: TyParamBounds {
567
619
bounds. iter ( ) . map ( |bound| self . lower_ty_param_bound ( bound) ) . collect ( )
568
620
}
569
621
0 commit comments