@@ -61,6 +61,7 @@ use syntax::attr;
61
61
use syntax:: ast:: * ;
62
62
use syntax:: errors;
63
63
use syntax:: ext:: hygiene:: { Mark , SyntaxContext } ;
64
+ use syntax:: print:: pprust;
64
65
use syntax:: ptr:: P ;
65
66
use syntax:: codemap:: { self , respan, Spanned , CompilerDesugaringKind } ;
66
67
use syntax:: std_inject;
@@ -106,6 +107,13 @@ pub struct LoweringContext<'a> {
106
107
is_in_loop_condition : bool ,
107
108
is_in_trait_impl : bool ,
108
109
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
+
109
117
// Used to create lifetime definitions from in-band lifetime usages.
110
118
// e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
111
119
// When a named lifetime is encountered in a function or impl header and
@@ -197,6 +205,7 @@ pub fn lower_crate(sess: &Session,
197
205
node_id_to_hir_id : IndexVec :: new ( ) ,
198
206
is_generator : false ,
199
207
is_in_trait_impl : false ,
208
+ in_band_ty_params : Vec :: new ( ) ,
200
209
lifetimes_to_define : Vec :: new ( ) ,
201
210
is_collecting_in_band_lifetimes : false ,
202
211
in_scope_lifetimes : Vec :: new ( ) ,
@@ -526,20 +535,23 @@ impl<'a> LoweringContext<'a> {
526
535
// Creates a new hir::LifetimeDef for every new lifetime encountered
527
536
// while evaluating `f`. Definitions are created with the parent provided.
528
537
// 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 > (
530
539
& mut self ,
531
540
parent_id : Option < DefId > ,
532
541
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
534
543
{
535
544
assert ! ( !self . is_collecting_in_band_lifetimes) ;
536
545
assert ! ( self . lifetimes_to_define. is_empty( ) ) ;
537
546
self . is_collecting_in_band_lifetimes = self . sess . features . borrow ( ) . in_band_lifetimes ;
538
547
548
+ assert ! ( self . in_band_ty_params. is_empty( ) ) ;
549
+
539
550
let res = f ( self ) ;
540
551
541
552
self . is_collecting_in_band_lifetimes = false ;
542
553
554
+ let in_band_ty_params = self . in_band_ty_params . split_off ( 0 ) ;
543
555
let lifetimes_to_define = self . lifetimes_to_define . split_off ( 0 ) ;
544
556
545
557
let lifetime_defs = match parent_id {
@@ -569,7 +581,7 @@ impl<'a> LoweringContext<'a> {
569
581
None => Vec :: new ( ) ,
570
582
} ;
571
583
572
- ( lifetime_defs, res)
584
+ ( in_band_ty_params , lifetime_defs, res)
573
585
}
574
586
575
587
// Evaluates `f` with the lifetimes in `lt_defs` in-scope.
@@ -613,29 +625,33 @@ impl<'a> LoweringContext<'a> {
613
625
res
614
626
}
615
627
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 > (
621
631
& mut self ,
622
632
generics : & Generics ,
623
633
parent_id : Option < DefId > ,
624
634
f : F
625
635
) -> ( hir:: Generics , T )
626
636
where F : FnOnce ( & mut LoweringContext ) -> T
627
637
{
628
- let ( in_band_defs , ( mut lowered_generics, res) ) =
638
+ let ( in_band_ty_defs , in_band_lifetime_defs , ( mut lowered_generics, res) ) =
629
639
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| {
631
641
( this. lower_generics ( generics) , f ( this) )
632
642
} )
633
643
} ) ;
634
644
645
+ lowered_generics. ty_params =
646
+ lowered_generics. ty_params
647
+ . iter ( ) . cloned ( )
648
+ . chain ( in_band_ty_defs. into_iter ( ) )
649
+ . collect ( ) ;
650
+
635
651
lowered_generics. lifetimes =
636
652
lowered_generics. lifetimes
637
653
. iter ( ) . cloned ( )
638
- . chain ( in_band_defs . into_iter ( ) )
654
+ . chain ( in_band_lifetime_defs . into_iter ( ) )
639
655
. collect ( ) ;
640
656
641
657
( lowered_generics, res)
@@ -922,6 +938,7 @@ impl<'a> LoweringContext<'a> {
922
938
}
923
939
TyKind :: ImplTrait ( ref bounds) => {
924
940
use syntax:: feature_gate:: { emit_feature_err, GateIssue } ;
941
+ let span = t. span ;
925
942
match itctx {
926
943
ImplTraitContext :: Existential => {
927
944
let has_feature = self . sess . features . borrow ( ) . conservative_impl_trait ;
@@ -944,7 +961,7 @@ impl<'a> LoweringContext<'a> {
944
961
id : self . next_id ( ) . node_id ,
945
962
predicates : Vec :: new ( ) . into ( ) ,
946
963
} ,
947
- span : t . span ,
964
+ span,
948
965
} ,
949
966
bounds : hir_bounds,
950
967
} , lifetimes)
@@ -956,7 +973,35 @@ impl<'a> LoweringContext<'a> {
956
973
t. span , GateIssue :: Language ,
957
974
"`impl Trait` in argument position is experimental" ) ;
958
975
}
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
+ } ) ) )
960
1005
} ,
961
1006
ImplTraitContext :: Disallowed => {
962
1007
span_err ! ( self . sess, t. span, E0562 ,
@@ -1829,7 +1874,7 @@ impl<'a> LoweringContext<'a> {
1829
1874
this. expr_block ( body, ThinVec :: new ( ) )
1830
1875
} ) ;
1831
1876
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|
1833
1878
this. lower_fn_decl ( decl, fn_def_id, true ) ) ;
1834
1879
1835
1880
hir:: ItemFn ( fn_decl,
@@ -1883,7 +1928,7 @@ impl<'a> LoweringContext<'a> {
1883
1928
ref impl_items) => {
1884
1929
let def_id = self . resolver . definitions ( ) . opt_local_def_id ( id) ;
1885
1930
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| {
1887
1932
let ifce = ifce. as_ref ( ) . map ( |trait_ref| {
1888
1933
this. lower_trait_ref ( trait_ref, ImplTraitContext :: Disallowed )
1889
1934
} ) ;
@@ -2059,7 +2104,7 @@ impl<'a> LoweringContext<'a> {
2059
2104
}
2060
2105
TraitItemKind :: Method ( ref sig, None ) => {
2061
2106
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|
2063
2108
hir:: TraitItemKind :: Method (
2064
2109
this. lower_method_sig ( sig, fn_def_id, false ) ,
2065
2110
hir:: TraitMethod :: Required ( names) ) )
@@ -2070,7 +2115,7 @@ impl<'a> LoweringContext<'a> {
2070
2115
this. expr_block ( body, ThinVec :: new ( ) )
2071
2116
} ) ;
2072
2117
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|
2074
2119
hir:: TraitItemKind :: Method (
2075
2120
this. lower_method_sig ( sig, fn_def_id, false ) ,
2076
2121
hir:: TraitMethod :: Provided ( body_id) ) )
@@ -2147,7 +2192,7 @@ impl<'a> LoweringContext<'a> {
2147
2192
} ) ;
2148
2193
let impl_trait_return_allow = !this. is_in_trait_impl ;
2149
2194
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|
2151
2196
hir:: ImplItemKind :: Method (
2152
2197
this. lower_method_sig ( sig, fn_def_id, impl_trait_return_allow) ,
2153
2198
body_id) )
@@ -2280,7 +2325,7 @@ impl<'a> LoweringContext<'a> {
2280
2325
ForeignItemKind :: Fn ( ref fdec, ref generics) => {
2281
2326
// Disallow impl Trait in foreign items
2282
2327
let ( generics, ( fn_dec, fn_args) ) =
2283
- this. add_in_band_lifetime_defs (
2328
+ this. add_in_band_defs (
2284
2329
generics,
2285
2330
Some ( def_id) ,
2286
2331
|this| (
0 commit comments