@@ -16,12 +16,15 @@ use rustc_middle::traits::solve::{
16
16
inspect, CanonicalInput , CanonicalResponse , Certainty , PredefinedOpaquesData , QueryResult ,
17
17
} ;
18
18
use rustc_middle:: traits:: specialization_graph;
19
+ use rustc_middle:: ty:: AliasRelationDirection ;
20
+ use rustc_middle:: ty:: TypeFolder ;
19
21
use rustc_middle:: ty:: {
20
22
self , InferCtxtLike , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable , TypeSuperVisitable ,
21
23
TypeVisitable , TypeVisitableExt , TypeVisitor ,
22
24
} ;
23
25
use rustc_session:: config:: DumpSolverProofTree ;
24
26
use rustc_span:: DUMMY_SP ;
27
+ use rustc_type_ir:: fold:: TypeSuperFoldable ;
25
28
use rustc_type_ir:: { self as ir, CanonicalVarValues , Interner } ;
26
29
use rustc_type_ir_macros:: { Lift_Generic , TypeFoldable_Generic , TypeVisitable_Generic } ;
27
30
@@ -468,13 +471,23 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
468
471
}
469
472
470
473
#[ instrument( level = "trace" , skip( self ) ) ]
471
- pub ( super ) fn add_normalizes_to_goal ( & mut self , goal : Goal < ' tcx , ty:: NormalizesTo < ' tcx > > ) {
474
+ pub ( super ) fn add_normalizes_to_goal ( & mut self , mut goal : Goal < ' tcx , ty:: NormalizesTo < ' tcx > > ) {
475
+ goal. predicate = goal
476
+ . predicate
477
+ . fold_with ( & mut ReplaceAliasWithInfer { ecx : self , param_env : goal. param_env } ) ;
472
478
self . inspect . add_normalizes_to_goal ( self . infcx , self . max_input_universe , goal) ;
473
479
self . nested_goals . normalizes_to_goals . push ( goal) ;
474
480
}
475
481
476
482
#[ instrument( level = "debug" , skip( self ) ) ]
477
- pub ( super ) fn add_goal ( & mut self , source : GoalSource , goal : Goal < ' tcx , ty:: Predicate < ' tcx > > ) {
483
+ pub ( super ) fn add_goal (
484
+ & mut self ,
485
+ source : GoalSource ,
486
+ mut goal : Goal < ' tcx , ty:: Predicate < ' tcx > > ,
487
+ ) {
488
+ goal. predicate = goal
489
+ . predicate
490
+ . fold_with ( & mut ReplaceAliasWithInfer { ecx : self , param_env : goal. param_env } ) ;
478
491
self . inspect . add_goal ( self . infcx , self . max_input_universe , source, goal) ;
479
492
self . nested_goals . goals . push ( ( source, goal) ) ;
480
493
}
@@ -1101,3 +1114,63 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
1101
1114
} ) ;
1102
1115
}
1103
1116
}
1117
+
1118
+ /// Eagerly replace aliases with inference variables, emitting `AliasRelate`
1119
+ /// goals, used when adding goals to the `EvalCtxt`. We compute the
1120
+ /// `AliasRelate` goals before evaluating the actual goal to get all the
1121
+ /// constraints we can.
1122
+ ///
1123
+ /// This is a performance optimization to more eagerly detect cycles during trait
1124
+ /// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
1125
+ struct ReplaceAliasWithInfer < ' me , ' a , ' tcx > {
1126
+ ecx : & ' me mut EvalCtxt < ' a , InferCtxt < ' tcx > > ,
1127
+ param_env : ty:: ParamEnv < ' tcx > ,
1128
+ }
1129
+
1130
+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for ReplaceAliasWithInfer < ' _ , ' _ , ' tcx > {
1131
+ fn interner ( & self ) -> TyCtxt < ' tcx > {
1132
+ self . ecx . tcx ( )
1133
+ }
1134
+
1135
+ fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1136
+ match * ty. kind ( ) {
1137
+ ty:: Alias ( ..) if !ty. has_escaping_bound_vars ( ) => {
1138
+ let infer_ty = self . ecx . next_ty_infer ( ) ;
1139
+ let normalizes_to = ty:: PredicateKind :: AliasRelate (
1140
+ ty. into ( ) ,
1141
+ infer_ty. into ( ) ,
1142
+ AliasRelationDirection :: Equate ,
1143
+ ) ;
1144
+ self . ecx . add_goal (
1145
+ GoalSource :: Misc ,
1146
+ Goal :: new ( self . interner ( ) , self . param_env , normalizes_to) ,
1147
+ ) ;
1148
+ infer_ty
1149
+ }
1150
+ _ => ty. super_fold_with ( self ) ,
1151
+ }
1152
+ }
1153
+
1154
+ fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
1155
+ match ct. kind ( ) {
1156
+ ty:: ConstKind :: Unevaluated ( ..) if !ct. has_escaping_bound_vars ( ) => {
1157
+ let infer_ct = self . ecx . next_const_infer ( ct. ty ( ) ) ;
1158
+ let normalizes_to = ty:: PredicateKind :: AliasRelate (
1159
+ ct. into ( ) ,
1160
+ infer_ct. into ( ) ,
1161
+ AliasRelationDirection :: Equate ,
1162
+ ) ;
1163
+ self . ecx . add_goal (
1164
+ GoalSource :: Misc ,
1165
+ Goal :: new ( self . interner ( ) , self . param_env , normalizes_to) ,
1166
+ ) ;
1167
+ infer_ct
1168
+ }
1169
+ _ => ct. super_fold_with ( self ) ,
1170
+ }
1171
+ }
1172
+
1173
+ fn fold_predicate ( & mut self , predicate : ty:: Predicate < ' tcx > ) -> ty:: Predicate < ' tcx > {
1174
+ if predicate. allow_normalization ( ) { predicate. super_fold_with ( self ) } else { predicate }
1175
+ }
1176
+ }
0 commit comments