@@ -1322,7 +1322,88 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
13221322 check_packed ( tcx, span, def_id) ;
13231323}
13241324
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".
13251327fn 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+ ) {
13261407 if let Err ( partially_expanded_type) = tcx. try_expand_impl_trait_type ( def_id, substs) {
13271408 let mut err = struct_span_err ! (
13281409 tcx. sess, span, E0720 ,
0 commit comments