@@ -240,6 +240,7 @@ fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
240240 }
241241 check_opaque_meets_bounds ( tcx, item. owner_id . def_id , substs, span, & origin) ;
242242}
243+
243244/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
244245/// in "inheriting lifetimes".
245246#[ instrument( level = "debug" , skip( tcx, span) ) ]
@@ -251,15 +252,19 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
251252 let item = tcx. hir ( ) . expect_item ( def_id) ;
252253 debug ! ( ?item, ?span) ;
253254
255+ #[ derive( Debug ) ]
254256 struct FoundParentLifetime ;
255- struct FindParentLifetimeVisitor < ' tcx > ( & ' tcx ty:: Generics ) ;
257+ struct FindParentLifetimeVisitor < ' tcx > {
258+ tcx : TyCtxt < ' tcx > ,
259+ parent_count : u32 ,
260+ }
256261 impl < ' tcx > ty:: visit:: TypeVisitor < ' tcx > for FindParentLifetimeVisitor < ' tcx > {
257262 type BreakTy = FoundParentLifetime ;
258263
264+ #[ instrument( level = "trace" , skip( self ) , ret) ]
259265 fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
260- debug ! ( "FindParentLifetimeVisitor: r={:?}" , r) ;
261266 if let ty:: ReEarlyBound ( ty:: EarlyBoundRegion { index, .. } ) = * r {
262- if index < self . 0 . parent_count as u32 {
267+ if index < self . parent_count {
263268 return ControlFlow :: Break ( FoundParentLifetime ) ;
264269 } else {
265270 return ControlFlow :: CONTINUE ;
@@ -269,6 +274,63 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
269274 r. super_visit_with ( self )
270275 }
271276
277+ #[ instrument( level = "trace" , skip( self ) , ret) ]
278+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
279+ // We're only interested in types involving regions
280+ if !ty. flags ( ) . intersects ( ty:: TypeFlags :: HAS_FREE_REGIONS ) {
281+ return ControlFlow :: CONTINUE ;
282+ }
283+
284+ match ty. kind ( ) {
285+ ty:: Closure ( _, ref substs) => {
286+ // Skip lifetime parameters of the enclosing item(s)
287+
288+ substs. as_closure ( ) . tupled_upvars_ty ( ) . visit_with ( self ) ?;
289+ substs. as_closure ( ) . sig_as_fn_ptr_ty ( ) . visit_with ( self ) ?;
290+ }
291+
292+ ty:: Generator ( _, ref substs, _) => {
293+ // Skip lifetime parameters of the enclosing item(s)
294+ // Also skip the witness type, because that has no free regions.
295+
296+ substs. as_generator ( ) . tupled_upvars_ty ( ) . visit_with ( self ) ?;
297+ substs. as_generator ( ) . return_ty ( ) . visit_with ( self ) ?;
298+ substs. as_generator ( ) . yield_ty ( ) . visit_with ( self ) ?;
299+ substs. as_generator ( ) . resume_ty ( ) . visit_with ( self ) ?;
300+ }
301+
302+ ty:: Opaque ( def_id, ref substs) => {
303+ // Skip lifetime paramters that are not captures.
304+ let variances = self . tcx . variances_of ( * def_id) ;
305+
306+ for ( v, s) in std:: iter:: zip ( variances, substs. iter ( ) ) {
307+ if * v != ty:: Variance :: Bivariant {
308+ s. visit_with ( self ) ?;
309+ }
310+ }
311+ }
312+
313+ ty:: Projection ( proj)
314+ if self . tcx . def_kind ( proj. item_def_id ) == DefKind :: ImplTraitPlaceholder =>
315+ {
316+ // Skip lifetime paramters that are not captures.
317+ let variances = self . tcx . variances_of ( proj. item_def_id ) ;
318+
319+ for ( v, s) in std:: iter:: zip ( variances, proj. substs . iter ( ) ) {
320+ if * v != ty:: Variance :: Bivariant {
321+ s. visit_with ( self ) ?;
322+ }
323+ }
324+ }
325+
326+ _ => {
327+ ty. super_visit_with ( self ) ?;
328+ }
329+ }
330+
331+ ControlFlow :: CONTINUE
332+ }
333+
272334 fn visit_const ( & mut self , c : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
273335 if let ty:: ConstKind :: Unevaluated ( ..) = c. kind ( ) {
274336 // FIXME(#72219) We currently don't detect lifetimes within substs
@@ -291,12 +353,15 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
291353 type BreakTy = Ty < ' tcx > ;
292354
293355 fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
294- debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}" , t ) ;
356+ debug ! ( ?t , "root_visit_ty" ) ;
295357 if t == self . opaque_identity_ty {
296358 ControlFlow :: CONTINUE
297359 } else {
298- t. super_visit_with ( & mut FindParentLifetimeVisitor ( self . generics ) )
299- . map_break ( |FoundParentLifetime | t)
360+ t. visit_with ( & mut FindParentLifetimeVisitor {
361+ tcx : self . tcx ,
362+ parent_count : self . generics . parent_count as u32 ,
363+ } )
364+ . map_break ( |FoundParentLifetime | t)
300365 }
301366 }
302367 }
@@ -329,14 +394,18 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
329394
330395 if let ItemKind :: OpaqueTy ( hir:: OpaqueTy {
331396 origin : hir:: OpaqueTyOrigin :: AsyncFn ( ..) | hir:: OpaqueTyOrigin :: FnReturn ( ..) ,
397+ in_trait,
332398 ..
333399 } ) = item. kind
334400 {
401+ let substs = InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ;
402+ let opaque_identity_ty = if in_trait {
403+ tcx. mk_projection ( def_id. to_def_id ( ) , substs)
404+ } else {
405+ tcx. mk_opaque ( def_id. to_def_id ( ) , substs)
406+ } ;
335407 let mut visitor = ProhibitOpaqueVisitor {
336- opaque_identity_ty : tcx. mk_opaque (
337- def_id. to_def_id ( ) ,
338- InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ,
339- ) ,
408+ opaque_identity_ty,
340409 generics : tcx. generics_of ( def_id) ,
341410 tcx,
342411 selftys : vec ! [ ] ,
@@ -345,10 +414,6 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
345414 . explicit_item_bounds ( def_id)
346415 . iter ( )
347416 . try_for_each ( |( predicate, _) | predicate. visit_with ( & mut visitor) ) ;
348- debug ! (
349- "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor.opaque_identity_ty={:?}, visitor.generics={:?}" ,
350- prohibit_opaque, visitor. opaque_identity_ty, visitor. generics
351- ) ;
352417
353418 if let Some ( ty) = prohibit_opaque. break_value ( ) {
354419 visitor. visit_item ( & item) ;
0 commit comments