@@ -1325,12 +1325,94 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
13251325 check_packed ( tcx, span, def_id) ;
13261326}
13271327
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".
13281330fn check_opaque < ' tcx > (
13291331 tcx : TyCtxt < ' tcx > ,
13301332 def_id : DefId ,
13311333 substs : SubstsRef < ' tcx > ,
13321334 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 ,
13341416) {
13351417 if let Err ( partially_expanded_type) = tcx. try_expand_impl_trait_type ( def_id, substs) {
13361418 if let hir:: OpaqueTyOrigin :: AsyncFn = origin {
0 commit comments