@@ -344,34 +344,57 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
344
344
) -> ProcessResult < PendingPredicateObligation < ' tcx > , FulfillmentErrorCode < ' tcx > > {
345
345
pending_obligation. stalled_on . truncate ( 0 ) ;
346
346
347
+ let infcx = self . selcx . infcx ( ) ;
347
348
let obligation = & mut pending_obligation. obligation ;
348
349
349
350
debug ! ( ?obligation, "process_obligation pre-resolve" ) ;
350
-
351
351
if obligation. predicate . has_infer_types_or_consts ( ) {
352
- obligation. predicate =
353
- self . selcx . infcx ( ) . resolve_vars_if_possible ( obligation. predicate ) ;
354
- }
355
-
356
- debug ! ( ?obligation, ?obligation. cause, "process_obligation" ) ;
352
+ let mut predicate_changed = false ;
357
353
358
- let infcx = self . selcx . infcx ( ) ;
354
+ if obligation. predicate . has_late_bound_vars_in_projection ( ) {
355
+ let mut obligations = Vec :: new ( ) ;
356
+ let predicate = crate :: traits:: project:: try_normalize_with_depth_to (
357
+ self . selcx ,
358
+ obligation. param_env ,
359
+ obligation. cause . clone ( ) ,
360
+ obligation. recursion_depth + 1 ,
361
+ obligation. predicate ,
362
+ & mut obligations,
363
+ ) ;
364
+ if predicate != obligation. predicate {
365
+ if obligations. is_empty ( ) {
366
+ debug ! (
367
+ "progress_changed_obligations: late-bound predicate updated, fast path: {} => {}" ,
368
+ obligation. predicate, predicate
369
+ ) ;
370
+ // Optimization, since we don't need to return with Changed if we're
371
+ // just updating the predicate to a new normalized form.
372
+ predicate_changed = true ;
373
+ obligation. predicate = predicate;
374
+ } else {
375
+ debug ! (
376
+ "progress_changed_obligations: late-bound predicate updated, slow path: {} => {}, additional obligations: {:?}" ,
377
+ obligation. predicate, predicate, obligations
378
+ ) ;
379
+ obligations. push ( obligation. with ( predicate) ) ;
380
+ return ProcessResult :: Changed ( mk_pending ( obligations) ) ;
381
+ }
382
+ } else {
383
+ debug ! (
384
+ "progress_changed_obligations: late-bound predicate not updated: {}" ,
385
+ obligation. predicate
386
+ ) ;
387
+ }
388
+ }
359
389
360
- if obligation. predicate . has_projections ( ) {
361
- let mut obligations = Vec :: new ( ) ;
362
- let predicate = crate :: traits:: project:: try_normalize_with_depth_to (
363
- self . selcx ,
364
- obligation. param_env ,
365
- obligation. cause . clone ( ) ,
366
- obligation. recursion_depth + 1 ,
367
- obligation. predicate ,
368
- & mut obligations,
369
- ) ;
370
- if predicate != obligation. predicate {
371
- obligations. push ( obligation. with ( predicate) ) ;
372
- return ProcessResult :: Changed ( mk_pending ( obligations) ) ;
390
+ if !predicate_changed {
391
+ obligation. predicate =
392
+ self . selcx . infcx ( ) . resolve_vars_if_possible ( obligation. predicate ) ;
373
393
}
374
394
}
395
+
396
+ debug ! ( ?obligation, ?obligation. cause, "process_obligation" ) ;
397
+
375
398
let binder = obligation. predicate . kind ( ) ;
376
399
match binder. no_bound_vars ( ) {
377
400
None => match binder. skip_binder ( ) {
0 commit comments