@@ -45,8 +45,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
45
45
projection_ty : goal. predicate . projection_ty ,
46
46
term : unconstrained_rhs,
47
47
} ) ;
48
- let ( _has_changed, normalize_certainty) =
49
- self . evaluate_goal ( goal. with ( self . tcx ( ) , unconstrained_predicate) ) ?;
48
+ let ( _has_changed, normalize_certainty) = self . in_projection_eq_hack ( |this| {
49
+ this. evaluate_goal ( goal. with ( this. tcx ( ) , unconstrained_predicate) )
50
+ } ) ?;
50
51
51
52
let nested_eq_goals =
52
53
self . infcx . eq ( goal. param_env , unconstrained_rhs, predicate. term ) ?;
@@ -55,6 +56,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
55
56
}
56
57
}
57
58
59
+ /// This sets a flag used by a debug assert in [`EvalCtxt::evaluate_goal`],
60
+ /// see the comment in that method for more details.
61
+ fn in_projection_eq_hack < T > ( & mut self , f : impl FnOnce ( & mut Self ) -> T ) -> T {
62
+ self . in_projection_eq_hack = true ;
63
+ let result = f ( self ) ;
64
+ self . in_projection_eq_hack = false ;
65
+ result
66
+ }
67
+
58
68
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
59
69
///
60
70
/// This is the case if the `term` is an inference variable in the innermost universe
@@ -122,6 +132,28 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
122
132
&& goal. param_env . visit_with ( & mut visitor) . is_continue ( )
123
133
}
124
134
135
+ /// After normalizing the projection to `normalized_alias` with the given
136
+ /// `normalization_certainty`, constrain the inference variable `term` to it
137
+ /// and return a query response.
138
+ fn eq_term_and_make_canonical_response (
139
+ & mut self ,
140
+ goal : Goal < ' tcx , ProjectionPredicate < ' tcx > > ,
141
+ normalization_certainty : Certainty ,
142
+ normalized_alias : impl Into < ty:: Term < ' tcx > > ,
143
+ ) -> QueryResult < ' tcx > {
144
+ // The term of our goal should be fully unconstrained, so this should never fail.
145
+ //
146
+ // It can however be ambiguous when the `normalized_alias` contains a projection.
147
+ let nested_goals = self
148
+ . infcx
149
+ . eq ( goal. param_env , goal. predicate . term , normalized_alias. into ( ) )
150
+ . expect ( "failed to unify with unconstrained term" ) ;
151
+ let rhs_certainty =
152
+ self . evaluate_all ( nested_goals) . expect ( "failed to unify with unconstrained term" ) ;
153
+
154
+ self . make_canonical_response ( normalization_certainty. unify_and ( rhs_certainty) )
155
+ }
156
+
125
157
fn merge_project_candidates (
126
158
& mut self ,
127
159
mut candidates : Vec < Candidate < ' tcx > > ,
@@ -218,7 +250,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
218
250
. map ( |pred| goal. with ( tcx, pred) ) ;
219
251
220
252
nested_goals. extend ( where_clause_bounds) ;
221
- let trait_ref_certainty = ecx. evaluate_all ( nested_goals) ?;
253
+ let match_impl_certainty = ecx. evaluate_all ( nested_goals) ?;
222
254
223
255
// In case the associated item is hidden due to specialization, we have to
224
256
// return ambiguity this would otherwise be incomplete, resulting in
@@ -230,7 +262,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
230
262
goal. predicate . def_id ( ) ,
231
263
impl_def_id
232
264
) ? else {
233
- return ecx. make_canonical_response ( trait_ref_certainty . unify_and ( Certainty :: AMBIGUOUS ) ) ;
265
+ return ecx. make_canonical_response ( match_impl_certainty . unify_and ( Certainty :: AMBIGUOUS ) ) ;
234
266
} ;
235
267
236
268
if !assoc_def. item . defaultness ( tcx) . has_value ( ) {
@@ -277,17 +309,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
277
309
ty. map_bound ( |ty| ty. into ( ) )
278
310
} ;
279
311
280
- // The term of our goal should be fully unconstrained, so this should never fail.
281
- //
282
- // It can however be ambiguous when the resolved type is a projection.
283
- let nested_goals = ecx
284
- . infcx
285
- . eq ( goal. param_env , goal. predicate . term , term. subst ( tcx, substs) )
286
- . expect ( "failed to unify with unconstrained term" ) ;
287
- let rhs_certainty =
288
- ecx. evaluate_all ( nested_goals) . expect ( "failed to unify with unconstrained term" ) ;
289
-
290
- ecx. make_canonical_response ( trait_ref_certainty. unify_and ( rhs_certainty) )
312
+ ecx. eq_term_and_make_canonical_response ( goal, match_impl_certainty, term. subst ( tcx, substs) )
291
313
} )
292
314
}
293
315
@@ -309,18 +331,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
309
331
) ?;
310
332
let subst_certainty = ecx. evaluate_all ( nested_goals) ?;
311
333
312
- // The term of our goal should be fully unconstrained, so this should never fail.
313
- //
314
- // It can however be ambiguous when the resolved type is a projection.
315
- let nested_goals = ecx
316
- . infcx
317
- . eq ( goal. param_env , goal. predicate . term , assumption_projection_pred. term )
318
- . expect ( "failed to unify with unconstrained term" ) ;
319
- let rhs_certainty = ecx
320
- . evaluate_all ( nested_goals)
321
- . expect ( "failed to unify with unconstrained term" ) ;
322
-
323
- ecx. make_canonical_response ( subst_certainty. unify_and ( rhs_certainty) )
334
+ ecx. eq_term_and_make_canonical_response (
335
+ goal,
336
+ subst_certainty,
337
+ assumption_projection_pred. term ,
338
+ )
324
339
} )
325
340
} else {
326
341
Err ( NoSolution )
@@ -437,14 +452,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
437
452
[ ty:: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
438
453
) ) ;
439
454
440
- let mut nested_goals = ecx. infcx . eq (
441
- goal. param_env ,
442
- goal. predicate . term . ty ( ) . unwrap ( ) ,
455
+ let is_sized_certainty = ecx. evaluate_goal ( goal. with ( tcx, sized_predicate) ) ?. 1 ;
456
+ return ecx. eq_term_and_make_canonical_response (
457
+ goal,
458
+ is_sized_certainty,
443
459
tcx. types . unit ,
444
- ) ?;
445
- nested_goals. push ( goal. with ( tcx, sized_predicate) ) ;
446
-
447
- return ecx. evaluate_all_and_make_canonical_response ( nested_goals) ;
460
+ ) ;
448
461
}
449
462
450
463
ty:: Adt ( def, substs) if def. is_struct ( ) => {
@@ -456,7 +469,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
456
469
tcx,
457
470
ty:: Binder :: dummy ( goal. predicate . with_self_ty ( tcx, self_ty) ) ,
458
471
) ;
459
- return ecx. evaluate_all_and_make_canonical_response ( vec ! [ new_goal] ) ;
472
+ let ( _, certainty) = ecx. evaluate_goal ( new_goal) ?;
473
+ return ecx. make_canonical_response ( certainty) ;
460
474
}
461
475
}
462
476
}
@@ -469,7 +483,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
469
483
tcx,
470
484
ty:: Binder :: dummy ( goal. predicate . with_self_ty ( tcx, self_ty) ) ,
471
485
) ;
472
- return ecx. evaluate_all_and_make_canonical_response ( vec ! [ new_goal] ) ;
486
+ let ( _, certainty) = ecx. evaluate_goal ( new_goal) ?;
487
+ return ecx. make_canonical_response ( certainty) ;
473
488
}
474
489
} ,
475
490
@@ -482,9 +497,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
482
497
) ,
483
498
} ;
484
499
485
- let nested_goals =
486
- ecx. infcx . eq ( goal. param_env , goal. predicate . term . ty ( ) . unwrap ( ) , metadata_ty) ?;
487
- ecx. evaluate_all_and_make_canonical_response ( nested_goals)
500
+ ecx. eq_term_and_make_canonical_response ( goal, Certainty :: Yes , metadata_ty)
488
501
} )
489
502
}
490
503
0 commit comments