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