@@ -182,7 +182,9 @@ enum ImplTraitContext {
182
182
/// Treat `impl Trait` as shorthand for a new universal existential parameter.
183
183
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
184
184
/// 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 ) ,
186
188
187
189
/// `impl Trait` is not accepted in this position.
188
190
Disallowed ,
@@ -238,6 +240,7 @@ enum ParamMode {
238
240
Optional ,
239
241
}
240
242
243
+ #[ derive( Debug ) ]
241
244
struct LoweredNodeId {
242
245
node_id : NodeId ,
243
246
hir_id : hir:: HirId ,
@@ -488,16 +491,16 @@ impl<'a> LoweringContext<'a> {
488
491
}
489
492
}
490
493
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
492
495
where
493
- F : FnOnce ( & mut Self ) ,
496
+ F : FnOnce ( & mut Self ) -> T ,
494
497
{
495
498
let counter = self . item_local_id_counters
496
499
. insert ( owner, HIR_ID_COUNTER_LOCKED )
497
500
. unwrap ( ) ;
498
501
let def_index = self . resolver . definitions ( ) . opt_def_index ( owner) . unwrap ( ) ;
499
502
self . current_hir_id_owner . push ( ( def_index, counter) ) ;
500
- f ( self ) ;
503
+ let ret = f ( self ) ;
501
504
let ( new_def_index, new_counter) = self . current_hir_id_owner . pop ( ) . unwrap ( ) ;
502
505
503
506
debug_assert ! ( def_index == new_def_index) ;
@@ -507,6 +510,7 @@ impl<'a> LoweringContext<'a> {
507
510
. insert ( owner, new_counter)
508
511
. unwrap ( ) ;
509
512
debug_assert ! ( prev == HIR_ID_COUNTER_LOCKED ) ;
513
+ ret
510
514
}
511
515
512
516
/// This method allocates a new HirId for the given NodeId and stores it in
@@ -530,7 +534,10 @@ impl<'a> LoweringContext<'a> {
530
534
531
535
fn lower_node_id_with_owner ( & mut self , ast_node_id : NodeId , owner : NodeId ) -> LoweredNodeId {
532
536
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" ) ;
534
541
let local_id = * local_id_counter;
535
542
536
543
// We want to be sure not to modify the counter in the map while it
@@ -539,7 +546,12 @@ impl<'a> LoweringContext<'a> {
539
546
debug_assert ! ( local_id != HIR_ID_COUNTER_LOCKED ) ;
540
547
541
548
* 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") ;
543
555
544
556
hir:: HirId {
545
557
owner : def_index,
@@ -1120,26 +1132,93 @@ impl<'a> LoweringContext<'a> {
1120
1132
TyKind :: ImplTrait ( ref bounds) => {
1121
1133
let span = t. span ;
1122
1134
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
+ ) ;
1128
1151
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 {
1131
1180
generics : hir:: Generics {
1132
1181
params : lifetime_defs,
1133
1182
where_clause : hir:: WhereClause {
1134
- id : self . next_id ( ) . node_id ,
1183
+ id : lctx . next_id ( ) . node_id ,
1135
1184
predicates : Vec :: new ( ) . into ( ) ,
1136
1185
} ,
1137
1186
span,
1138
1187
} ,
1139
1188
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
+ } )
1143
1222
}
1144
1223
ImplTraitContext :: Universal ( def_id) => {
1145
1224
let def_node_id = self . next_id ( ) . node_id ;
@@ -1148,7 +1227,7 @@ impl<'a> LoweringContext<'a> {
1148
1227
let def_index = self . resolver . definitions ( ) . create_def_with_parent (
1149
1228
def_id. index ,
1150
1229
def_node_id,
1151
- DefPathData :: ImplTrait ,
1230
+ DefPathData :: UniversalImplTrait ,
1152
1231
DefIndexAddressSpace :: High ,
1153
1232
Mark :: root ( ) ,
1154
1233
span,
@@ -1203,6 +1282,7 @@ impl<'a> LoweringContext<'a> {
1203
1282
1204
1283
fn lifetimes_from_impl_trait_bounds (
1205
1284
& mut self ,
1285
+ exist_ty_id : NodeId ,
1206
1286
parent_index : DefIndex ,
1207
1287
bounds : & hir:: TyParamBounds ,
1208
1288
) -> ( HirVec < hir:: Lifetime > , HirVec < hir:: GenericParam > ) {
@@ -1212,6 +1292,7 @@ impl<'a> LoweringContext<'a> {
1212
1292
struct ImplTraitLifetimeCollector < ' r , ' a : ' r > {
1213
1293
context : & ' r mut LoweringContext < ' a > ,
1214
1294
parent : DefIndex ,
1295
+ exist_ty_id : NodeId ,
1215
1296
collect_elided_lifetimes : bool ,
1216
1297
currently_bound_lifetimes : Vec < hir:: LifetimeName > ,
1217
1298
already_defined_lifetimes : HashSet < hir:: LifetimeName > ,
@@ -1306,7 +1387,11 @@ impl<'a> LoweringContext<'a> {
1306
1387
name,
1307
1388
} ) ;
1308
1389
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 ) ;
1310
1395
self . context . resolver . definitions ( ) . create_def_with_parent (
1311
1396
self . parent ,
1312
1397
def_node_id,
@@ -1318,7 +1403,7 @@ impl<'a> LoweringContext<'a> {
1318
1403
let def_lifetime = hir:: Lifetime {
1319
1404
id : def_node_id,
1320
1405
span : lifetime. span ,
1321
- name : name ,
1406
+ name,
1322
1407
} ;
1323
1408
self . output_lifetime_params
1324
1409
. push ( hir:: GenericParam :: Lifetime ( hir:: LifetimeDef {
@@ -1334,6 +1419,7 @@ impl<'a> LoweringContext<'a> {
1334
1419
let mut lifetime_collector = ImplTraitLifetimeCollector {
1335
1420
context : self ,
1336
1421
parent : parent_index,
1422
+ exist_ty_id,
1337
1423
collect_elided_lifetimes : true ,
1338
1424
currently_bound_lifetimes : Vec :: new ( ) ,
1339
1425
already_defined_lifetimes : HashSet :: new ( ) ,
@@ -1772,8 +1858,8 @@ impl<'a> LoweringContext<'a> {
1772
1858
. collect ( ) ,
1773
1859
output : match decl. output {
1774
1860
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 ) ) )
1777
1863
}
1778
1864
_ => hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Disallowed ) ) ,
1779
1865
} ,
0 commit comments