@@ -179,7 +179,9 @@ enum ImplTraitContext {
179179 /// Treat `impl Trait` as shorthand for a new universal existential parameter.
180180 /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
181181 /// equivalent to a fresh existential parameter like `abstract type T; fn foo() -> T`.
182- Existential ,
182+ ///
183+ /// We store a DefId here so we can look up necessary information later
184+ Existential ( DefId ) ,
183185
184186 /// `impl Trait` is not accepted in this position.
185187 Disallowed ,
@@ -235,6 +237,7 @@ enum ParamMode {
235237 Optional ,
236238}
237239
240+ #[ derive( Debug ) ]
238241struct LoweredNodeId {
239242 node_id : NodeId ,
240243 hir_id : hir:: HirId ,
@@ -485,16 +488,16 @@ impl<'a> LoweringContext<'a> {
485488 }
486489 }
487490
488- fn with_hir_id_owner < F > ( & mut self , owner : NodeId , f : F )
491+ fn with_hir_id_owner < F , T > ( & mut self , owner : NodeId , f : F ) -> T
489492 where
490- F : FnOnce ( & mut Self ) ,
493+ F : FnOnce ( & mut Self ) -> T ,
491494 {
492495 let counter = self . item_local_id_counters
493496 . insert ( owner, HIR_ID_COUNTER_LOCKED )
494497 . unwrap ( ) ;
495498 let def_index = self . resolver . definitions ( ) . opt_def_index ( owner) . unwrap ( ) ;
496499 self . current_hir_id_owner . push ( ( def_index, counter) ) ;
497- f ( self ) ;
500+ let ret = f ( self ) ;
498501 let ( new_def_index, new_counter) = self . current_hir_id_owner . pop ( ) . unwrap ( ) ;
499502
500503 debug_assert ! ( def_index == new_def_index) ;
@@ -504,6 +507,7 @@ impl<'a> LoweringContext<'a> {
504507 . insert ( owner, new_counter)
505508 . unwrap ( ) ;
506509 debug_assert ! ( prev == HIR_ID_COUNTER_LOCKED ) ;
510+ ret
507511 }
508512
509513 /// This method allocates a new HirId for the given NodeId and stores it in
@@ -527,7 +531,10 @@ impl<'a> LoweringContext<'a> {
527531
528532 fn lower_node_id_with_owner ( & mut self , ast_node_id : NodeId , owner : NodeId ) -> LoweredNodeId {
529533 self . lower_node_id_generic ( ast_node_id, |this| {
530- let local_id_counter = this. item_local_id_counters . get_mut ( & owner) . unwrap ( ) ;
534+ let local_id_counter = this
535+ . item_local_id_counters
536+ . get_mut ( & owner)
537+ . expect ( "called lower_node_id_with_owner before allocate_hir_id_counter" ) ;
531538 let local_id = * local_id_counter;
532539
533540 // We want to be sure not to modify the counter in the map while it
@@ -536,7 +543,12 @@ impl<'a> LoweringContext<'a> {
536543 debug_assert ! ( local_id != HIR_ID_COUNTER_LOCKED ) ;
537544
538545 * local_id_counter += 1 ;
539- let def_index = this. resolver . definitions ( ) . opt_def_index ( owner) . unwrap ( ) ;
546+ let def_index = this
547+ . resolver
548+ . definitions ( )
549+ . opt_def_index ( owner)
550+ . expect ( "You forgot to call `create_def_with_parent` or are lowering node ids \
551+ that do not belong to the current owner") ;
540552
541553 hir:: HirId {
542554 owner : def_index,
@@ -1108,26 +1120,93 @@ impl<'a> LoweringContext<'a> {
11081120 TyKind :: ImplTrait ( ref bounds) => {
11091121 let span = t. span ;
11101122 match itctx {
1111- ImplTraitContext :: Existential => {
1112- let def_index = self . resolver . definitions ( ) . opt_def_index ( t. id ) . unwrap ( ) ;
1113- let hir_bounds = self . lower_bounds ( bounds, itctx) ;
1114- let ( lifetimes, lifetime_defs) =
1115- self . lifetimes_from_impl_trait_bounds ( def_index, & hir_bounds) ;
1123+ ImplTraitContext :: Existential ( fn_def_id) => {
1124+
1125+ // We need to manually repeat the code of `next_id` because the lowering
1126+ // needs to happen while the owner_id is pointing to the item itself,
1127+ // because items are their own owners
1128+ let exist_ty_node_id = self . sess . next_node_id ( ) ;
1129+
1130+ // Make sure we know that some funky desugaring has been going on here.
1131+ // This is a first: there is code in other places like for loop
1132+ // desugaring that explicitly states that we don't want to track that.
1133+ // Not tracking it makes lints in rustc and clippy very fragile as
1134+ // frequently opened issues show.
1135+ let exist_ty_span = self . allow_internal_unstable (
1136+ CompilerDesugaringKind :: ExistentialReturnType ,
1137+ t. span ,
1138+ ) ;
11161139
1117- hir:: TyImplTraitExistential (
1118- hir:: ExistTy {
1140+ // Pull a new definition from the ether
1141+ let exist_ty_def_index = self
1142+ . resolver
1143+ . definitions ( )
1144+ . create_def_with_parent (
1145+ fn_def_id. index ,
1146+ exist_ty_node_id,
1147+ DefPathData :: ExistentialImplTrait ,
1148+ DefIndexAddressSpace :: High ,
1149+ Mark :: root ( ) ,
1150+ exist_ty_span,
1151+ ) ;
1152+
1153+ // the `t` is just for printing debug messages
1154+ self . allocate_hir_id_counter ( exist_ty_node_id, t) ;
1155+
1156+ let hir_bounds = self . with_hir_id_owner ( exist_ty_node_id, |lctx| {
1157+ lctx. lower_bounds ( bounds, itctx)
1158+ } ) ;
1159+
1160+ let ( lifetimes, lifetime_defs) = self . lifetimes_from_impl_trait_bounds (
1161+ exist_ty_node_id,
1162+ exist_ty_def_index,
1163+ & hir_bounds,
1164+ ) ;
1165+
1166+ self . with_hir_id_owner ( exist_ty_node_id, |lctx| {
1167+ let exist_ty_item_kind = hir:: ItemExistential ( hir:: ExistTy {
11191168 generics : hir:: Generics {
11201169 params : lifetime_defs,
11211170 where_clause : hir:: WhereClause {
1122- id : self . next_id ( ) . node_id ,
1171+ id : lctx . next_id ( ) . node_id ,
11231172 predicates : Vec :: new ( ) . into ( ) ,
11241173 } ,
11251174 span,
11261175 } ,
11271176 bounds : hir_bounds,
1128- } ,
1129- lifetimes,
1130- )
1177+ impl_trait_fn : Some ( fn_def_id) ,
1178+ } ) ;
1179+ let exist_ty_id = lctx. lower_node_id ( exist_ty_node_id) ;
1180+ // Generate an `existential type Foo: Trait;` declaration
1181+ trace ! ( "creating existential type with id {:#?}" , exist_ty_id) ;
1182+ // Set the name to `impl Bound1 + Bound2`
1183+ let exist_ty_name = Symbol :: intern ( & pprust:: ty_to_string ( t) ) ;
1184+
1185+ trace ! ( "exist ty def index: {:#?}" , exist_ty_def_index) ;
1186+ let exist_ty_item = hir:: Item {
1187+ id : exist_ty_id. node_id ,
1188+ hir_id : exist_ty_id. hir_id ,
1189+ name : exist_ty_name,
1190+ attrs : Default :: default ( ) ,
1191+ node : exist_ty_item_kind,
1192+ vis : hir:: Visibility :: Inherited ,
1193+ span : exist_ty_span,
1194+ } ;
1195+
1196+ // Insert the item into the global list. This usually happens
1197+ // automatically for all AST items. But this existential type item
1198+ // does not actually exist in the AST.
1199+ lctx. items . insert ( exist_ty_id. node_id , exist_ty_item) ;
1200+
1201+ // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
1202+ hir:: TyImplTraitExistential (
1203+ hir:: ItemId {
1204+ id : exist_ty_id. node_id
1205+ } ,
1206+ DefId :: local ( exist_ty_def_index) ,
1207+ lifetimes,
1208+ )
1209+ } )
11311210 }
11321211 ImplTraitContext :: Universal ( def_id) => {
11331212 let def_node_id = self . next_id ( ) . node_id ;
@@ -1136,7 +1215,7 @@ impl<'a> LoweringContext<'a> {
11361215 let def_index = self . resolver . definitions ( ) . create_def_with_parent (
11371216 def_id. index ,
11381217 def_node_id,
1139- DefPathData :: ImplTrait ,
1218+ DefPathData :: UniversalImplTrait ,
11401219 DefIndexAddressSpace :: High ,
11411220 Mark :: root ( ) ,
11421221 span,
@@ -1191,6 +1270,7 @@ impl<'a> LoweringContext<'a> {
11911270
11921271 fn lifetimes_from_impl_trait_bounds (
11931272 & mut self ,
1273+ exist_ty_id : NodeId ,
11941274 parent_index : DefIndex ,
11951275 bounds : & hir:: TyParamBounds ,
11961276 ) -> ( HirVec < hir:: Lifetime > , HirVec < hir:: GenericParam > ) {
@@ -1200,6 +1280,7 @@ impl<'a> LoweringContext<'a> {
12001280 struct ImplTraitLifetimeCollector < ' r , ' a : ' r > {
12011281 context : & ' r mut LoweringContext < ' a > ,
12021282 parent : DefIndex ,
1283+ exist_ty_id : NodeId ,
12031284 collect_elided_lifetimes : bool ,
12041285 currently_bound_lifetimes : Vec < hir:: LifetimeName > ,
12051286 already_defined_lifetimes : HashSet < hir:: LifetimeName > ,
@@ -1294,7 +1375,11 @@ impl<'a> LoweringContext<'a> {
12941375 name,
12951376 } ) ;
12961377
1297- let def_node_id = self . context . next_id ( ) . node_id ;
1378+ // We need to manually create the ids here, because the
1379+ // definitions will go into the explicit `existential type`
1380+ // declaration and thus need to have their owner set to that item
1381+ let def_node_id = self . context . sess . next_node_id ( ) ;
1382+ let _ = self . context . lower_node_id_with_owner ( def_node_id, self . exist_ty_id ) ;
12981383 self . context . resolver . definitions ( ) . create_def_with_parent (
12991384 self . parent ,
13001385 def_node_id,
@@ -1306,7 +1391,7 @@ impl<'a> LoweringContext<'a> {
13061391 let def_lifetime = hir:: Lifetime {
13071392 id : def_node_id,
13081393 span : lifetime. span ,
1309- name : name ,
1394+ name,
13101395 } ;
13111396 self . output_lifetime_params
13121397 . push ( hir:: GenericParam :: Lifetime ( hir:: LifetimeDef {
@@ -1322,6 +1407,7 @@ impl<'a> LoweringContext<'a> {
13221407 let mut lifetime_collector = ImplTraitLifetimeCollector {
13231408 context : self ,
13241409 parent : parent_index,
1410+ exist_ty_id,
13251411 collect_elided_lifetimes : true ,
13261412 currently_bound_lifetimes : Vec :: new ( ) ,
13271413 already_defined_lifetimes : HashSet :: new ( ) ,
@@ -1759,8 +1845,8 @@ impl<'a> LoweringContext<'a> {
17591845 . collect ( ) ,
17601846 output : match decl. output {
17611847 FunctionRetTy :: Ty ( ref ty) => match fn_def_id {
1762- Some ( _ ) if impl_trait_return_allow => {
1763- hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Existential ) )
1848+ Some ( def_id ) if impl_trait_return_allow => {
1849+ hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Existential ( def_id ) ) )
17641850 }
17651851 _ => hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Disallowed ) ) ,
17661852 } ,
0 commit comments