@@ -528,6 +528,7 @@ impl Ord for DepsFrame {
528
528
}
529
529
}
530
530
531
+ #[ derive( Clone ) ]
531
532
struct BacktrackFrame < ' a > {
532
533
cur : usize ,
533
534
context_backup : Context < ' a > ,
@@ -543,10 +544,20 @@ struct RemainingCandidates {
543
544
remaining : RcVecIter < Candidate > ,
544
545
// note: change to RcList or something if clone is to expensive
545
546
conflicting_prev_active : HashSet < PackageId > ,
547
+ // This is a inlined peekable generator
548
+ has_another : Option < Candidate > ,
546
549
}
547
550
548
551
impl RemainingCandidates {
549
- fn next ( & mut self , prev_active : & [ Summary ] ) -> Result < Candidate , HashSet < PackageId > > {
552
+ fn new ( candidates : & Rc < Vec < Candidate > > ) -> RemainingCandidates {
553
+ RemainingCandidates {
554
+ remaining : RcVecIter :: new ( Rc :: clone ( candidates) ) ,
555
+ conflicting_prev_active : HashSet :: new ( ) ,
556
+ has_another : None ,
557
+ }
558
+ }
559
+
560
+ fn next ( & mut self , prev_active : & [ Summary ] ) -> Result < ( Candidate , bool ) , HashSet < PackageId > > {
550
561
// Filter the set of candidates based on the previously activated
551
562
// versions for this dependency. We can actually use a version if it
552
563
// precisely matches an activated version or if it is otherwise
@@ -559,15 +570,22 @@ impl RemainingCandidates {
559
570
// that conflicted with the ones we tried. If any of these change
560
571
// then we would have considered different candidates.
561
572
for ( _, b) in self . remaining . by_ref ( ) {
562
- if let Some ( a) = prev_active. iter ( ) . find ( |a| compatible ( a. version ( ) , b. summary . version ( ) ) ) {
573
+ if let Some ( a) = prev_active
574
+ . iter ( )
575
+ . find ( |a| compatible ( a. version ( ) , b. summary . version ( ) ) )
576
+ {
563
577
if * a != b. summary {
564
578
self . conflicting_prev_active . insert ( a. package_id ( ) . clone ( ) ) ;
565
- continue
579
+ continue ;
566
580
}
567
581
}
568
- return Ok ( b) ;
582
+ if let Some ( r) = :: std:: mem:: replace ( & mut self . has_another , Some ( b) ) {
583
+ return Ok ( ( r, true ) ) ;
584
+ }
569
585
}
570
- Err ( self . conflicting_prev_active . clone ( ) )
586
+ :: std:: mem:: replace ( & mut self . has_another , None )
587
+ . map ( |r| ( r, false ) )
588
+ . ok_or_else ( || self . conflicting_prev_active . clone ( ) )
571
589
}
572
590
}
573
591
@@ -652,20 +670,10 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
652
670
let ( mut parent, ( mut cur, ( mut dep, candidates, mut features) ) ) = frame;
653
671
assert ! ( !remaining_deps. is_empty( ) ) ;
654
672
655
- let ( next, has_another, remaining_candidates) = {
656
- let prev_active = cx. prev_active ( & dep) ;
657
- trace ! ( "{}[{}]>{} {} candidates" , parent. name( ) , cur, dep. name( ) ,
658
- candidates. len( ) ) ;
659
- trace ! ( "{}[{}]>{} {} prev activations" , parent. name( ) , cur,
660
- dep. name( ) , prev_active. len( ) ) ;
661
- let mut candidates = RemainingCandidates {
662
- remaining : RcVecIter :: new ( Rc :: clone ( & candidates) ) ,
663
- conflicting_prev_active : HashSet :: new ( ) ,
664
- } ;
665
- ( candidates. next ( prev_active) ,
666
- candidates. clone ( ) . next ( prev_active) . is_ok ( ) ,
667
- candidates)
668
- } ;
673
+ trace ! ( "{}[{}]>{} {} candidates" , parent. name( ) , cur, dep. name( ) , candidates. len( ) ) ;
674
+ trace ! ( "{}[{}]>{} {} prev activations" , parent. name( ) , cur, dep. name( ) , cx. prev_active( & dep) . len( ) ) ;
675
+ let mut remaining_candidates = RemainingCandidates :: new ( & candidates) ;
676
+ let next = remaining_candidates. next ( cx. prev_active ( & dep) ) ;
669
677
670
678
// Alright, for each candidate that's gotten this far, it meets the
671
679
// following requirements:
@@ -680,15 +688,15 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
680
688
// turn. We could possibly fail to activate each candidate, so we try
681
689
// each one in turn.
682
690
let candidate = match next {
683
- Ok ( candidate) => {
691
+ Ok ( ( candidate, has_another ) ) => {
684
692
// We have a candidate. Add an entry to the `backtrack_stack` so
685
693
// we can try the next one if this one fails.
686
694
if has_another {
687
695
backtrack_stack. push ( BacktrackFrame {
688
696
cur,
689
697
context_backup : Context :: clone ( & cx) ,
690
698
deps_backup : <BinaryHeap < DepsFrame > >:: clone ( & remaining_deps) ,
691
- remaining_candidates : remaining_candidates ,
699
+ remaining_candidates,
692
700
parent : Summary :: clone ( & parent) ,
693
701
dep : Dependency :: clone ( & dep) ,
694
702
features : Rc :: clone ( & features) ,
@@ -759,13 +767,7 @@ fn find_candidate<'a>(
759
767
conflicting_activations : & mut HashSet < PackageId > ,
760
768
) -> Option < Candidate > {
761
769
while let Some ( mut frame) = backtrack_stack. pop ( ) {
762
- let ( next, has_another) = {
763
- let prev_active = frame. context_backup . prev_active ( & frame. dep ) ;
764
- (
765
- frame. remaining_candidates . next ( prev_active) ,
766
- frame. remaining_candidates . clone ( ) . next ( prev_active) . is_ok ( ) ,
767
- )
768
- } ;
770
+ let next= frame. remaining_candidates . next ( frame. context_backup . prev_active ( & frame. dep ) ) ;
769
771
if frame. context_backup . is_active ( parent. package_id ( ) )
770
772
&& conflicting_activations
771
773
. iter ( )
@@ -774,22 +776,16 @@ fn find_candidate<'a>(
774
776
{
775
777
continue ;
776
778
}
777
- if let Ok ( candidate) = next {
778
- * cur = frame. cur ;
779
+ if let Ok ( ( candidate, has_another) ) = next {
779
780
if has_another {
780
- * cx = frame. context_backup . clone ( ) ;
781
- * remaining_deps = frame. deps_backup . clone ( ) ;
782
- * parent = frame. parent . clone ( ) ;
783
- * dep = frame. dep . clone ( ) ;
784
- * features = Rc :: clone ( & frame. features ) ;
785
- backtrack_stack. push ( frame) ;
786
- } else {
787
- * cx = frame. context_backup ;
788
- * remaining_deps = frame. deps_backup ;
789
- * parent = frame. parent ;
790
- * dep = frame. dep ;
791
- * features = frame. features ;
781
+ backtrack_stack. push ( frame. clone ( ) ) ;
792
782
}
783
+ * cur = frame. cur ;
784
+ * cx = frame. context_backup ;
785
+ * remaining_deps = frame. deps_backup ;
786
+ * parent = frame. parent ;
787
+ * dep = frame. dep ;
788
+ * features = frame. features ;
793
789
return Some ( candidate) ;
794
790
}
795
791
}
0 commit comments