@@ -542,97 +542,103 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
542
542
goal : Goal < ' tcx , G > ,
543
543
candidates : & mut Vec < Candidate < ' tcx > > ,
544
544
) {
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
+ }
593
549
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
+ }
599
594
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 )
602
601
{
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 } ) ;
610
603
}
604
+ return ;
605
+ }
611
606
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 } ) ;
633
619
}
620
+ Err ( NoSolution ) => { }
634
621
}
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
+ }
636
642
}
637
643
638
644
/// Check that we are allowed to use an alias bound originating from the self
0 commit comments