@@ -207,6 +207,13 @@ enum Scope<'a> {
207
207
/// In some cases not allowing late bounds allows us to avoid ICEs.
208
208
/// This is almost ways set to true.
209
209
allow_late_bound : bool ,
210
+
211
+ /// If this binder comes from a where clause, specify how it was created.
212
+ /// This is used to diagnose inaccessible lifetimes in APIT:
213
+ /// ```ignore (illustrative)
214
+ /// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
215
+ /// ```
216
+ where_bound_origin : Option < hir:: PredicateOrigin > ,
210
217
} ,
211
218
212
219
/// Lifetimes introduced by a fn are scoped to the call-site for that fn,
@@ -277,17 +284,19 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
277
284
opaque_type_parent,
278
285
scope_type,
279
286
hir_id,
280
- s : _,
281
287
allow_late_bound,
288
+ where_bound_origin,
289
+ s : _,
282
290
} => f
283
291
. debug_struct ( "Binder" )
284
292
. field ( "lifetimes" , lifetimes)
285
293
. field ( "next_early_index" , next_early_index)
286
294
. field ( "opaque_type_parent" , opaque_type_parent)
287
295
. field ( "scope_type" , scope_type)
288
296
. field ( "hir_id" , hir_id)
289
- . field ( "s" , & ".." )
290
297
. field ( "allow_late_bound" , allow_late_bound)
298
+ . field ( "where_bound_origin" , where_bound_origin)
299
+ . field ( "s" , & ".." )
291
300
. finish ( ) ,
292
301
Scope :: Body { id, s : _ } => {
293
302
f. debug_struct ( "Body" ) . field ( "id" , id) . field ( "s" , & ".." ) . finish ( )
@@ -638,6 +647,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
638
647
opaque_type_parent : false ,
639
648
scope_type : BinderScopeType :: Normal ,
640
649
allow_late_bound : true ,
650
+ where_bound_origin : None ,
641
651
} ;
642
652
self . with ( scope, move |this| intravisit:: walk_fn ( this, fk, fd, b, s, hir_id) ) ;
643
653
}
@@ -753,6 +763,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
753
763
scope_type : BinderScopeType :: Normal ,
754
764
s : ROOT_SCOPE ,
755
765
allow_late_bound : false ,
766
+ where_bound_origin : None ,
756
767
} ;
757
768
self . with ( scope, |this| {
758
769
let scope = Scope :: TraitRefBoundary { s : this. scope } ;
@@ -818,6 +829,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
818
829
opaque_type_parent : false ,
819
830
scope_type : BinderScopeType :: Normal ,
820
831
allow_late_bound : true ,
832
+ where_bound_origin : None ,
821
833
} ;
822
834
self . with ( scope, |this| {
823
835
// a bare fn has no bounds, so everything
@@ -1006,6 +1018,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1006
1018
opaque_type_parent : false ,
1007
1019
scope_type : BinderScopeType :: Normal ,
1008
1020
allow_late_bound : false ,
1021
+ where_bound_origin : None ,
1009
1022
} ;
1010
1023
this. with ( scope, |this| {
1011
1024
this. visit_generics ( generics) ;
@@ -1026,6 +1039,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1026
1039
opaque_type_parent : false ,
1027
1040
scope_type : BinderScopeType :: Normal ,
1028
1041
allow_late_bound : false ,
1042
+ where_bound_origin : None ,
1029
1043
} ;
1030
1044
self . with ( scope, |this| {
1031
1045
let scope = Scope :: TraitRefBoundary { s : this. scope } ;
@@ -1084,6 +1098,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1084
1098
opaque_type_parent : true ,
1085
1099
scope_type : BinderScopeType :: Normal ,
1086
1100
allow_late_bound : false ,
1101
+ where_bound_origin : None ,
1087
1102
} ;
1088
1103
self . with ( scope, |this| {
1089
1104
let scope = Scope :: TraitRefBoundary { s : this. scope } ;
@@ -1151,6 +1166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1151
1166
opaque_type_parent : true ,
1152
1167
scope_type : BinderScopeType :: Normal ,
1153
1168
allow_late_bound : true ,
1169
+ where_bound_origin : None ,
1154
1170
} ;
1155
1171
self . with ( scope, |this| {
1156
1172
let scope = Scope :: TraitRefBoundary { s : this. scope } ;
@@ -1266,6 +1282,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1266
1282
ref bounded_ty,
1267
1283
bounds,
1268
1284
ref bound_generic_params,
1285
+ origin,
1269
1286
..
1270
1287
} ) => {
1271
1288
let ( lifetimes, binders) : ( FxIndexMap < LocalDefId , Region > , Vec < _ > ) =
@@ -1296,6 +1313,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1296
1313
opaque_type_parent : false ,
1297
1314
scope_type : BinderScopeType :: Normal ,
1298
1315
allow_late_bound : true ,
1316
+ where_bound_origin : Some ( origin) ,
1299
1317
} ;
1300
1318
this. with ( scope, |this| {
1301
1319
this. visit_ty ( & bounded_ty) ;
@@ -1368,6 +1386,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1368
1386
opaque_type_parent : false ,
1369
1387
scope_type,
1370
1388
allow_late_bound : true ,
1389
+ where_bound_origin : None ,
1371
1390
} ;
1372
1391
self . with ( scope, |this| {
1373
1392
intravisit:: walk_param_bound ( this, bound) ;
@@ -1420,6 +1439,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1420
1439
opaque_type_parent : false ,
1421
1440
scope_type,
1422
1441
allow_late_bound : true ,
1442
+ where_bound_origin : None ,
1423
1443
} ;
1424
1444
self . with ( scope, |this| {
1425
1445
walk_list ! ( this, visit_generic_param, trait_ref. bound_generic_params) ;
@@ -1680,6 +1700,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1680
1700
opaque_type_parent : true ,
1681
1701
scope_type : BinderScopeType :: Normal ,
1682
1702
allow_late_bound : true ,
1703
+ where_bound_origin : None ,
1683
1704
} ;
1684
1705
self . with ( scope, walk) ;
1685
1706
}
@@ -1783,12 +1804,48 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1783
1804
}
1784
1805
1785
1806
self . insert_lifetime ( lifetime_ref, def) ;
1786
- } else {
1787
- self . tcx . sess . delay_span_bug (
1788
- lifetime_ref. span ,
1789
- & format ! ( "Could not resolve {:?} in scope {:#?}" , lifetime_ref, self . scope, ) ,
1790
- ) ;
1807
+ return ;
1791
1808
}
1809
+
1810
+ // We may fail to resolve higher-ranked lifetimes that are mentionned by APIT.
1811
+ // AST-based resolution does not care for impl-trait desugaring, which are the
1812
+ // responibility of lowering. This may create a mismatch between the resolution
1813
+ // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1814
+ // ```
1815
+ // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1816
+ // ```
1817
+ //
1818
+ // In such case, walk back the binders to diagnose it properly.
1819
+ let mut scope = self . scope ;
1820
+ loop {
1821
+ match * scope {
1822
+ Scope :: Binder {
1823
+ where_bound_origin : Some ( hir:: PredicateOrigin :: ImplTrait ) , ..
1824
+ } => {
1825
+ let mut err = self . tcx . sess . struct_span_err (
1826
+ lifetime_ref. span ,
1827
+ "`impl Trait` can only mention lifetimes bound at the fn or impl level" ,
1828
+ ) ;
1829
+ err. span_note ( self . tcx . def_span ( region_def_id) , "lifetime declared here" ) ;
1830
+ err. emit ( ) ;
1831
+ return ;
1832
+ }
1833
+ Scope :: Root => break ,
1834
+ Scope :: Binder { s, .. }
1835
+ | Scope :: Body { s, .. }
1836
+ | Scope :: Elision { s, .. }
1837
+ | Scope :: ObjectLifetimeDefault { s, .. }
1838
+ | Scope :: Supertrait { s, .. }
1839
+ | Scope :: TraitRefBoundary { s, .. } => {
1840
+ scope = s;
1841
+ }
1842
+ }
1843
+ }
1844
+
1845
+ self . tcx . sess . delay_span_bug (
1846
+ lifetime_ref. span ,
1847
+ & format ! ( "Could not resolve {:?} in scope {:#?}" , lifetime_ref, self . scope, ) ,
1848
+ ) ;
1792
1849
}
1793
1850
1794
1851
fn visit_segment_args (
0 commit comments