@@ -542,97 +542,101 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
542542 goal : Goal < ' tcx , G > ,
543543 candidates : & mut Vec < Candidate < ' tcx > > ,
544544 ) {
545- let _ = self . probe ( |_| ProbeKind :: NormalizedSelfTyAssembly ) . enter ( |ecx| {
546- let mut self_ty = goal. predicate . self_ty ( ) ;
547-
548- // For some deeply nested `<T>::A::B::C::D` rigid associated type,
549- // we should explore the item bounds for all levels, since the
550- // `associated_type_bounds` feature means that a parent associated
551- // type may carry bounds for a nested associated type.
552- loop {
553- let ( kind, alias_ty) = match * self_ty. kind ( ) {
554- ty:: Bool
555- | ty:: Char
556- | ty:: Int ( _)
557- | ty:: Uint ( _)
558- | ty:: Float ( _)
559- | ty:: Adt ( _, _)
560- | ty:: Foreign ( _)
561- | ty:: Str
562- | ty:: Array ( _, _)
563- | ty:: Slice ( _)
564- | ty:: RawPtr ( _)
565- | ty:: Ref ( _, _, _)
566- | ty:: FnDef ( _, _)
567- | ty:: FnPtr ( _)
568- | ty:: Dynamic ( ..)
569- | ty:: Closure ( ..)
570- | ty:: CoroutineClosure ( ..)
571- | ty:: Coroutine ( ..)
572- | ty:: CoroutineWitness ( ..)
573- | ty:: Never
574- | ty:: Tuple ( _)
575- | ty:: Param ( _)
576- | ty:: Placeholder ( ..)
577- | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
578- | ty:: Error ( _) => break ,
579- ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
580- | ty:: Bound ( ..) => bug ! ( "unexpected self type for `{goal:?}`" ) ,
581-
582- // If we hit infer when normalizing the self type of an alias,
583- // then bail with ambiguity.
584- ty:: Infer ( ty:: TyVar ( _) ) => {
585- if let Ok ( result) = ecx
586- . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
587- {
588- candidates
589- . push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
590- }
591- break ;
592- }
545+ let ( ) = self . probe ( |_| ProbeKind :: NormalizedSelfTyAssembly ) . enter ( |ecx| {
546+ ecx. assemble_alias_bound_candidates_recur ( goal. predicate . self_ty ( ) , goal, candidates) ;
547+ } ) ;
548+ }
593549
594- ty:: Alias ( kind @ ( ty:: Projection | ty:: Opaque ) , alias_ty) => ( kind, alias_ty) ,
595- ty:: Alias ( ty:: Inherent | ty:: Weak , _) => {
596- unreachable ! ( "Weak and Inherent aliases should have been normalized away" )
597- }
598- } ;
550+ // For some deeply nested `<T>::A::B::C::D` rigid associated type,
551+ // we should explore the item bounds for all levels, since the
552+ // `associated_type_bounds` feature means that a parent associated
553+ // type may carry bounds for a nested associated type.
554+ //
555+ // If we have a projection, check that its self type is a rigid projection.
556+ // If so, continue searching by recursively calling after normalization.
557+ fn assemble_alias_bound_candidates_recur < G : GoalKind < ' tcx > > (
558+ & mut self ,
559+ self_ty : Ty < ' tcx > ,
560+ goal : Goal < ' tcx , G > ,
561+ candidates : & mut Vec < Candidate < ' tcx > > ,
562+ ) {
563+ let ( kind, alias_ty) = match * self_ty. kind ( ) {
564+ ty:: Bool
565+ | ty:: Char
566+ | ty:: Int ( _)
567+ | ty:: Uint ( _)
568+ | ty:: Float ( _)
569+ | ty:: Adt ( _, _)
570+ | ty:: Foreign ( _)
571+ | ty:: Str
572+ | ty:: Array ( _, _)
573+ | ty:: Slice ( _)
574+ | ty:: RawPtr ( _)
575+ | ty:: Ref ( _, _, _)
576+ | ty:: FnDef ( _, _)
577+ | ty:: FnPtr ( _)
578+ | ty:: Dynamic ( ..)
579+ | ty:: Closure ( ..)
580+ | ty:: CoroutineClosure ( ..)
581+ | ty:: Coroutine ( ..)
582+ | ty:: CoroutineWitness ( ..)
583+ | ty:: Never
584+ | ty:: Tuple ( _)
585+ | ty:: Param ( _)
586+ | ty:: Placeholder ( ..)
587+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
588+ | ty:: Error ( _) => return ,
589+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) | ty:: Bound ( ..) => {
590+ bug ! ( "unexpected self type for `{goal:?}`" )
591+ }
599592
600- for assumption in
601- ecx. tcx ( ) . item_bounds ( alias_ty. def_id ) . instantiate ( ecx. tcx ( ) , alias_ty. args )
593+ ty:: Infer ( ty:: TyVar ( _) ) => {
594+ // If we hit infer when normalizing the self type of an alias,
595+ // then bail with ambiguity. We should never encounter this on
596+ // the *first* iteration of this recursive function.
597+ if let Ok ( result) =
598+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
602599 {
603- match G :: consider_alias_bound_candidate ( ecx, goal, assumption) {
604- Ok ( result) => {
605- candidates
606- . push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
607- }
608- Err ( NoSolution ) => { }
609- }
600+ candidates. push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
610601 }
602+ return ;
603+ }
611604
612- // If we have a projection, check that its self type is a rigid projection.
613- // If so, continue searching.
614- if kind == ty:: Projection {
615- match ecx. try_normalize_ty ( goal. param_env , alias_ty. self_ty ( ) ) {
616- Some ( next_self_ty) => self_ty = next_self_ty,
617- None => {
618- if let Ok ( result) = ecx
619- . evaluate_added_goals_and_make_canonical_response (
620- Certainty :: OVERFLOW ,
621- )
622- {
623- candidates. push ( Candidate {
624- source : CandidateSource :: AliasBound ,
625- result,
626- } ) ;
627- }
628- break ;
629- }
630- }
631- } else {
632- break ;
605+ ty:: Alias ( kind @ ( ty:: Projection | ty:: Opaque ) , alias_ty) => ( kind, alias_ty) ,
606+ ty:: Alias ( ty:: Inherent | ty:: Weak , _) => {
607+ unreachable ! ( "Weak and Inherent aliases should have been normalized away already" )
608+ }
609+ } ;
610+
611+ for assumption in
612+ self . tcx ( ) . item_bounds ( alias_ty. def_id ) . instantiate ( self . tcx ( ) , alias_ty. args )
613+ {
614+ match G :: consider_alias_bound_candidate ( self , goal, assumption) {
615+ Ok ( result) => {
616+ candidates. push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
633617 }
618+ Err ( NoSolution ) => { }
634619 }
635- } ) ;
620+ }
621+
622+ if kind != ty:: Projection {
623+ return ;
624+ }
625+
626+ match self . try_normalize_ty ( goal. param_env , alias_ty. self_ty ( ) ) {
627+ Some ( next_self_ty) => {
628+ // recurse on the alias self ty
629+ self . assemble_alias_bound_candidates_recur ( next_self_ty, goal, candidates) ;
630+ }
631+ None => {
632+ // bail if we overflow when normalizing
633+ if let Ok ( result) =
634+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: OVERFLOW )
635+ {
636+ candidates. push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
637+ }
638+ }
639+ }
636640 }
637641
638642 /// Check that we are allowed to use an alias bound originating from the self
0 commit comments