@@ -13,11 +13,14 @@ use rustc_middle::traits::solve::{
13
13
inspect, CanonicalInput , CanonicalResponse , Certainty , PredefinedOpaquesData , QueryResult ,
14
14
} ;
15
15
use rustc_middle:: traits:: specialization_graph;
16
+ use rustc_middle:: ty:: AliasRelationDirection ;
17
+ use rustc_middle:: ty:: TypeFolder ;
16
18
use rustc_middle:: ty:: {
17
19
self , InferCtxtLike , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable , TypeSuperVisitable ,
18
20
TypeVisitable , TypeVisitableExt , TypeVisitor ,
19
21
} ;
20
22
use rustc_span:: DUMMY_SP ;
23
+ use rustc_type_ir:: fold:: TypeSuperFoldable ;
21
24
use rustc_type_ir:: { self as ir, CanonicalVarValues , Interner } ;
22
25
use rustc_type_ir_macros:: { Lift_Generic , TypeFoldable_Generic , TypeVisitable_Generic } ;
23
26
use std:: ops:: ControlFlow ;
@@ -455,13 +458,23 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
455
458
}
456
459
457
460
#[ instrument( level = "trace" , skip( self ) ) ]
458
- pub ( super ) fn add_normalizes_to_goal ( & mut self , goal : Goal < ' tcx , ty:: NormalizesTo < ' tcx > > ) {
461
+ pub ( super ) fn add_normalizes_to_goal ( & mut self , mut goal : Goal < ' tcx , ty:: NormalizesTo < ' tcx > > ) {
462
+ goal. predicate = goal
463
+ . predicate
464
+ . fold_with ( & mut ReplaceAliasWithInfer { ecx : self , param_env : goal. param_env } ) ;
459
465
self . inspect . add_normalizes_to_goal ( self . infcx , self . max_input_universe , goal) ;
460
466
self . nested_goals . normalizes_to_goals . push ( goal) ;
461
467
}
462
468
463
469
#[ instrument( level = "debug" , skip( self ) ) ]
464
- pub ( super ) fn add_goal ( & mut self , source : GoalSource , goal : Goal < ' tcx , ty:: Predicate < ' tcx > > ) {
470
+ pub ( super ) fn add_goal (
471
+ & mut self ,
472
+ source : GoalSource ,
473
+ mut goal : Goal < ' tcx , ty:: Predicate < ' tcx > > ,
474
+ ) {
475
+ goal. predicate = goal
476
+ . predicate
477
+ . fold_with ( & mut ReplaceAliasWithInfer { ecx : self , param_env : goal. param_env } ) ;
465
478
self . inspect . add_goal ( self . infcx , self . max_input_universe , source, goal) ;
466
479
self . nested_goals . goals . push ( ( source, goal) ) ;
467
480
}
@@ -1084,3 +1097,63 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
1084
1097
} ) ;
1085
1098
}
1086
1099
}
1100
+
1101
+ /// Eagerly replace aliases with inference variables, emitting `AliasRelate`
1102
+ /// goals, used when adding goals to the `EvalCtxt`. We compute the
1103
+ /// `AliasRelate` goals before evaluating the actual goal to get all the
1104
+ /// constraints we can.
1105
+ ///
1106
+ /// This is a performance optimization to more eagerly detect cycles during trait
1107
+ /// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
1108
+ struct ReplaceAliasWithInfer < ' me , ' a , ' tcx > {
1109
+ ecx : & ' me mut EvalCtxt < ' a , InferCtxt < ' tcx > > ,
1110
+ param_env : ty:: ParamEnv < ' tcx > ,
1111
+ }
1112
+
1113
+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for ReplaceAliasWithInfer < ' _ , ' _ , ' tcx > {
1114
+ fn interner ( & self ) -> TyCtxt < ' tcx > {
1115
+ self . ecx . tcx ( )
1116
+ }
1117
+
1118
+ fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1119
+ match * ty. kind ( ) {
1120
+ ty:: Alias ( ..) if !ty. has_escaping_bound_vars ( ) => {
1121
+ let infer_ty = self . ecx . next_ty_infer ( ) ;
1122
+ let normalizes_to = ty:: PredicateKind :: AliasRelate (
1123
+ ty. into ( ) ,
1124
+ infer_ty. into ( ) ,
1125
+ AliasRelationDirection :: Equate ,
1126
+ ) ;
1127
+ self . ecx . add_goal (
1128
+ GoalSource :: Misc ,
1129
+ Goal :: new ( self . interner ( ) , self . param_env , normalizes_to) ,
1130
+ ) ;
1131
+ infer_ty
1132
+ }
1133
+ _ => ty. super_fold_with ( self ) ,
1134
+ }
1135
+ }
1136
+
1137
+ fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
1138
+ match ct. kind ( ) {
1139
+ ty:: ConstKind :: Unevaluated ( ..) if !ct. has_escaping_bound_vars ( ) => {
1140
+ let infer_ct = self . ecx . next_const_infer ( ct. ty ( ) ) ;
1141
+ let normalizes_to = ty:: PredicateKind :: AliasRelate (
1142
+ ct. into ( ) ,
1143
+ infer_ct. into ( ) ,
1144
+ AliasRelationDirection :: Equate ,
1145
+ ) ;
1146
+ self . ecx . add_goal (
1147
+ GoalSource :: Misc ,
1148
+ Goal :: new ( self . interner ( ) , self . param_env , normalizes_to) ,
1149
+ ) ;
1150
+ infer_ct
1151
+ }
1152
+ _ => ct. super_fold_with ( self ) ,
1153
+ }
1154
+ }
1155
+
1156
+ fn fold_predicate ( & mut self , predicate : ty:: Predicate < ' tcx > ) -> ty:: Predicate < ' tcx > {
1157
+ if predicate. allow_normalization ( ) { predicate. super_fold_with ( self ) } else { predicate }
1158
+ }
1159
+ }
0 commit comments