@@ -79,11 +79,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
7979 // them. This is necessary for inference during typeck.
8080 //
8181 // As this is incomplete, we must not do so during coherence.
82- match ( self . solver_mode ( ) , subst_relate_response) {
83- ( SolverMode :: Normal , Ok ( response) ) => Ok ( response) ,
84- ( SolverMode :: Normal , Err ( NoSolution ) ) | ( SolverMode :: Coherence , _) => {
85- self . flounder ( & candidates)
82+ match self . solver_mode ( ) {
83+ SolverMode :: Normal => {
84+ if let Ok ( subst_relate_response) = subst_relate_response {
85+ Ok ( subst_relate_response)
86+ } else if let Ok ( bidirectional_normalizes_to_response) = self
87+ . assemble_bidirectional_normalizes_to_candidate (
88+ param_env, lhs, rhs, direction,
89+ )
90+ {
91+ Ok ( bidirectional_normalizes_to_response)
92+ } else {
93+ self . flounder ( & candidates)
94+ }
8695 }
96+ SolverMode :: Coherence => self . flounder ( & candidates) ,
8797 }
8898 }
8999 }
@@ -100,29 +110,42 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
100110 invert : Invert ,
101111 ) -> QueryResult < ' tcx > {
102112 self . probe ( |ecx| {
103- let other = match direction {
104- // This is purely an optimization.
105- ty:: AliasRelationDirection :: Equate => other,
106-
107- ty:: AliasRelationDirection :: Subtype => {
108- let fresh = ecx. next_term_infer_of_kind ( other) ;
109- let ( sub, sup) = match invert {
110- Invert :: No => ( fresh, other) ,
111- Invert :: Yes => ( other, fresh) ,
112- } ;
113- ecx. sub ( param_env, sub, sup) ?;
114- fresh
115- }
116- } ;
117- ecx. add_goal ( Goal :: new (
118- ecx. tcx ( ) ,
119- param_env,
120- ty:: Binder :: dummy ( ty:: ProjectionPredicate { projection_ty : alias, term : other } ) ,
121- ) ) ;
113+ ecx. normalizes_to_inner ( param_env, alias, other, direction, invert) ?;
122114 ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
123115 } )
124116 }
125117
118+ fn normalizes_to_inner (
119+ & mut self ,
120+ param_env : ty:: ParamEnv < ' tcx > ,
121+ alias : ty:: AliasTy < ' tcx > ,
122+ other : ty:: Term < ' tcx > ,
123+ direction : ty:: AliasRelationDirection ,
124+ invert : Invert ,
125+ ) -> Result < ( ) , NoSolution > {
126+ let other = match direction {
127+ // This is purely an optimization.
128+ ty:: AliasRelationDirection :: Equate => other,
129+
130+ ty:: AliasRelationDirection :: Subtype => {
131+ let fresh = self . next_term_infer_of_kind ( other) ;
132+ let ( sub, sup) = match invert {
133+ Invert :: No => ( fresh, other) ,
134+ Invert :: Yes => ( other, fresh) ,
135+ } ;
136+ self . sub ( param_env, sub, sup) ?;
137+ fresh
138+ }
139+ } ;
140+ self . add_goal ( Goal :: new (
141+ self . tcx ( ) ,
142+ param_env,
143+ ty:: Binder :: dummy ( ty:: ProjectionPredicate { projection_ty : alias, term : other } ) ,
144+ ) ) ;
145+
146+ Ok ( ( ) )
147+ }
148+
126149 fn assemble_subst_relate_candidate (
127150 & mut self ,
128151 param_env : ty:: ParamEnv < ' tcx > ,
@@ -143,4 +166,30 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
143166 ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
144167 } )
145168 }
169+
170+ fn assemble_bidirectional_normalizes_to_candidate (
171+ & mut self ,
172+ param_env : ty:: ParamEnv < ' tcx > ,
173+ lhs : ty:: Term < ' tcx > ,
174+ rhs : ty:: Term < ' tcx > ,
175+ direction : ty:: AliasRelationDirection ,
176+ ) -> QueryResult < ' tcx > {
177+ self . probe ( |ecx| {
178+ ecx. normalizes_to_inner (
179+ param_env,
180+ lhs. to_alias_ty ( ecx. tcx ( ) ) . unwrap ( ) ,
181+ rhs,
182+ direction,
183+ Invert :: No ,
184+ ) ?;
185+ ecx. normalizes_to_inner (
186+ param_env,
187+ rhs. to_alias_ty ( ecx. tcx ( ) ) . unwrap ( ) ,
188+ lhs,
189+ direction,
190+ Invert :: Yes ,
191+ ) ?;
192+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
193+ } )
194+ }
146195}
0 commit comments