@@ -367,26 +367,29 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
367367 let impl_sig = ocx. normalize (
368368 & norm_cause,
369369 param_env,
370- infcx. replace_bound_vars_with_fresh_vars (
371- return_span,
372- infer:: HigherRankedType ,
373- tcx. fn_sig ( impl_m. def_id ) ,
374- ) ,
370+ tcx. liberate_late_bound_regions ( impl_m. def_id , tcx. fn_sig ( impl_m. def_id ) ) ,
375371 ) ;
372+ debug ! ( ?impl_sig) ;
376373 let impl_return_ty = impl_sig. output ( ) ;
377374
378375 // Normalize the trait signature with liberated bound vars, passing it through
379376 // the ImplTraitInTraitCollector, which gathers all of the RPITITs and replaces
380377 // them with inference variables.
381378 // We will use these inference variables to collect the hidden types of RPITITs.
382379 let mut collector = ImplTraitInTraitCollector :: new ( & ocx, return_span, param_env, impl_m_hir_id) ;
383- let unnormalized_trait_sig = tcx
384- . liberate_late_bound_regions (
385- impl_m. def_id ,
380+ let unnormalized_trait_sig = infcx
381+ . replace_bound_vars_with_fresh_vars (
382+ return_span,
383+ infer:: HigherRankedType ,
386384 tcx. bound_fn_sig ( trait_m. def_id ) . subst ( tcx, trait_to_placeholder_substs) ,
387385 )
388386 . fold_with ( & mut collector) ;
387+ if collector. types . is_empty ( ) {
388+ return Ok ( & * tcx. arena . alloc ( FxHashMap :: default ( ) ) ) ;
389+ }
390+
389391 let trait_sig = ocx. normalize ( & norm_cause, param_env, unnormalized_trait_sig) ;
392+ debug ! ( ?trait_sig) ;
390393 let trait_return_ty = trait_sig. output ( ) ;
391394
392395 let wf_tys = FxIndexSet :: from_iter (
@@ -422,7 +425,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
422425 }
423426 }
424427
425- debug ! ( ?trait_sig , ?impl_sig , "equating function signatures" ) ;
428+ debug ! ( "equating function signatures" ) ;
426429
427430 let trait_fty = tcx. mk_fn_ptr ( ty:: Binder :: dummy ( trait_sig) ) ;
428431 let impl_fty = tcx. mk_fn_ptr ( ty:: Binder :: dummy ( impl_sig) ) ;
@@ -461,86 +464,167 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
461464
462465 // Finally, resolve all regions. This catches wily misuses of
463466 // lifetime parameters.
467+ debug ! ( "check_region_obligations" ) ;
464468 let outlives_environment = OutlivesEnvironment :: with_bounds (
465469 param_env,
466470 Some ( infcx) ,
467471 infcx. implied_bounds_tys ( param_env, impl_m_hir_id, wf_tys) ,
468472 ) ;
473+ debug ! ( region_bound_pairs=?outlives_environment. region_bound_pairs( ) ) ;
469474 infcx. check_region_obligations_and_report_errors (
470475 impl_m. def_id . expect_local ( ) ,
471476 & outlives_environment,
472477 ) ;
473478
479+ debug ! ( "resolve collected" ) ;
474480 let mut collected_tys = FxHashMap :: default ( ) ;
475- for ( def_id, ( ty, substs) ) in collector. types {
476- match infcx. fully_resolve ( ty) {
477- Ok ( ty) => {
478- // `ty` contains free regions that we created earlier while liberating the
479- // trait fn signature. However, projection normalization expects `ty` to
480- // contains `def_id`'s early-bound regions.
481- let id_substs = InternalSubsts :: identity_for_item ( tcx, def_id) ;
482- debug ! ( ?id_substs, ?substs) ;
483- let map: FxHashMap < ty:: GenericArg < ' tcx > , ty:: GenericArg < ' tcx > > =
484- std:: iter:: zip ( substs, id_substs) . collect ( ) ;
485- debug ! ( ?map) ;
486-
487- // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
488- // region substs that are synthesized during AST lowering. These are substs
489- // that are appended to the parent substs (trait and trait method). However,
490- // we're trying to infer the unsubstituted type value of the RPITIT inside
491- // the *impl*, so we can later use the impl's method substs to normalize
492- // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
493- //
494- // Due to the design of RPITITs, during AST lowering, we have no idea that
495- // an impl method corresponds to a trait method with RPITITs in it. Therefore,
496- // we don't have a list of early-bound region substs for the RPITIT in the impl.
497- // Since early region parameters are index-based, we can't just rebase these
498- // (trait method) early-bound region substs onto the impl, and there's no
499- // guarantee that the indices from the trait substs and impl substs line up.
500- // So to fix this, we subtract the number of trait substs and add the number of
501- // impl substs to *renumber* these early-bound regions to their corresponding
502- // indices in the impl's substitutions list.
503- //
504- // Also, we only need to account for a difference in trait and impl substs,
505- // since we previously enforce that the trait method and impl method have the
506- // same generics.
507- let num_trait_substs = trait_to_impl_substs. len ( ) ;
508- let num_impl_substs = tcx. generics_of ( impl_m. container_id ( tcx) ) . params . len ( ) ;
509- let ty = tcx. fold_regions ( ty, |region, _| {
510- match region. kind ( ) {
511- // Remap all free regions, which correspond to late-bound regions in the function.
512- ty:: ReFree ( _) => { }
513- // Remap early-bound regions as long as they don't come from the `impl` itself.
514- ty:: ReEarlyBound ( ebr) if tcx. parent ( ebr. def_id ) != impl_m. container_id ( tcx) => { }
515- _ => return region,
516- }
517- let Some ( ty:: ReEarlyBound ( e) ) = map. get ( & region. into ( ) ) . map ( |r| r. expect_region ( ) . kind ( ) )
518- else {
519- tcx
520- . sess
521- . delay_span_bug (
522- return_span,
523- "expected ReFree to map to ReEarlyBound"
524- ) ;
525- return tcx. lifetimes . re_static ;
526- } ;
527- tcx. mk_region ( ty:: ReEarlyBound ( ty:: EarlyBoundRegion {
528- def_id : e. def_id ,
529- name : e. name ,
530- index : ( e. index as usize - num_trait_substs + num_impl_substs) as u32 ,
531- } ) )
532- } ) ;
533- debug ! ( %ty) ;
534- collected_tys. insert ( def_id, ty) ;
481+ for ( def_id, ( raw_ty, substs) ) in collector. types {
482+ debug ! ( ?def_id) ;
483+
484+ let substs = match infcx. fully_resolve ( substs) {
485+ Ok ( substs) => substs,
486+ Err ( err) => {
487+ collected_tys. insert (
488+ def_id,
489+ tcx. ty_error_with_message (
490+ return_span,
491+ & format ! ( "could not fully resolve: {substs:?} => {err:?}" ) ,
492+ ) ,
493+ ) ;
494+ continue ;
535495 }
496+ } ;
497+ debug ! ( ?substs) ;
498+
499+ let raw_ty = match infcx. fully_resolve ( raw_ty) {
500+ Ok ( raw_ty) => raw_ty,
536501 Err ( err) => {
537- let reported = tcx. sess . delay_span_bug (
538- return_span,
539- format ! ( "could not fully resolve: {ty} => {err:?}" ) ,
502+ collected_tys. insert (
503+ def_id,
504+ tcx. ty_error_with_message (
505+ return_span,
506+ & format ! ( "could not fully resolve: {raw_ty} => {err:?}" ) ,
507+ ) ,
540508 ) ;
541- collected_tys . insert ( def_id , tcx . ty_error_with_guaranteed ( reported ) ) ;
509+ continue ;
542510 }
511+ } ;
512+ debug ! ( ?raw_ty) ;
513+
514+ // `raw_ty` contains free regions that we created earlier while liberating the
515+ // trait fn signature. However, projection normalization expects `raw_ty` to
516+ // contains `def_id`'s early-bound regions.
517+ let id_substs = InternalSubsts :: identity_for_item ( tcx, def_id) ;
518+ debug ! ( ?id_substs, ?substs) ;
519+
520+ let variances = tcx. variances_of ( def_id) ;
521+ debug ! ( ?variances) ;
522+
523+ // Opaque types may only use regions that are bound. So for
524+ // ```rust
525+ // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
526+ // ```
527+ // we may not use `'c` in the hidden type.
528+ let map: FxHashMap < ty:: GenericArg < ' tcx > , ty:: GenericArg < ' tcx > > =
529+ std:: iter:: zip ( substs, id_substs)
530+ . filter ( |( _, v) | {
531+ let ty:: GenericArgKind :: Lifetime ( lt) = v. unpack ( ) else { return true } ;
532+ let ty:: ReEarlyBound ( ebr) = lt. kind ( ) else { bug ! ( ) } ;
533+ variances[ ebr. index as usize ] == ty:: Variance :: Invariant
534+ } )
535+ . collect ( ) ;
536+ debug ! ( ?map) ;
537+
538+ // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
539+ // region substs that are synthesized during AST lowering. These are substs
540+ // that are appended to the parent substs (trait and trait method). However,
541+ // we're trying to infer the unsubstituted type value of the RPITIT inside
542+ // the *impl*, so we can later use the impl's method substs to normalize
543+ // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
544+ //
545+ // Due to the design of RPITITs, during AST lowering, we have no idea that
546+ // an impl method corresponds to a trait method with RPITITs in it. Therefore,
547+ // we don't have a list of early-bound region substs for the RPITIT in the impl.
548+ // Since early region parameters are index-based, we can't just rebase these
549+ // (trait method) early-bound region substs onto the impl, and there's no
550+ // guarantee that the indices from the trait substs and impl substs line up.
551+ // So to fix this, we subtract the number of trait substs and add the number of
552+ // impl substs to *renumber* these early-bound regions to their corresponding
553+ // indices in the impl's substitutions list.
554+ //
555+ // Also, we only need to account for a difference in trait and impl substs,
556+ // since we previously enforce that the trait method and impl method have the
557+ // same generics.
558+ let num_trait_substs = trait_to_impl_substs. len ( ) ;
559+ let num_impl_substs = tcx. generics_of ( impl_m. def_id ) . parent_count ;
560+ debug ! ( ?num_trait_substs, ?num_impl_substs) ;
561+
562+ let mut bad_regions = vec ! [ ] ;
563+
564+ let ty = tcx. fold_regions ( raw_ty, |region, _| {
565+ debug ! ( ?region) ;
566+ match region. kind ( ) {
567+ // Remap all free regions, which correspond to late-bound regions in the function.
568+ ty:: ReFree ( _) => { }
569+ // Remap early-bound regions as long as they don't come from the `impl` itself.
570+ ty:: ReEarlyBound ( ebr) if ( ebr. index as usize ) >= num_impl_substs => { }
571+ _ => return region,
572+ }
573+ debug ! ( mapped = ?map. get( & region. into( ) ) ) ;
574+ let Some ( ty:: ReEarlyBound ( e) ) = map. get ( & region. into ( ) ) . map ( |r| r. expect_region ( ) . kind ( ) )
575+ else {
576+ bad_regions. push ( region) ;
577+ return tcx. lifetimes . re_static ;
578+ } ;
579+ tcx. mk_region ( ty:: ReEarlyBound ( ty:: EarlyBoundRegion {
580+ def_id : e. def_id ,
581+ name : e. name ,
582+ index : ( e. index as usize - num_trait_substs + num_impl_substs) as u32 ,
583+ } ) )
584+ } ) ;
585+
586+ if !bad_regions. is_empty ( ) {
587+ let mut err = tcx. sess . struct_span_err (
588+ return_span,
589+ "`impl` item return type captures lifetime that doesn't appear in `trait` item bounds" ,
590+ ) ;
591+ for r in bad_regions {
592+ let span = match r. kind ( ) {
593+ ty:: ReEarlyBound ( ebr) => tcx. def_span ( ebr. def_id ) ,
594+ ty:: ReFree ( fr) => fr. bound_region . opt_span ( tcx) . unwrap ( ) ,
595+ _ => bug ! ( ) ,
596+ } ;
597+ let name = if r. has_name ( ) {
598+ format ! ( "lifetime `{r}`" )
599+ } else {
600+ "the anonymous lifetime" . to_string ( )
601+ } ;
602+ err. span_label ( span, format ! ( "type `{raw_ty}` captures {name} defined here" ) ) ;
603+ }
604+
605+ let generics = tcx. generics_of ( def_id) ;
606+ match & generics. params [ ..] {
607+ [ ] => {
608+ err. span_label ( tcx. def_span ( def_id) , "type declared not to capture lifetimes" ) ;
609+ }
610+ [ param] => {
611+ err. span_label (
612+ tcx. def_span ( param. def_id ) ,
613+ "type can only capture this lifetime" ,
614+ ) ;
615+ }
616+ params => {
617+ err. span_labels (
618+ params. iter ( ) . map ( |param| tcx. def_span ( param. def_id ) ) ,
619+ "type can only capture lifetimes enumerated here" ,
620+ ) ;
621+ }
622+ } ;
623+ err. emit ( ) ;
543624 }
625+
626+ debug ! ( ?ty) ;
627+ collected_tys. insert ( def_id, ty) ;
544628 }
545629
546630 Ok ( & * tcx. arena . alloc ( collected_tys) )
0 commit comments