@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
3
3
use derive_where:: derive_where;
4
4
#[ cfg( feature = "nightly" ) ]
5
5
use rustc_macros:: { HashStable_NoContext , TyDecodable , TyEncodable } ;
6
- use rustc_type_ir:: data_structures:: ensure_sufficient_stack;
6
+ use rustc_type_ir:: data_structures:: { HashMap , HashSet , ensure_sufficient_stack} ;
7
7
use rustc_type_ir:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
8
8
use rustc_type_ir:: inherent:: * ;
9
9
use rustc_type_ir:: relate:: Relate ;
@@ -587,7 +587,7 @@ where
587
587
pub ( super ) fn add_normalizes_to_goal ( & mut self , mut goal : Goal < I , ty:: NormalizesTo < I > > ) {
588
588
goal. predicate = goal
589
589
. predicate
590
- . fold_with ( & mut ReplaceAliasWithInfer { ecx : self , param_env : goal. param_env } ) ;
590
+ . fold_with ( & mut ReplaceAliasWithInfer :: new ( self , goal. param_env ) ) ;
591
591
self . inspect . add_normalizes_to_goal ( self . delegate , self . max_input_universe , goal) ;
592
592
self . nested_goals . normalizes_to_goals . push ( goal) ;
593
593
}
@@ -596,7 +596,7 @@ where
596
596
pub ( super ) fn add_goal ( & mut self , source : GoalSource , mut goal : Goal < I , I :: Predicate > ) {
597
597
goal. predicate = goal
598
598
. predicate
599
- . fold_with ( & mut ReplaceAliasWithInfer { ecx : self , param_env : goal. param_env } ) ;
599
+ . fold_with ( & mut ReplaceAliasWithInfer :: new ( self , goal. param_env ) ) ;
600
600
self . inspect . add_goal ( self . delegate , self . max_input_universe , source, goal) ;
601
601
self . nested_goals . goals . push ( ( source, goal) ) ;
602
602
}
@@ -660,6 +660,7 @@ where
660
660
term : I :: Term ,
661
661
universe_of_term : ty:: UniverseIndex ,
662
662
delegate : & ' a D ,
663
+ cache : HashSet < I :: Ty > ,
663
664
}
664
665
665
666
impl < D : SolverDelegate < Interner = I > , I : Interner > ContainsTermOrNotNameable < ' _ , D , I > {
@@ -677,6 +678,10 @@ where
677
678
{
678
679
type Result = ControlFlow < ( ) > ;
679
680
fn visit_ty ( & mut self , t : I :: Ty ) -> Self :: Result {
681
+ if self . cache . contains ( & t) {
682
+ return ControlFlow :: Continue ( ( ) ) ;
683
+ }
684
+
680
685
match t. kind ( ) {
681
686
ty:: Infer ( ty:: TyVar ( vid) ) => {
682
687
if let ty:: TermKind :: Ty ( term) = self . term . kind ( ) {
@@ -689,17 +694,18 @@ where
689
694
}
690
695
}
691
696
692
- self . check_nameable ( self . delegate . universe_of_ty ( vid) . unwrap ( ) )
697
+ self . check_nameable ( self . delegate . universe_of_ty ( vid) . unwrap ( ) ) ? ;
693
698
}
694
- ty:: Placeholder ( p) => self . check_nameable ( p. universe ( ) ) ,
699
+ ty:: Placeholder ( p) => self . check_nameable ( p. universe ( ) ) ? ,
695
700
_ => {
696
701
if t. has_non_region_infer ( ) || t. has_placeholders ( ) {
697
- t. super_visit_with ( self )
698
- } else {
699
- ControlFlow :: Continue ( ( ) )
702
+ t. super_visit_with ( self ) ?
700
703
}
701
704
}
702
705
}
706
+
707
+ assert ! ( self . cache. insert( t) ) ;
708
+ ControlFlow :: Continue ( ( ) )
703
709
}
704
710
705
711
fn visit_const ( & mut self , c : I :: Const ) -> Self :: Result {
@@ -734,6 +740,7 @@ where
734
740
delegate : self . delegate ,
735
741
universe_of_term,
736
742
term : goal. predicate . term ,
743
+ cache : Default :: default ( ) ,
737
744
} ;
738
745
goal. predicate . alias . visit_with ( & mut visitor) . is_continue ( )
739
746
&& goal. param_env . visit_with ( & mut visitor) . is_continue ( )
@@ -1021,6 +1028,17 @@ where
1021
1028
{
1022
1029
ecx : & ' me mut EvalCtxt < ' a , D > ,
1023
1030
param_env : I :: ParamEnv ,
1031
+ cache : HashMap < I :: Ty , I :: Ty > ,
1032
+ }
1033
+
1034
+ impl < ' me , ' a , D , I > ReplaceAliasWithInfer < ' me , ' a , D , I >
1035
+ where
1036
+ D : SolverDelegate < Interner = I > ,
1037
+ I : Interner ,
1038
+ {
1039
+ fn new ( ecx : & ' me mut EvalCtxt < ' a , D > , param_env : I :: ParamEnv ) -> Self {
1040
+ ReplaceAliasWithInfer { ecx, param_env, cache : Default :: default ( ) }
1041
+ }
1024
1042
}
1025
1043
1026
1044
impl < D , I > TypeFolder < I > for ReplaceAliasWithInfer < ' _ , ' _ , D , I >
@@ -1033,7 +1051,11 @@ where
1033
1051
}
1034
1052
1035
1053
fn fold_ty ( & mut self , ty : I :: Ty ) -> I :: Ty {
1036
- match ty. kind ( ) {
1054
+ if let Some ( & entry) = self . cache . get ( & ty) {
1055
+ return entry;
1056
+ }
1057
+
1058
+ let res = match ty. kind ( ) {
1037
1059
ty:: Alias ( ..) if !ty. has_escaping_bound_vars ( ) => {
1038
1060
let infer_ty = self . ecx . next_ty_infer ( ) ;
1039
1061
let normalizes_to = ty:: PredicateKind :: AliasRelate (
@@ -1048,7 +1070,10 @@ where
1048
1070
infer_ty
1049
1071
}
1050
1072
_ => ty. super_fold_with ( self ) ,
1051
- }
1073
+ } ;
1074
+
1075
+ assert ! ( self . cache. insert( ty, res) . is_none( ) ) ;
1076
+ res
1052
1077
}
1053
1078
1054
1079
fn fold_const ( & mut self , ct : I :: Const ) -> I :: Const {
0 commit comments