@@ -1315,7 +1315,88 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
1315
1315
check_packed ( tcx, span, def_id) ;
1316
1316
}
1317
1317
1318
+ /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
1319
+ /// projections that would result in "inheriting lifetimes".
1318
1320
fn check_opaque < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : DefId , substs : SubstsRef < ' tcx > , span : Span ) {
1321
+ check_opaque_for_inheriting_lifetimes ( tcx, def_id, span) ;
1322
+ check_opaque_for_cycles ( tcx, def_id, substs, span) ;
1323
+ }
1324
+
1325
+ /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
1326
+ /// in "inheriting lifetimes".
1327
+ fn check_opaque_for_inheriting_lifetimes (
1328
+ tcx : TyCtxt < ' tcx > ,
1329
+ def_id : DefId ,
1330
+ span : Span ,
1331
+ ) {
1332
+ let item = tcx. hir ( ) . expect_item (
1333
+ tcx. hir ( ) . as_local_hir_id ( def_id) . expect ( "existential type is not local" ) ) ;
1334
+ debug ! ( "check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}" ,
1335
+ def_id, span, item) ;
1336
+
1337
+ #[ derive( Debug ) ]
1338
+ struct ProhibitOpaqueVisitor < ' tcx > {
1339
+ opaque_identity_ty : Ty < ' tcx > ,
1340
+ generics : & ' tcx ty:: Generics ,
1341
+ } ;
1342
+
1343
+ impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for ProhibitOpaqueVisitor < ' tcx > {
1344
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
1345
+ debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}" , t) ;
1346
+ if t == self . opaque_identity_ty { false } else { t. super_visit_with ( self ) }
1347
+ }
1348
+
1349
+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> bool {
1350
+ debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}" , r) ;
1351
+ if let RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion { index, .. } ) = r {
1352
+ return * index < self . generics . parent_count as u32 ;
1353
+ }
1354
+
1355
+ r. super_visit_with ( self )
1356
+ }
1357
+ }
1358
+
1359
+ let prohibit_opaque = match item. node {
1360
+ ItemKind :: Existential ( hir:: ExistTy { origin : hir:: ExistTyOrigin :: AsyncFn , .. } ) |
1361
+ ItemKind :: Existential ( hir:: ExistTy { origin : hir:: ExistTyOrigin :: ReturnImplTrait , .. } ) => {
1362
+ let mut visitor = ProhibitOpaqueVisitor {
1363
+ opaque_identity_ty : tcx. mk_opaque (
1364
+ def_id, InternalSubsts :: identity_for_item ( tcx, def_id) ) ,
1365
+ generics : tcx. generics_of ( def_id) ,
1366
+ } ;
1367
+ debug ! ( "check_opaque_for_inheriting_lifetimes: visitor={:?}" , visitor) ;
1368
+
1369
+ tcx. predicates_of ( def_id) . predicates . iter ( ) . any (
1370
+ |( predicate, _) | predicate. visit_with ( & mut visitor) )
1371
+ } ,
1372
+ _ => false ,
1373
+ } ;
1374
+
1375
+ debug ! ( "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}" , prohibit_opaque) ;
1376
+ if prohibit_opaque {
1377
+ let is_async = match item. node {
1378
+ ItemKind :: Existential ( hir:: ExistTy { origin, .. } ) => match origin {
1379
+ hir:: ExistTyOrigin :: AsyncFn => true ,
1380
+ _ => false ,
1381
+ } ,
1382
+ _ => unreachable ! ( ) ,
1383
+ } ;
1384
+
1385
+ tcx. sess . span_err ( span, & format ! (
1386
+ "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
1387
+ a parent scope",
1388
+ if is_async { "async fn" } else { "impl Trait" } ,
1389
+ ) ) ;
1390
+ }
1391
+ }
1392
+
1393
+ /// Checks that an opaque type does not contain cycles.
1394
+ fn check_opaque_for_cycles < ' tcx > (
1395
+ tcx : TyCtxt < ' tcx > ,
1396
+ def_id : DefId ,
1397
+ substs : SubstsRef < ' tcx > ,
1398
+ span : Span ,
1399
+ ) {
1319
1400
if let Err ( partially_expanded_type) = tcx. try_expand_impl_trait_type ( def_id, substs) {
1320
1401
let mut err = struct_span_err ! (
1321
1402
tcx. sess, span, E0720 ,
0 commit comments