@@ -61,6 +61,7 @@ use syntax::attr;
6161use syntax:: ast:: * ;
6262use syntax:: errors;
6363use syntax:: ext:: hygiene:: { Mark , SyntaxContext } ;
64+ use syntax:: print:: pprust;
6465use syntax:: ptr:: P ;
6566use syntax:: codemap:: { self , respan, Spanned , CompilerDesugaringKind } ;
6667use syntax:: std_inject;
@@ -106,6 +107,13 @@ pub struct LoweringContext<'a> {
106107 is_in_loop_condition : bool ,
107108 is_in_trait_impl : bool ,
108109
110+ // This is a list of in-band type definitions being generated by
111+ // Argument-position `impl Trait`.
112+ // When traversing a signature such as `fn foo(x: impl Trait)`,
113+ // we record `impl Trait` as a new type parameter, then later
114+ // add it on to `foo`s generics.
115+ in_band_ty_params : Vec < hir:: TyParam > ,
116+
109117 // Used to create lifetime definitions from in-band lifetime usages.
110118 // e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
111119 // When a named lifetime is encountered in a function or impl header and
@@ -197,6 +205,7 @@ pub fn lower_crate(sess: &Session,
197205 node_id_to_hir_id : IndexVec :: new ( ) ,
198206 is_generator : false ,
199207 is_in_trait_impl : false ,
208+ in_band_ty_params : Vec :: new ( ) ,
200209 lifetimes_to_define : Vec :: new ( ) ,
201210 is_collecting_in_band_lifetimes : false ,
202211 in_scope_lifetimes : Vec :: new ( ) ,
@@ -526,20 +535,23 @@ impl<'a> LoweringContext<'a> {
526535 // Creates a new hir::LifetimeDef for every new lifetime encountered
527536 // while evaluating `f`. Definitions are created with the parent provided.
528537 // If no `parent_id` is provided, no definitions will be returned.
529- fn collect_in_band_lifetime_defs < T , F > (
538+ fn collect_in_band_defs < T , F > (
530539 & mut self ,
531540 parent_id : Option < DefId > ,
532541 f : F
533- ) -> ( Vec < hir:: LifetimeDef > , T ) where F : FnOnce ( & mut LoweringContext ) -> T
542+ ) -> ( Vec < hir:: TyParam > , Vec < hir :: LifetimeDef > , T ) where F : FnOnce ( & mut LoweringContext ) -> T
534543 {
535544 assert ! ( !self . is_collecting_in_band_lifetimes) ;
536545 assert ! ( self . lifetimes_to_define. is_empty( ) ) ;
537546 self . is_collecting_in_band_lifetimes = self . sess . features . borrow ( ) . in_band_lifetimes ;
538547
548+ assert ! ( self . in_band_ty_params. is_empty( ) ) ;
549+
539550 let res = f ( self ) ;
540551
541552 self . is_collecting_in_band_lifetimes = false ;
542553
554+ let in_band_ty_params = self . in_band_ty_params . split_off ( 0 ) ;
543555 let lifetimes_to_define = self . lifetimes_to_define . split_off ( 0 ) ;
544556
545557 let lifetime_defs = match parent_id {
@@ -569,7 +581,7 @@ impl<'a> LoweringContext<'a> {
569581 None => Vec :: new ( ) ,
570582 } ;
571583
572- ( lifetime_defs, res)
584+ ( in_band_ty_params , lifetime_defs, res)
573585 }
574586
575587 // Evaluates `f` with the lifetimes in `lt_defs` in-scope.
@@ -613,29 +625,33 @@ impl<'a> LoweringContext<'a> {
613625 res
614626 }
615627
616- // Appends in-band lifetime defs to the existing set of out-of-band lifetime defs.
617- // Evaluates all within the context of the out-of-band defs.
618- // If provided, `impl_item_id` is used to find the parent impls of impl items so
619- // that their generics are not duplicated.
620- fn add_in_band_lifetime_defs < F , T > (
628+ // Appends in-band lifetime defs and argument-position `impl Trait` defs
629+ // to the existing set of generics.
630+ fn add_in_band_defs < F , T > (
621631 & mut self ,
622632 generics : & Generics ,
623633 parent_id : Option < DefId > ,
624634 f : F
625635 ) -> ( hir:: Generics , T )
626636 where F : FnOnce ( & mut LoweringContext ) -> T
627637 {
628- let ( in_band_defs , ( mut lowered_generics, res) ) =
638+ let ( in_band_ty_defs , in_band_lifetime_defs , ( mut lowered_generics, res) ) =
629639 self . with_in_scope_lifetime_defs ( & generics. lifetimes , |this| {
630- this. collect_in_band_lifetime_defs ( parent_id, |this| {
640+ this. collect_in_band_defs ( parent_id, |this| {
631641 ( this. lower_generics ( generics) , f ( this) )
632642 } )
633643 } ) ;
634644
645+ lowered_generics. ty_params =
646+ lowered_generics. ty_params
647+ . iter ( ) . cloned ( )
648+ . chain ( in_band_ty_defs. into_iter ( ) )
649+ . collect ( ) ;
650+
635651 lowered_generics. lifetimes =
636652 lowered_generics. lifetimes
637653 . iter ( ) . cloned ( )
638- . chain ( in_band_defs . into_iter ( ) )
654+ . chain ( in_band_lifetime_defs . into_iter ( ) )
639655 . collect ( ) ;
640656
641657 ( lowered_generics, res)
@@ -922,6 +938,7 @@ impl<'a> LoweringContext<'a> {
922938 }
923939 TyKind :: ImplTrait ( ref bounds) => {
924940 use syntax:: feature_gate:: { emit_feature_err, GateIssue } ;
941+ let span = t. span ;
925942 match itctx {
926943 ImplTraitContext :: Existential => {
927944 let has_feature = self . sess . features . borrow ( ) . conservative_impl_trait ;
@@ -944,7 +961,7 @@ impl<'a> LoweringContext<'a> {
944961 id : self . next_id ( ) . node_id ,
945962 predicates : Vec :: new ( ) . into ( ) ,
946963 } ,
947- span : t . span ,
964+ span,
948965 } ,
949966 bounds : hir_bounds,
950967 } , lifetimes)
@@ -956,7 +973,35 @@ impl<'a> LoweringContext<'a> {
956973 t. span , GateIssue :: Language ,
957974 "`impl Trait` in argument position is experimental" ) ;
958975 }
959- hir:: TyImplTraitUniversal ( def_id, self . lower_bounds ( bounds, itctx) )
976+
977+ let def_node_id = self . next_id ( ) . node_id ;
978+
979+ // Add a definition for the in-band TyParam
980+ let def_index = self . resolver . definitions ( ) . create_def_with_parent (
981+ def_id. index ,
982+ def_node_id,
983+ DefPathData :: ImplTrait ,
984+ DefIndexAddressSpace :: High ,
985+ Mark :: root ( )
986+ ) ;
987+
988+ let hir_bounds = self . lower_bounds ( bounds, itctx) ;
989+ self . in_band_ty_params . push ( hir:: TyParam {
990+ // Set the name to `impl Bound1 + Bound2`
991+ name : Symbol :: intern ( & pprust:: ty_to_string ( t) ) ,
992+ id : def_node_id,
993+ bounds : hir_bounds,
994+ default : None ,
995+ span,
996+ pure_wrt_drop : false ,
997+ synthetic : Some ( hir:: SyntheticTyParamKind :: ImplTrait ) ,
998+ } ) ;
999+
1000+ hir:: TyPath ( hir:: QPath :: Resolved ( None , P ( hir:: Path {
1001+ span,
1002+ def : Def :: TyParam ( DefId :: local ( def_index) ) ,
1003+ segments : vec ! [ ] . into ( ) ,
1004+ } ) ) )
9601005 } ,
9611006 ImplTraitContext :: Disallowed => {
9621007 span_err ! ( self . sess, t. span, E0562 ,
@@ -1829,7 +1874,7 @@ impl<'a> LoweringContext<'a> {
18291874 this. expr_block ( body, ThinVec :: new ( ) )
18301875 } ) ;
18311876 let ( generics, fn_decl) =
1832- this. add_in_band_lifetime_defs ( generics, fn_def_id, |this|
1877+ this. add_in_band_defs ( generics, fn_def_id, |this|
18331878 this. lower_fn_decl ( decl, fn_def_id, true ) ) ;
18341879
18351880 hir:: ItemFn ( fn_decl,
@@ -1883,7 +1928,7 @@ impl<'a> LoweringContext<'a> {
18831928 ref impl_items) => {
18841929 let def_id = self . resolver . definitions ( ) . opt_local_def_id ( id) ;
18851930 let ( generics, ( ifce, lowered_ty) ) =
1886- self . add_in_band_lifetime_defs ( ast_generics, def_id, |this| {
1931+ self . add_in_band_defs ( ast_generics, def_id, |this| {
18871932 let ifce = ifce. as_ref ( ) . map ( |trait_ref| {
18881933 this. lower_trait_ref ( trait_ref, ImplTraitContext :: Disallowed )
18891934 } ) ;
@@ -2059,7 +2104,7 @@ impl<'a> LoweringContext<'a> {
20592104 }
20602105 TraitItemKind :: Method ( ref sig, None ) => {
20612106 let names = this. lower_fn_args_to_names ( & sig. decl ) ;
2062- this. add_in_band_lifetime_defs ( & i. generics , fn_def_id, |this|
2107+ this. add_in_band_defs ( & i. generics , fn_def_id, |this|
20632108 hir:: TraitItemKind :: Method (
20642109 this. lower_method_sig ( sig, fn_def_id, false ) ,
20652110 hir:: TraitMethod :: Required ( names) ) )
@@ -2070,7 +2115,7 @@ impl<'a> LoweringContext<'a> {
20702115 this. expr_block ( body, ThinVec :: new ( ) )
20712116 } ) ;
20722117
2073- this. add_in_band_lifetime_defs ( & i. generics , fn_def_id, |this|
2118+ this. add_in_band_defs ( & i. generics , fn_def_id, |this|
20742119 hir:: TraitItemKind :: Method (
20752120 this. lower_method_sig ( sig, fn_def_id, false ) ,
20762121 hir:: TraitMethod :: Provided ( body_id) ) )
@@ -2147,7 +2192,7 @@ impl<'a> LoweringContext<'a> {
21472192 } ) ;
21482193 let impl_trait_return_allow = !this. is_in_trait_impl ;
21492194
2150- this. add_in_band_lifetime_defs ( & i. generics , fn_def_id, |this|
2195+ this. add_in_band_defs ( & i. generics , fn_def_id, |this|
21512196 hir:: ImplItemKind :: Method (
21522197 this. lower_method_sig ( sig, fn_def_id, impl_trait_return_allow) ,
21532198 body_id) )
@@ -2280,7 +2325,7 @@ impl<'a> LoweringContext<'a> {
22802325 ForeignItemKind :: Fn ( ref fdec, ref generics) => {
22812326 // Disallow impl Trait in foreign items
22822327 let ( generics, ( fn_dec, fn_args) ) =
2283- this. add_in_band_lifetime_defs (
2328+ this. add_in_band_defs (
22842329 generics,
22852330 Some ( def_id) ,
22862331 |this| (
0 commit comments