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