@@ -608,8 +608,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
608
608
609
609
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
610
610
///
611
- /// This is the case if the `term` is an inference variable in the innermost universe
612
- /// and does not occur in any other part of the predicate .
611
+ /// This is the case if the `term` does not occur in any other part of the predicate
612
+ /// and is able to name all other placeholder and inference variables .
613
613
#[ instrument( level = "debug" , skip( self ) , ret) ]
614
614
pub ( super ) fn term_is_fully_unconstrained (
615
615
& self ,
@@ -632,55 +632,67 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
632
632
}
633
633
} ;
634
634
635
- // Guard against `<T as Trait<?0>>::Assoc = ?0>`.
636
635
struct ContainsTermOrNotNameable < ' a , ' tcx > {
637
636
term : ty:: Term < ' tcx > ,
638
637
universe_of_term : ty:: UniverseIndex ,
639
638
infcx : & ' a InferCtxt < ' tcx > ,
640
639
}
640
+
641
+ impl < ' a , ' tcx > ContainsTermOrNotNameable < ' a , ' tcx > {
642
+ fn check_nameable ( & self , universe : ty:: UniverseIndex ) -> ControlFlow < ( ) > {
643
+ if self . universe_of_term . can_name ( universe) {
644
+ ControlFlow :: Continue ( ( ) )
645
+ } else {
646
+ ControlFlow :: Break ( ( ) )
647
+ }
648
+ }
649
+ }
650
+
641
651
impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for ContainsTermOrNotNameable < ' _ , ' tcx > {
642
652
type BreakTy = ( ) ;
643
653
fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
644
- if let Some ( vid) = t. ty_vid ( ) {
645
- if let ty:: TermKind :: Ty ( term) = self . term . unpack ( )
646
- && let Some ( term_vid) = term. ty_vid ( )
647
- && self . infcx . root_var ( vid) == self . infcx . root_var ( term_vid)
648
- {
649
- ControlFlow :: Break ( ( ) )
650
- } else if self
651
- . universe_of_term
652
- . cannot_name ( self . infcx . universe_of_ty ( vid) . unwrap ( ) )
653
- {
654
- ControlFlow :: Break ( ( ) )
655
- } else {
656
- ControlFlow :: Continue ( ( ) )
654
+ match * t. kind ( ) {
655
+ ty:: Infer ( ty:: TyVar ( vid) ) => {
656
+ if let ty:: TermKind :: Ty ( term) = self . term . unpack ( )
657
+ && let Some ( term_vid) = term. ty_vid ( )
658
+ && self . infcx . root_var ( vid) == self . infcx . root_var ( term_vid)
659
+ {
660
+ ControlFlow :: Break ( ( ) )
661
+ } else {
662
+ self . check_nameable ( self . infcx . universe_of_ty ( vid) . unwrap ( ) )
663
+ }
664
+ }
665
+ ty:: Placeholder ( p) => self . check_nameable ( p. universe ) ,
666
+ _ => {
667
+ if t. has_non_region_infer ( ) || t. has_placeholders ( ) {
668
+ t. super_visit_with ( self )
669
+ } else {
670
+ ControlFlow :: Continue ( ( ) )
671
+ }
657
672
}
658
- } else if t. has_non_region_infer ( ) {
659
- t. super_visit_with ( self )
660
- } else {
661
- ControlFlow :: Continue ( ( ) )
662
673
}
663
674
}
664
675
665
676
fn visit_const ( & mut self , c : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
666
- if let ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( vid) ) = c. kind ( ) {
667
- if let ty:: TermKind :: Const ( term) = self . term . unpack ( )
668
- && let ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( term_vid) ) = term. kind ( )
669
- && self . infcx . root_const_var ( vid) == self . infcx . root_const_var ( term_vid)
670
- {
671
- ControlFlow :: Break ( ( ) )
672
- } else if self
673
- . universe_of_term
674
- . cannot_name ( self . infcx . universe_of_ct ( vid) . unwrap ( ) )
675
- {
676
- ControlFlow :: Break ( ( ) )
677
- } else {
678
- ControlFlow :: Continue ( ( ) )
677
+ match c. kind ( ) {
678
+ ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( vid) ) => {
679
+ if let ty:: TermKind :: Const ( term) = self . term . unpack ( )
680
+ && let ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( term_vid) ) = term. kind ( )
681
+ && self . infcx . root_const_var ( vid) == self . infcx . root_const_var ( term_vid)
682
+ {
683
+ ControlFlow :: Break ( ( ) )
684
+ } else {
685
+ self . check_nameable ( self . infcx . universe_of_ct ( vid) . unwrap ( ) )
686
+ }
687
+ }
688
+ ty:: ConstKind :: Placeholder ( p) => self . check_nameable ( p. universe ) ,
689
+ _ => {
690
+ if c. has_non_region_infer ( ) || c. has_placeholders ( ) {
691
+ c. super_visit_with ( self )
692
+ } else {
693
+ ControlFlow :: Continue ( ( ) )
694
+ }
679
695
}
680
- } else if c. has_non_region_infer ( ) {
681
- c. super_visit_with ( self )
682
- } else {
683
- ControlFlow :: Continue ( ( ) )
684
696
}
685
697
}
686
698
}
0 commit comments