@@ -97,7 +97,17 @@ pub trait ObligationProcessor {
97
97
type Error : Debug ;
98
98
type OUT : OutcomeTrait < Obligation = Self :: Obligation , Error = Error < Self :: Obligation , Self :: Error > > ;
99
99
100
- fn needs_process_obligation ( & self , obligation : & Self :: Obligation ) -> bool ;
100
+ /// Implementations can provide a fast-path to obligation-processing
101
+ /// by counting the prefix of the passed iterator for which
102
+ /// `needs_process_obligation` would return false.
103
+ fn skippable_obligations < ' a > (
104
+ & ' a self ,
105
+ _it : impl Iterator < Item = & ' a Self :: Obligation > ,
106
+ ) -> usize {
107
+ 0
108
+ }
109
+
110
+ fn needs_process_obligation ( & self , _obligation : & Self :: Obligation ) -> bool ;
101
111
102
112
fn process_obligation (
103
113
& mut self ,
@@ -416,6 +426,10 @@ impl<O: ForestObligation> ObligationForest<O> {
416
426
loop {
417
427
let mut has_changed = false ;
418
428
429
+ // This is the super fast path for cheap-to-check conditions.
430
+ let mut index =
431
+ processor. skippable_obligations ( self . nodes . iter ( ) . map ( |n| & n. obligation ) ) ;
432
+
419
433
// Note that the loop body can append new nodes, and those new nodes
420
434
// will then be processed by subsequent iterations of the loop.
421
435
//
@@ -424,9 +438,8 @@ impl<O: ForestObligation> ObligationForest<O> {
424
438
// `for index in 0..self.nodes.len() { ... }` because the range would
425
439
// be computed with the initial length, and we would miss the appended
426
440
// nodes. Therefore we use a `while` loop.
427
- let mut index = 0 ;
428
441
while let Some ( node) = self . nodes . get_mut ( index) {
429
- // This test is extremely hot .
442
+ // This is the moderately fast path when the prefix skipping above didn't work out .
430
443
if node. state . get ( ) != NodeState :: Pending
431
444
|| !processor. needs_process_obligation ( & node. obligation )
432
445
{
0 commit comments