@@ -179,7 +179,9 @@ enum ImplTraitContext {
179
179
/// Treat `impl Trait` as shorthand for a new universal existential parameter.
180
180
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
181
181
/// 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 ) ,
183
185
184
186
/// `impl Trait` is not accepted in this position.
185
187
Disallowed ,
@@ -235,6 +237,7 @@ enum ParamMode {
235
237
Optional ,
236
238
}
237
239
240
+ #[ derive( Debug ) ]
238
241
struct LoweredNodeId {
239
242
node_id : NodeId ,
240
243
hir_id : hir:: HirId ,
@@ -485,16 +488,16 @@ impl<'a> LoweringContext<'a> {
485
488
}
486
489
}
487
490
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
489
492
where
490
- F : FnOnce ( & mut Self ) ,
493
+ F : FnOnce ( & mut Self ) -> T ,
491
494
{
492
495
let counter = self . item_local_id_counters
493
496
. insert ( owner, HIR_ID_COUNTER_LOCKED )
494
497
. unwrap ( ) ;
495
498
let def_index = self . resolver . definitions ( ) . opt_def_index ( owner) . unwrap ( ) ;
496
499
self . current_hir_id_owner . push ( ( def_index, counter) ) ;
497
- f ( self ) ;
500
+ let ret = f ( self ) ;
498
501
let ( new_def_index, new_counter) = self . current_hir_id_owner . pop ( ) . unwrap ( ) ;
499
502
500
503
debug_assert ! ( def_index == new_def_index) ;
@@ -504,6 +507,7 @@ impl<'a> LoweringContext<'a> {
504
507
. insert ( owner, new_counter)
505
508
. unwrap ( ) ;
506
509
debug_assert ! ( prev == HIR_ID_COUNTER_LOCKED ) ;
510
+ ret
507
511
}
508
512
509
513
/// This method allocates a new HirId for the given NodeId and stores it in
@@ -527,7 +531,10 @@ impl<'a> LoweringContext<'a> {
527
531
528
532
fn lower_node_id_with_owner ( & mut self , ast_node_id : NodeId , owner : NodeId ) -> LoweredNodeId {
529
533
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" ) ;
531
538
let local_id = * local_id_counter;
532
539
533
540
// We want to be sure not to modify the counter in the map while it
@@ -536,7 +543,12 @@ impl<'a> LoweringContext<'a> {
536
543
debug_assert ! ( local_id != HIR_ID_COUNTER_LOCKED ) ;
537
544
538
545
* 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") ;
540
552
541
553
hir:: HirId {
542
554
owner : def_index,
@@ -1108,26 +1120,93 @@ impl<'a> LoweringContext<'a> {
1108
1120
TyKind :: ImplTrait ( ref bounds) => {
1109
1121
let span = t. span ;
1110
1122
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
+ ) ;
1116
1139
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 {
1119
1168
generics : hir:: Generics {
1120
1169
params : lifetime_defs,
1121
1170
where_clause : hir:: WhereClause {
1122
- id : self . next_id ( ) . node_id ,
1171
+ id : lctx . next_id ( ) . node_id ,
1123
1172
predicates : Vec :: new ( ) . into ( ) ,
1124
1173
} ,
1125
1174
span,
1126
1175
} ,
1127
1176
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
+ } )
1131
1210
}
1132
1211
ImplTraitContext :: Universal ( def_id) => {
1133
1212
let def_node_id = self . next_id ( ) . node_id ;
@@ -1136,7 +1215,7 @@ impl<'a> LoweringContext<'a> {
1136
1215
let def_index = self . resolver . definitions ( ) . create_def_with_parent (
1137
1216
def_id. index ,
1138
1217
def_node_id,
1139
- DefPathData :: ImplTrait ,
1218
+ DefPathData :: UniversalImplTrait ,
1140
1219
DefIndexAddressSpace :: High ,
1141
1220
Mark :: root ( ) ,
1142
1221
span,
@@ -1191,6 +1270,7 @@ impl<'a> LoweringContext<'a> {
1191
1270
1192
1271
fn lifetimes_from_impl_trait_bounds (
1193
1272
& mut self ,
1273
+ exist_ty_id : NodeId ,
1194
1274
parent_index : DefIndex ,
1195
1275
bounds : & hir:: TyParamBounds ,
1196
1276
) -> ( HirVec < hir:: Lifetime > , HirVec < hir:: GenericParam > ) {
@@ -1200,6 +1280,7 @@ impl<'a> LoweringContext<'a> {
1200
1280
struct ImplTraitLifetimeCollector < ' r , ' a : ' r > {
1201
1281
context : & ' r mut LoweringContext < ' a > ,
1202
1282
parent : DefIndex ,
1283
+ exist_ty_id : NodeId ,
1203
1284
collect_elided_lifetimes : bool ,
1204
1285
currently_bound_lifetimes : Vec < hir:: LifetimeName > ,
1205
1286
already_defined_lifetimes : HashSet < hir:: LifetimeName > ,
@@ -1294,7 +1375,11 @@ impl<'a> LoweringContext<'a> {
1294
1375
name,
1295
1376
} ) ;
1296
1377
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 ) ;
1298
1383
self . context . resolver . definitions ( ) . create_def_with_parent (
1299
1384
self . parent ,
1300
1385
def_node_id,
@@ -1306,7 +1391,7 @@ impl<'a> LoweringContext<'a> {
1306
1391
let def_lifetime = hir:: Lifetime {
1307
1392
id : def_node_id,
1308
1393
span : lifetime. span ,
1309
- name : name ,
1394
+ name,
1310
1395
} ;
1311
1396
self . output_lifetime_params
1312
1397
. push ( hir:: GenericParam :: Lifetime ( hir:: LifetimeDef {
@@ -1322,6 +1407,7 @@ impl<'a> LoweringContext<'a> {
1322
1407
let mut lifetime_collector = ImplTraitLifetimeCollector {
1323
1408
context : self ,
1324
1409
parent : parent_index,
1410
+ exist_ty_id,
1325
1411
collect_elided_lifetimes : true ,
1326
1412
currently_bound_lifetimes : Vec :: new ( ) ,
1327
1413
already_defined_lifetimes : HashSet :: new ( ) ,
@@ -1759,8 +1845,8 @@ impl<'a> LoweringContext<'a> {
1759
1845
. collect ( ) ,
1760
1846
output : match decl. output {
1761
1847
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 ) ) )
1764
1850
}
1765
1851
_ => hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Disallowed ) ) ,
1766
1852
} ,
0 commit comments