@@ -256,29 +256,46 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
256
256
& mut self ,
257
257
pending_obligation : & mut Self :: Obligation ,
258
258
) -> ProcessResult < Self :: Obligation , Self :: Error > {
259
- // If we were stalled on some unresolved variables, first check
260
- // whether any of them have been resolved; if not, don't bother
261
- // doing more work yet
262
- if !pending_obligation. stalled_on . is_empty ( ) {
263
- let mut changed = false ;
264
- // This `for` loop was once a call to `all()`, but this lower-level
265
- // form was a perf win. See #64545 for details.
266
- for & ty in & pending_obligation. stalled_on {
267
- if ShallowResolver :: new ( self . selcx . infcx ( ) ) . shallow_resolve_changed ( ty) {
268
- changed = true ;
269
- break ;
270
- }
259
+ // If we were stalled on some unresolved variables, first check whether
260
+ // any of them have been resolved; if not, don't bother doing more work
261
+ // yet.
262
+ let change = match pending_obligation. stalled_on . len ( ) {
263
+ // Match arms are in order of frequency, which matters because this
264
+ // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
265
+ 1 => {
266
+ let ty = pending_obligation. stalled_on [ 0 ] ;
267
+ ShallowResolver :: new ( self . selcx . infcx ( ) ) . shallow_resolve_changed ( ty)
268
+ }
269
+ 0 => {
270
+ // In this case we haven't changed, but wish to make a change.
271
+ true
271
272
}
272
- if !changed {
273
- debug ! ( "process_predicate: pending obligation {:?} still stalled on {:?}" ,
274
- self . selcx. infcx( )
275
- . resolve_vars_if_possible( & pending_obligation. obligation) ,
276
- pending_obligation. stalled_on) ;
277
- return ProcessResult :: Unchanged ;
273
+ _ => {
274
+ // This `for` loop was once a call to `all()`, but this lower-level
275
+ // form was a perf win. See #64545 for details.
276
+ ( || {
277
+ for & ty in & pending_obligation. stalled_on {
278
+ if ShallowResolver :: new ( self . selcx . infcx ( ) ) . shallow_resolve_changed ( ty) {
279
+ return true ;
280
+ }
281
+ }
282
+ false
283
+ } ) ( )
278
284
}
279
- pending_obligation. stalled_on = vec ! [ ] ;
285
+ } ;
286
+
287
+ if !change {
288
+ debug ! ( "process_predicate: pending obligation {:?} still stalled on {:?}" ,
289
+ self . selcx. infcx( )
290
+ . resolve_vars_if_possible( & pending_obligation. obligation) ,
291
+ pending_obligation. stalled_on) ;
292
+ return ProcessResult :: Unchanged ;
280
293
}
281
294
295
+ // This part of the code is much colder.
296
+
297
+ pending_obligation. stalled_on . truncate ( 0 ) ;
298
+
282
299
let obligation = & mut pending_obligation. obligation ;
283
300
284
301
if obligation. predicate . has_infer_types ( ) {
0 commit comments