@@ -492,6 +492,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
492492 } ;
493493
494494 let mut expected_captures = UnordSet :: default ( ) ;
495+ let mut shadowed_captures = UnordSet :: default ( ) ;
495496 let mut seen_params = UnordMap :: default ( ) ;
496497 let mut prev_non_lifetime_param = None ;
497498 for arg in precise_capturing_args {
@@ -530,6 +531,21 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
530531 match tcx. named_bound_var ( hir_id) {
531532 Some ( ResolvedArg :: EarlyBound ( def_id) ) => {
532533 expected_captures. insert ( def_id) ;
534+
535+ // Make sure we allow capturing these lifetimes through `Self` and
536+ // `T::Assoc` projection syntax, too. These will occur when we only
537+ // see lifetimes are captured after hir-lowering -- this aligns with
538+ // the cases that were stabilized with the `impl_trait_projection`
539+ // feature -- see <https://github.com/rust-lang/rust/pull/115659>.
540+ if let DefKind :: LifetimeParam = tcx. def_kind ( def_id)
541+ && let ty:: ReEarlyParam ( ty:: EarlyParamRegion { def_id, .. } )
542+ | ty:: ReLateParam ( ty:: LateParamRegion {
543+ bound_region : ty:: BoundRegionKind :: BrNamed ( def_id, _) ,
544+ ..
545+ } ) = * tcx. map_opaque_lifetime_to_parent_lifetime ( def_id. expect_local ( ) )
546+ {
547+ shadowed_captures. insert ( def_id) ;
548+ }
533549 }
534550 _ => {
535551 tcx. dcx ( ) . span_delayed_bug (
@@ -555,23 +571,30 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
555571 ) ;
556572 continue ;
557573 }
574+ // If a param is shadowed by a early-bound (duplicated) lifetime, then
575+ // it may or may not be captured as invariant, depending on if it shows
576+ // up through `Self` or `T::Assoc` syntax.
577+ if shadowed_captures. contains ( & param. def_id ) {
578+ continue ;
579+ }
558580
559581 match param. kind {
560582 ty:: GenericParamDefKind :: Lifetime => {
561583 // Check if the lifetime param was captured but isn't named in the precise captures list.
562584 if variances[ param. index as usize ] == ty:: Invariant {
563- let param_span =
564- if let ty:: ReEarlyParam ( ty:: EarlyParamRegion { def_id, .. } )
585+ let param_span = if let DefKind :: OpaqueTy =
586+ tcx. def_kind ( tcx. parent ( param. def_id ) )
587+ && let ty:: ReEarlyParam ( ty:: EarlyParamRegion { def_id, .. } )
565588 | ty:: ReLateParam ( ty:: LateParamRegion {
566589 bound_region : ty:: BoundRegionKind :: BrNamed ( def_id, _) ,
567590 ..
568591 } ) = * tcx
569592 . map_opaque_lifetime_to_parent_lifetime ( param. def_id . expect_local ( ) )
570- {
571- Some ( tcx. def_span ( def_id) )
572- } else {
573- None
574- } ;
593+ {
594+ Some ( tcx. def_span ( def_id) )
595+ } else {
596+ None
597+ } ;
575598 // FIXME(precise_capturing): Structured suggestion for this would be useful
576599 tcx. dcx ( ) . emit_err ( errors:: LifetimeNotCaptured {
577600 use_span : tcx. def_span ( param. def_id ) ,
0 commit comments