@@ -256,29 +256,46 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
256256 & mut self ,
257257 pending_obligation : & mut Self :: Obligation ,
258258 ) -> 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
271272 }
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+ } ) ( )
278284 }
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 ;
280293 }
281294
295+ // This part of the code is much colder.
296+
297+ pending_obligation. stalled_on . truncate ( 0 ) ;
298+
282299 let obligation = & mut pending_obligation. obligation ;
283300
284301 if obligation. predicate . has_infer_types ( ) {
0 commit comments