@@ -462,39 +462,25 @@ pub(super) fn check_opaque<'tcx>(
462462
463463/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
464464/// in "inheriting lifetimes".
465+ #[ instrument( skip( tcx, span) ) ]
465466pub ( super ) fn check_opaque_for_inheriting_lifetimes (
466467 tcx : TyCtxt < ' tcx > ,
467468 def_id : LocalDefId ,
468469 span : Span ,
469470) {
470471 let item = tcx. hir ( ) . expect_item ( tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ) ;
471- debug ! (
472- "check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}" ,
473- def_id, span, item
474- ) ;
475-
476- #[ derive( Debug ) ]
477- struct ProhibitOpaqueVisitor < ' tcx > {
478- opaque_identity_ty : Ty < ' tcx > ,
479- generics : & ' tcx ty:: Generics ,
480- }
472+ debug ! ( ?item, ?span) ;
481473
482- impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for ProhibitOpaqueVisitor < ' tcx > {
483- type BreakTy = Option < Ty < ' tcx > > ;
484-
485- fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
486- debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}" , t) ;
487- if t != self . opaque_identity_ty && t. super_visit_with ( self ) . is_break ( ) {
488- return ControlFlow :: Break ( Some ( t) ) ;
489- }
490- ControlFlow :: CONTINUE
491- }
474+ struct FoundParentLifetime ;
475+ struct FindParentLifetimeVisitor < ' tcx > ( & ' tcx ty:: Generics ) ;
476+ impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for FindParentLifetimeVisitor < ' tcx > {
477+ type BreakTy = FoundParentLifetime ;
492478
493479 fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
494- debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}" , r) ;
480+ debug ! ( "FindParentLifetimeVisitor: r={:?}" , r) ;
495481 if let RegionKind :: ReEarlyBound ( ty:: EarlyBoundRegion { index, .. } ) = r {
496- if * index < self . generics . parent_count as u32 {
497- return ControlFlow :: Break ( None ) ;
482+ if * index < self . 0 . parent_count as u32 {
483+ return ControlFlow :: Break ( FoundParentLifetime ) ;
498484 } else {
499485 return ControlFlow :: CONTINUE ;
500486 }
@@ -505,7 +491,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
505491
506492 fn visit_const ( & mut self , c : & ' tcx ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
507493 if let ty:: ConstKind :: Unevaluated ( ..) = c. val {
508- // FIXME(#72219) We currenctly don't detect lifetimes within substs
494+ // FIXME(#72219) We currently don't detect lifetimes within substs
509495 // which would violate this check. Even though the particular substitution is not used
510496 // within the const, this should still be fixed.
511497 return ControlFlow :: CONTINUE ;
@@ -514,6 +500,26 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
514500 }
515501 }
516502
503+ #[ derive( Debug ) ]
504+ struct ProhibitOpaqueVisitor < ' tcx > {
505+ opaque_identity_ty : Ty < ' tcx > ,
506+ generics : & ' tcx ty:: Generics ,
507+ }
508+
509+ impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for ProhibitOpaqueVisitor < ' tcx > {
510+ type BreakTy = Ty < ' tcx > ;
511+
512+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
513+ debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}" , t) ;
514+ if t == self . opaque_identity_ty {
515+ ControlFlow :: CONTINUE
516+ } else {
517+ t. super_visit_with ( & mut FindParentLifetimeVisitor ( self . generics ) )
518+ . map_break ( |FoundParentLifetime | t)
519+ }
520+ }
521+ }
522+
517523 if let ItemKind :: OpaqueTy ( hir:: OpaqueTy {
518524 origin : hir:: OpaqueTyOrigin :: AsyncFn | hir:: OpaqueTyOrigin :: FnReturn ,
519525 ..
@@ -555,14 +561,12 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
555561
556562 if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( span) {
557563 if snippet == "Self" {
558- if let Some ( ty) = ty {
559- err. span_suggestion (
560- span,
561- "consider spelling out the type instead" ,
562- format ! ( "{:?}" , ty) ,
563- Applicability :: MaybeIncorrect ,
564- ) ;
565- }
564+ err. span_suggestion (
565+ span,
566+ "consider spelling out the type instead" ,
567+ format ! ( "{:?}" , ty) ,
568+ Applicability :: MaybeIncorrect ,
569+ ) ;
566570 }
567571 }
568572 err. emit ( ) ;
0 commit comments