@@ -182,7 +182,9 @@ enum ImplTraitContext {
182182 /// Treat `impl Trait` as shorthand for a new universal existential parameter.
183183 /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
184184 /// equivalent to a fresh existential parameter like `abstract type T; fn foo() -> T`.
185- Existential ,
185+ ///
186+ /// We store a DefId here so we can look up necessary information later
187+ Existential ( DefId ) ,
186188
187189 /// `impl Trait` is not accepted in this position.
188190 Disallowed ,
@@ -238,6 +240,7 @@ enum ParamMode {
238240 Optional ,
239241}
240242
243+ #[ derive( Debug ) ]
241244struct LoweredNodeId {
242245 node_id : NodeId ,
243246 hir_id : hir:: HirId ,
@@ -488,16 +491,16 @@ impl<'a> LoweringContext<'a> {
488491 }
489492 }
490493
491- fn with_hir_id_owner < F > ( & mut self , owner : NodeId , f : F )
494+ fn with_hir_id_owner < F , T > ( & mut self , owner : NodeId , f : F ) -> T
492495 where
493- F : FnOnce ( & mut Self ) ,
496+ F : FnOnce ( & mut Self ) -> T ,
494497 {
495498 let counter = self . item_local_id_counters
496499 . insert ( owner, HIR_ID_COUNTER_LOCKED )
497500 . unwrap ( ) ;
498501 let def_index = self . resolver . definitions ( ) . opt_def_index ( owner) . unwrap ( ) ;
499502 self . current_hir_id_owner . push ( ( def_index, counter) ) ;
500- f ( self ) ;
503+ let ret = f ( self ) ;
501504 let ( new_def_index, new_counter) = self . current_hir_id_owner . pop ( ) . unwrap ( ) ;
502505
503506 debug_assert ! ( def_index == new_def_index) ;
@@ -507,6 +510,7 @@ impl<'a> LoweringContext<'a> {
507510 . insert ( owner, new_counter)
508511 . unwrap ( ) ;
509512 debug_assert ! ( prev == HIR_ID_COUNTER_LOCKED ) ;
513+ ret
510514 }
511515
512516 /// This method allocates a new HirId for the given NodeId and stores it in
@@ -530,7 +534,10 @@ impl<'a> LoweringContext<'a> {
530534
531535 fn lower_node_id_with_owner ( & mut self , ast_node_id : NodeId , owner : NodeId ) -> LoweredNodeId {
532536 self . lower_node_id_generic ( ast_node_id, |this| {
533- let local_id_counter = this. item_local_id_counters . get_mut ( & owner) . unwrap ( ) ;
537+ let local_id_counter = this
538+ . item_local_id_counters
539+ . get_mut ( & owner)
540+ . expect ( "called lower_node_id_with_owner before allocate_hir_id_counter" ) ;
534541 let local_id = * local_id_counter;
535542
536543 // We want to be sure not to modify the counter in the map while it
@@ -539,7 +546,12 @@ impl<'a> LoweringContext<'a> {
539546 debug_assert ! ( local_id != HIR_ID_COUNTER_LOCKED ) ;
540547
541548 * local_id_counter += 1 ;
542- let def_index = this. resolver . definitions ( ) . opt_def_index ( owner) . unwrap ( ) ;
549+ let def_index = this
550+ . resolver
551+ . definitions ( )
552+ . opt_def_index ( owner)
553+ . expect ( "You forgot to call `create_def_with_parent` or are lowering node ids \
554+ that do not belong to the current owner") ;
543555
544556 hir:: HirId {
545557 owner : def_index,
@@ -1120,26 +1132,93 @@ impl<'a> LoweringContext<'a> {
11201132 TyKind :: ImplTrait ( ref bounds) => {
11211133 let span = t. span ;
11221134 match itctx {
1123- ImplTraitContext :: Existential => {
1124- let def_index = self . resolver . definitions ( ) . opt_def_index ( t. id ) . unwrap ( ) ;
1125- let hir_bounds = self . lower_bounds ( bounds, itctx) ;
1126- let ( lifetimes, lifetime_defs) =
1127- self . lifetimes_from_impl_trait_bounds ( def_index, & hir_bounds) ;
1135+ ImplTraitContext :: Existential ( fn_def_id) => {
1136+
1137+ // We need to manually repeat the code of `next_id` because the lowering
1138+ // needs to happen while the owner_id is pointing to the item itself,
1139+ // because items are their own owners
1140+ let exist_ty_node_id = self . sess . next_node_id ( ) ;
1141+
1142+ // Make sure we know that some funky desugaring has been going on here.
1143+ // This is a first: there is code in other places like for loop
1144+ // desugaring that explicitly states that we don't want to track that.
1145+ // Not tracking it makes lints in rustc and clippy very fragile as
1146+ // frequently opened issues show.
1147+ let exist_ty_span = self . allow_internal_unstable (
1148+ CompilerDesugaringKind :: ExistentialReturnType ,
1149+ t. span ,
1150+ ) ;
11281151
1129- hir:: TyImplTraitExistential (
1130- hir:: ExistTy {
1152+ // Pull a new definition from the ether
1153+ let exist_ty_def_index = self
1154+ . resolver
1155+ . definitions ( )
1156+ . create_def_with_parent (
1157+ fn_def_id. index ,
1158+ exist_ty_node_id,
1159+ DefPathData :: ExistentialImplTrait ,
1160+ DefIndexAddressSpace :: High ,
1161+ Mark :: root ( ) ,
1162+ exist_ty_span,
1163+ ) ;
1164+
1165+ // the `t` is just for printing debug messages
1166+ self . allocate_hir_id_counter ( exist_ty_node_id, t) ;
1167+
1168+ let hir_bounds = self . with_hir_id_owner ( exist_ty_node_id, |lctx| {
1169+ lctx. lower_bounds ( bounds, itctx)
1170+ } ) ;
1171+
1172+ let ( lifetimes, lifetime_defs) = self . lifetimes_from_impl_trait_bounds (
1173+ exist_ty_node_id,
1174+ exist_ty_def_index,
1175+ & hir_bounds,
1176+ ) ;
1177+
1178+ self . with_hir_id_owner ( exist_ty_node_id, |lctx| {
1179+ let exist_ty_item_kind = hir:: ItemExistential ( hir:: ExistTy {
11311180 generics : hir:: Generics {
11321181 params : lifetime_defs,
11331182 where_clause : hir:: WhereClause {
1134- id : self . next_id ( ) . node_id ,
1183+ id : lctx . next_id ( ) . node_id ,
11351184 predicates : Vec :: new ( ) . into ( ) ,
11361185 } ,
11371186 span,
11381187 } ,
11391188 bounds : hir_bounds,
1140- } ,
1141- lifetimes,
1142- )
1189+ impl_trait_fn : Some ( fn_def_id) ,
1190+ } ) ;
1191+ let exist_ty_id = lctx. lower_node_id ( exist_ty_node_id) ;
1192+ // Generate an `existential type Foo: Trait;` declaration
1193+ trace ! ( "creating existential type with id {:#?}" , exist_ty_id) ;
1194+ // Set the name to `impl Bound1 + Bound2`
1195+ let exist_ty_name = Symbol :: intern ( & pprust:: ty_to_string ( t) ) ;
1196+
1197+ trace ! ( "exist ty def index: {:#?}" , exist_ty_def_index) ;
1198+ let exist_ty_item = hir:: Item {
1199+ id : exist_ty_id. node_id ,
1200+ hir_id : exist_ty_id. hir_id ,
1201+ name : exist_ty_name,
1202+ attrs : Default :: default ( ) ,
1203+ node : exist_ty_item_kind,
1204+ vis : hir:: Visibility :: Inherited ,
1205+ span : exist_ty_span,
1206+ } ;
1207+
1208+ // Insert the item into the global list. This usually happens
1209+ // automatically for all AST items. But this existential type item
1210+ // does not actually exist in the AST.
1211+ lctx. items . insert ( exist_ty_id. node_id , exist_ty_item) ;
1212+
1213+ // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
1214+ hir:: TyImplTraitExistential (
1215+ hir:: ItemId {
1216+ id : exist_ty_id. node_id
1217+ } ,
1218+ DefId :: local ( exist_ty_def_index) ,
1219+ lifetimes,
1220+ )
1221+ } )
11431222 }
11441223 ImplTraitContext :: Universal ( def_id) => {
11451224 let def_node_id = self . next_id ( ) . node_id ;
@@ -1148,7 +1227,7 @@ impl<'a> LoweringContext<'a> {
11481227 let def_index = self . resolver . definitions ( ) . create_def_with_parent (
11491228 def_id. index ,
11501229 def_node_id,
1151- DefPathData :: ImplTrait ,
1230+ DefPathData :: UniversalImplTrait ,
11521231 DefIndexAddressSpace :: High ,
11531232 Mark :: root ( ) ,
11541233 span,
@@ -1203,6 +1282,7 @@ impl<'a> LoweringContext<'a> {
12031282
12041283 fn lifetimes_from_impl_trait_bounds (
12051284 & mut self ,
1285+ exist_ty_id : NodeId ,
12061286 parent_index : DefIndex ,
12071287 bounds : & hir:: TyParamBounds ,
12081288 ) -> ( HirVec < hir:: Lifetime > , HirVec < hir:: GenericParam > ) {
@@ -1212,6 +1292,7 @@ impl<'a> LoweringContext<'a> {
12121292 struct ImplTraitLifetimeCollector < ' r , ' a : ' r > {
12131293 context : & ' r mut LoweringContext < ' a > ,
12141294 parent : DefIndex ,
1295+ exist_ty_id : NodeId ,
12151296 collect_elided_lifetimes : bool ,
12161297 currently_bound_lifetimes : Vec < hir:: LifetimeName > ,
12171298 already_defined_lifetimes : HashSet < hir:: LifetimeName > ,
@@ -1306,7 +1387,11 @@ impl<'a> LoweringContext<'a> {
13061387 name,
13071388 } ) ;
13081389
1309- let def_node_id = self . context . next_id ( ) . node_id ;
1390+ // We need to manually create the ids here, because the
1391+ // definitions will go into the explicit `existential type`
1392+ // declaration and thus need to have their owner set to that item
1393+ let def_node_id = self . context . sess . next_node_id ( ) ;
1394+ let _ = self . context . lower_node_id_with_owner ( def_node_id, self . exist_ty_id ) ;
13101395 self . context . resolver . definitions ( ) . create_def_with_parent (
13111396 self . parent ,
13121397 def_node_id,
@@ -1318,7 +1403,7 @@ impl<'a> LoweringContext<'a> {
13181403 let def_lifetime = hir:: Lifetime {
13191404 id : def_node_id,
13201405 span : lifetime. span ,
1321- name : name ,
1406+ name,
13221407 } ;
13231408 self . output_lifetime_params
13241409 . push ( hir:: GenericParam :: Lifetime ( hir:: LifetimeDef {
@@ -1334,6 +1419,7 @@ impl<'a> LoweringContext<'a> {
13341419 let mut lifetime_collector = ImplTraitLifetimeCollector {
13351420 context : self ,
13361421 parent : parent_index,
1422+ exist_ty_id,
13371423 collect_elided_lifetimes : true ,
13381424 currently_bound_lifetimes : Vec :: new ( ) ,
13391425 already_defined_lifetimes : HashSet :: new ( ) ,
@@ -1772,8 +1858,8 @@ impl<'a> LoweringContext<'a> {
17721858 . collect ( ) ,
17731859 output : match decl. output {
17741860 FunctionRetTy :: Ty ( ref ty) => match fn_def_id {
1775- Some ( _ ) if impl_trait_return_allow => {
1776- hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Existential ) )
1861+ Some ( def_id ) if impl_trait_return_allow => {
1862+ hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Existential ( def_id ) ) )
17771863 }
17781864 _ => hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Disallowed ) ) ,
17791865 } ,
0 commit comments