@@ -542,97 +542,103 @@ 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+ // FIXME: This may recurse infinitely, but I can't seem to trigger it without
558+ // hitting another overflow error something. Add a depth parameter needed later.
559+ fn assemble_alias_bound_candidates_recur < G : GoalKind < ' tcx > > (
560+ & mut self ,
561+ self_ty : Ty < ' tcx > ,
562+ goal : Goal < ' tcx , G > ,
563+ candidates : & mut Vec < Candidate < ' tcx > > ,
564+ ) {
565+ let ( kind, alias_ty) = match * self_ty. kind ( ) {
566+ ty:: Bool
567+ | ty:: Char
568+ | ty:: Int ( _)
569+ | ty:: Uint ( _)
570+ | ty:: Float ( _)
571+ | ty:: Adt ( _, _)
572+ | ty:: Foreign ( _)
573+ | ty:: Str
574+ | ty:: Array ( _, _)
575+ | ty:: Slice ( _)
576+ | ty:: RawPtr ( _)
577+ | ty:: Ref ( _, _, _)
578+ | ty:: FnDef ( _, _)
579+ | ty:: FnPtr ( _)
580+ | ty:: Dynamic ( ..)
581+ | ty:: Closure ( ..)
582+ | ty:: CoroutineClosure ( ..)
583+ | ty:: Coroutine ( ..)
584+ | ty:: CoroutineWitness ( ..)
585+ | ty:: Never
586+ | ty:: Tuple ( _)
587+ | ty:: Param ( _)
588+ | ty:: Placeholder ( ..)
589+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
590+ | ty:: Error ( _) => return ,
591+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) | ty:: Bound ( ..) => {
592+ bug ! ( "unexpected self type for `{goal:?}`" )
593+ }
599594
600- for assumption in
601- ecx. tcx ( ) . item_bounds ( alias_ty. def_id ) . instantiate ( ecx. tcx ( ) , alias_ty. args )
595+ ty:: Infer ( ty:: TyVar ( _) ) => {
596+ // If we hit infer when normalizing the self type of an alias,
597+ // then bail with ambiguity. We should never encounter this on
598+ // the *first* iteration of this recursive function.
599+ if let Ok ( result) =
600+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
602601 {
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- }
602+ candidates. push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
610603 }
604+ return ;
605+ }
611606
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 ;
607+ ty:: Alias ( kind @ ( ty:: Projection | ty:: Opaque ) , alias_ty) => ( kind, alias_ty) ,
608+ ty:: Alias ( ty:: Inherent | ty:: Weak , _) => {
609+ unreachable ! ( "Weak and Inherent aliases should have been normalized away already" )
610+ }
611+ } ;
612+
613+ for assumption in
614+ self . tcx ( ) . item_bounds ( alias_ty. def_id ) . instantiate ( self . tcx ( ) , alias_ty. args )
615+ {
616+ match G :: consider_alias_bound_candidate ( self , goal, assumption) {
617+ Ok ( result) => {
618+ candidates. push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
633619 }
620+ Err ( NoSolution ) => { }
634621 }
635- } ) ;
622+ }
623+
624+ if kind != ty:: Projection {
625+ return ;
626+ }
627+
628+ match self . try_normalize_ty ( goal. param_env , alias_ty. self_ty ( ) ) {
629+ // Recurse on the self type of the projection.
630+ Some ( next_self_ty) => {
631+ self . assemble_alias_bound_candidates_recur ( next_self_ty, goal, candidates) ;
632+ }
633+ // Bail if we overflow when normalizing, adding an ambiguous candidate.
634+ None => {
635+ if let Ok ( result) =
636+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: OVERFLOW )
637+ {
638+ candidates. push ( Candidate { source : CandidateSource :: AliasBound , result } ) ;
639+ }
640+ }
641+ }
636642 }
637643
638644 /// Check that we are allowed to use an alias bound originating from the self
0 commit comments