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