@@ -230,6 +230,13 @@ enum Scope<'a> {
230
230
/// In some cases not allowing late bounds allows us to avoid ICEs.
231
231
/// This is almost ways set to true.
232
232
allow_late_bound : bool ,
233
+
234
+ /// If this binder comes from a where clause, specify how it was created.
235
+ /// This is used to diagnose inaccessible lifetimes in APIT:
236
+ /// ```ignore (illustrative)
237
+ /// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
238
+ /// ```
239
+ where_bound_origin : Option < hir:: PredicateOrigin > ,
233
240
} ,
234
241
235
242
/// Lifetimes introduced by a fn are scoped to the call-site for that fn,
@@ -301,8 +308,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
301
308
opaque_type_parent,
302
309
scope_type,
303
310
hir_id,
304
- s : _,
305
311
allow_late_bound,
312
+ where_bound_origin,
313
+ s : _,
306
314
} => f
307
315
. debug_struct ( "Binder" )
308
316
. field ( "lifetimes" , lifetimes)
@@ -311,8 +319,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
311
319
. field ( "opaque_type_parent" , opaque_type_parent)
312
320
. field ( "scope_type" , scope_type)
313
321
. field ( "hir_id" , hir_id)
314
- . field ( "s" , & ".." )
315
322
. field ( "allow_late_bound" , allow_late_bound)
323
+ . field ( "where_bound_origin" , where_bound_origin)
324
+ . field ( "s" , & ".." )
316
325
. finish ( ) ,
317
326
Scope :: Body { id, s : _ } => {
318
327
f. debug_struct ( "Body" ) . field ( "id" , id) . field ( "s" , & ".." ) . finish ( )
@@ -701,6 +710,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
701
710
opaque_type_parent : false ,
702
711
scope_type : BinderScopeType :: Normal ,
703
712
allow_late_bound : true ,
713
+ where_bound_origin : None ,
704
714
} ;
705
715
self . with ( scope, move |_old_scope, this| {
706
716
intravisit:: walk_fn ( this, fk, fd, b, s, hir_id)
@@ -829,6 +839,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
829
839
scope_type : BinderScopeType :: Normal ,
830
840
s : ROOT_SCOPE ,
831
841
allow_late_bound : false ,
842
+ where_bound_origin : None ,
832
843
} ;
833
844
self . with ( scope, |old_scope, this| {
834
845
this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -896,6 +907,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
896
907
opaque_type_parent : false ,
897
908
scope_type : BinderScopeType :: Normal ,
898
909
allow_late_bound : true ,
910
+ where_bound_origin : None ,
899
911
} ;
900
912
self . with ( scope, |old_scope, this| {
901
913
// a bare fn has no bounds, so everything
@@ -1091,6 +1103,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1091
1103
opaque_type_parent : false ,
1092
1104
scope_type : BinderScopeType :: Normal ,
1093
1105
allow_late_bound : false ,
1106
+ where_bound_origin : None ,
1094
1107
} ;
1095
1108
this. with ( scope, |_old_scope, this| {
1096
1109
this. visit_generics ( generics) ;
@@ -1112,6 +1125,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1112
1125
opaque_type_parent : false ,
1113
1126
scope_type : BinderScopeType :: Normal ,
1114
1127
allow_late_bound : false ,
1128
+ where_bound_origin : None ,
1115
1129
} ;
1116
1130
self . with ( scope, |_old_scope, this| {
1117
1131
let scope = Scope :: TraitRefBoundary { s : this. scope } ;
@@ -1172,6 +1186,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1172
1186
opaque_type_parent : true ,
1173
1187
scope_type : BinderScopeType :: Normal ,
1174
1188
allow_late_bound : false ,
1189
+ where_bound_origin : None ,
1175
1190
} ;
1176
1191
self . with ( scope, |old_scope, this| {
1177
1192
this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -1242,6 +1257,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1242
1257
opaque_type_parent : true ,
1243
1258
scope_type : BinderScopeType :: Normal ,
1244
1259
allow_late_bound : true ,
1260
+ where_bound_origin : None ,
1245
1261
} ;
1246
1262
self . with ( scope, |old_scope, this| {
1247
1263
this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -1356,6 +1372,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1356
1372
ref bounded_ty,
1357
1373
bounds,
1358
1374
ref bound_generic_params,
1375
+ origin,
1359
1376
..
1360
1377
} ) => {
1361
1378
let ( lifetimes, binders) : ( FxIndexMap < hir:: ParamName , Region > , Vec < _ > ) =
@@ -1387,6 +1404,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1387
1404
opaque_type_parent : false ,
1388
1405
scope_type : BinderScopeType :: Normal ,
1389
1406
allow_late_bound : true ,
1407
+ where_bound_origin : Some ( origin) ,
1390
1408
} ;
1391
1409
this. with ( scope, |old_scope, this| {
1392
1410
this. check_lifetime_params ( old_scope, & bound_generic_params) ;
@@ -1461,6 +1479,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1461
1479
opaque_type_parent : false ,
1462
1480
scope_type,
1463
1481
allow_late_bound : true ,
1482
+ where_bound_origin : None ,
1464
1483
} ;
1465
1484
self . with ( scope, |_, this| {
1466
1485
intravisit:: walk_param_bound ( this, bound) ;
@@ -1514,6 +1533,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1514
1533
opaque_type_parent : false ,
1515
1534
scope_type,
1516
1535
allow_late_bound : true ,
1536
+ where_bound_origin : None ,
1517
1537
} ;
1518
1538
self . with ( scope, |old_scope, this| {
1519
1539
this. check_lifetime_params ( old_scope, & trait_ref. bound_generic_params ) ;
@@ -2207,6 +2227,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2207
2227
track_lifetime_uses : false ,
2208
2228
scope_type : BinderScopeType :: Normal ,
2209
2229
allow_late_bound : true ,
2230
+ where_bound_origin : None ,
2210
2231
} ;
2211
2232
self . with ( scope, move |old_scope, this| {
2212
2233
this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -2321,12 +2342,49 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2321
2342
}
2322
2343
2323
2344
self . insert_lifetime ( lifetime_ref, def) ;
2324
- } else {
2325
- self . tcx . sess . delay_span_bug (
2326
- lifetime_ref. span ,
2327
- & format ! ( "Could not resolve {:?} in scope {:#?}" , lifetime_ref, self . scope, ) ,
2328
- ) ;
2345
+ return ;
2346
+ }
2347
+
2348
+ // We may fail to resolve higher-ranked lifetimes that are mentionned by APIT.
2349
+ // AST-based resolution does not care for impl-trait desugaring, which are the
2350
+ // responibility of lowering. This may create a mismatch between the resolution
2351
+ // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
2352
+ // ```
2353
+ // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
2354
+ // ```
2355
+ //
2356
+ // In such case, walk back the binders to diagnose it properly.
2357
+ let mut scope = self . scope ;
2358
+ loop {
2359
+ match * scope {
2360
+ Scope :: Binder {
2361
+ where_bound_origin : Some ( hir:: PredicateOrigin :: ImplTrait ) , ..
2362
+ } => {
2363
+ self . tcx
2364
+ . sess
2365
+ . struct_span_err (
2366
+ lifetime_ref. span ,
2367
+ "`impl Trait` can only mention lifetimes bound at the fn or impl level" ,
2368
+ )
2369
+ . emit ( ) ;
2370
+ return ;
2371
+ }
2372
+ Scope :: Root => break ,
2373
+ Scope :: Binder { s, .. }
2374
+ | Scope :: Body { s, .. }
2375
+ | Scope :: Elision { s, .. }
2376
+ | Scope :: ObjectLifetimeDefault { s, .. }
2377
+ | Scope :: Supertrait { s, .. }
2378
+ | Scope :: TraitRefBoundary { s, .. } => {
2379
+ scope = s;
2380
+ }
2381
+ }
2329
2382
}
2383
+
2384
+ self . tcx . sess . delay_span_bug (
2385
+ lifetime_ref. span ,
2386
+ & format ! ( "Could not resolve {:?} in scope {:#?}" , lifetime_ref, self . scope, ) ,
2387
+ ) ;
2330
2388
}
2331
2389
2332
2390
fn visit_segment_args (
0 commit comments