@@ -547,6 +547,7 @@ impl ConflictReason {
547
547
}
548
548
}
549
549
550
+ #[ derive( Clone ) ]
550
551
struct BacktrackFrame < ' a > {
551
552
cur : usize ,
552
553
context_backup : Context < ' a > ,
@@ -562,10 +563,20 @@ struct RemainingCandidates {
562
563
remaining : RcVecIter < Candidate > ,
563
564
// note: change to RcList or something if clone is to expensive
564
565
conflicting_prev_active : HashMap < PackageId , ConflictReason > ,
566
+ // This is a inlined peekable generator
567
+ has_another : Option < Candidate > ,
565
568
}
566
569
567
570
impl RemainingCandidates {
568
- fn next ( & mut self , prev_active : & [ Summary ] , links : & HashMap < String , PackageId > ) -> Result < Candidate , HashMap < PackageId , ConflictReason > > {
571
+ fn new ( candidates : & Rc < Vec < Candidate > > ) -> RemainingCandidates {
572
+ RemainingCandidates {
573
+ remaining : RcVecIter :: new ( Rc :: clone ( candidates) ) ,
574
+ conflicting_prev_active : HashMap :: new ( ) ,
575
+ has_another : None ,
576
+ }
577
+ }
578
+
579
+ fn next ( & mut self , prev_active : & [ Summary ] , links : & HashMap < String , PackageId > ) -> Result < ( Candidate , bool ) , HashMap < PackageId , ConflictReason > > {
569
580
// Filter the set of candidates based on the previously activated
570
581
// versions for this dependency. We can actually use a version if it
571
582
// precisely matches an activated version or if it is otherwise
@@ -578,6 +589,7 @@ impl RemainingCandidates {
578
589
// When we are done we return the set of previously activated
579
590
// that conflicted with the ones we tried. If any of these change
580
591
// then we would have considered different candidates.
592
+ use std:: mem:: replace;
581
593
for ( _, b) in self . remaining . by_ref ( ) {
582
594
if let Some ( link) = b. summary . links ( ) {
583
595
if let Some ( a) = links. get ( link) {
@@ -587,15 +599,22 @@ impl RemainingCandidates {
587
599
}
588
600
}
589
601
}
590
- if let Some ( a) = prev_active. iter ( ) . find ( |a| compatible ( a. version ( ) , b. summary . version ( ) ) ) {
602
+ if let Some ( a) = prev_active
603
+ . iter ( )
604
+ . find ( |a| compatible ( a. version ( ) , b. summary . version ( ) ) )
605
+ {
591
606
if * a != b. summary {
592
607
self . conflicting_prev_active . insert ( a. package_id ( ) . clone ( ) , ConflictReason :: Semver ) ;
593
- continue
608
+ continue ;
594
609
}
595
610
}
596
- return Ok ( b) ;
611
+ if let Some ( r) = replace ( & mut self . has_another , Some ( b) ) {
612
+ return Ok ( ( r, true ) ) ;
613
+ }
597
614
}
598
- Err ( self . conflicting_prev_active . clone ( ) )
615
+ replace ( & mut self . has_another , None )
616
+ . map ( |r| ( r, false ) )
617
+ . ok_or_else ( || self . conflicting_prev_active . clone ( ) )
599
618
}
600
619
}
601
620
@@ -604,11 +623,12 @@ impl RemainingCandidates {
604
623
///
605
624
/// If all dependencies can be activated and resolved to a version in the
606
625
/// dependency graph, cx.resolve is returned.
607
- fn activate_deps_loop < ' a > ( mut cx : Context < ' a > ,
608
- registry : & mut Registry ,
609
- summaries : & [ ( Summary , Method ) ] ,
610
- config : Option < & Config > )
611
- -> CargoResult < Context < ' a > > {
626
+ fn activate_deps_loop < ' a > (
627
+ mut cx : Context < ' a > ,
628
+ registry : & mut Registry ,
629
+ summaries : & [ ( Summary , Method ) ] ,
630
+ config : Option < & Config > ,
631
+ ) -> CargoResult < Context < ' a > > {
612
632
// Note that a `BinaryHeap` is used for the remaining dependencies that need
613
633
// activation. This heap is sorted such that the "largest value" is the most
614
634
// constrained dependency, or the one with the least candidates.
@@ -620,7 +640,10 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
620
640
let mut remaining_deps = BinaryHeap :: new ( ) ;
621
641
for & ( ref summary, ref method) in summaries {
622
642
debug ! ( "initial activation: {}" , summary. package_id( ) ) ;
623
- let candidate = Candidate { summary : summary. clone ( ) , replace : None } ;
643
+ let candidate = Candidate {
644
+ summary : summary. clone ( ) ,
645
+ replace : None ,
646
+ } ;
624
647
let res = activate ( & mut cx, registry, None , candidate, method) ?;
625
648
if let Some ( ( frame, _) ) = res {
626
649
remaining_deps. push ( frame) ;
@@ -647,7 +670,6 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
647
670
// backtracking states where if we hit an error we can return to in order to
648
671
// attempt to continue resolving.
649
672
while let Some ( mut deps_frame) = remaining_deps. pop ( ) {
650
-
651
673
// If we spend a lot of time here (we shouldn't in most cases) then give
652
674
// a bit of a visual indicator as to what we're doing. Only enable this
653
675
// when stderr is a tty (a human is likely to be watching) to ensure we
@@ -659,10 +681,8 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
659
681
// to amortize the cost of the current time lookup.
660
682
ticks += 1 ;
661
683
if let Some ( config) = config {
662
- if config. shell ( ) . is_err_tty ( ) &&
663
- !printed &&
664
- ticks % 1000 == 0 &&
665
- start. elapsed ( ) - deps_time > time_to_print
684
+ if config. shell ( ) . is_err_tty ( ) && !printed && ticks % 1000 == 0
685
+ && start. elapsed ( ) - deps_time > time_to_print
666
686
{
667
687
printed = true ;
668
688
config. shell ( ) . status ( "Resolving" , "dependency graph..." ) ?;
@@ -680,20 +700,10 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
680
700
let ( mut parent, ( mut cur, ( mut dep, candidates, mut features) ) ) = frame;
681
701
assert ! ( !remaining_deps. is_empty( ) ) ;
682
702
683
- let ( next, has_another, remaining_candidates) = {
684
- let prev_active = cx. prev_active ( & dep) ;
685
- trace ! ( "{}[{}]>{} {} candidates" , parent. name( ) , cur, dep. name( ) ,
686
- candidates. len( ) ) ;
687
- trace ! ( "{}[{}]>{} {} prev activations" , parent. name( ) , cur,
688
- dep. name( ) , prev_active. len( ) ) ;
689
- let mut candidates = RemainingCandidates {
690
- remaining : RcVecIter :: new ( Rc :: clone ( & candidates) ) ,
691
- conflicting_prev_active : HashMap :: new ( ) ,
692
- } ;
693
- ( candidates. next ( prev_active, & cx. links ) ,
694
- candidates. clone ( ) . next ( prev_active, & cx. links ) . is_ok ( ) ,
695
- candidates)
696
- } ;
703
+ trace ! ( "{}[{}]>{} {} candidates" , parent. name( ) , cur, dep. name( ) , candidates. len( ) ) ;
704
+ trace ! ( "{}[{}]>{} {} prev activations" , parent. name( ) , cur, dep. name( ) , cx. prev_active( & dep) . len( ) ) ;
705
+ let mut remaining_candidates = RemainingCandidates :: new ( & candidates) ;
706
+ let next = remaining_candidates. next ( cx. prev_active ( & dep) , & cx. links ) ;
697
707
698
708
// Alright, for each candidate that's gotten this far, it meets the
699
709
// following requirements:
@@ -707,54 +717,55 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
707
717
// This means that we're going to attempt to activate each candidate in
708
718
// turn. We could possibly fail to activate each candidate, so we try
709
719
// each one in turn.
710
- let candidate = match next {
711
- Ok ( candidate) => {
712
- // We have a candidate. Add an entry to the `backtrack_stack` so
713
- // we can try the next one if this one fails.
714
- if has_another {
715
- backtrack_stack. push ( BacktrackFrame {
716
- cur,
717
- context_backup : Context :: clone ( & cx) ,
718
- deps_backup : <BinaryHeap < DepsFrame > >:: clone ( & remaining_deps) ,
719
- remaining_candidates,
720
- parent : Summary :: clone ( & parent) ,
721
- dep : Dependency :: clone ( & dep) ,
722
- features : Rc :: clone ( & features) ,
723
- } ) ;
724
- }
725
- candidate
726
- }
727
- Err ( mut conflicting) => {
728
- // This dependency has no valid candidate. Backtrack until we
729
- // find a dependency that does have a candidate to try, and try
730
- // to activate that one. This resets the `remaining_deps` to
731
- // their state at the found level of the `backtrack_stack`.
732
- trace ! ( "{}[{}]>{} -- no candidates" , parent. name( ) , cur,
733
- dep. name( ) ) ;
734
- match find_candidate ( & mut backtrack_stack,
735
- & mut cx,
736
- & mut remaining_deps,
737
- & mut parent,
738
- & mut cur,
739
- & mut dep,
740
- & mut features,
741
- & mut conflicting) {
742
- None => return Err ( activation_error ( & cx, registry, & parent,
743
- & dep,
744
- conflicting,
745
- & candidates, config) ) ,
746
- Some ( candidate) => candidate,
747
- }
748
- }
749
- } ;
720
+ let ( candidate, has_another) = next. or_else ( |mut conflicting| {
721
+ // This dependency has no valid candidate. Backtrack until we
722
+ // find a dependency that does have a candidate to try, and try
723
+ // to activate that one. This resets the `remaining_deps` to
724
+ // their state at the found level of the `backtrack_stack`.
725
+ trace ! ( "{}[{}]>{} -- no candidates" , parent. name( ) , cur, dep. name( ) ) ;
726
+ find_candidate (
727
+ & mut backtrack_stack,
728
+ & mut cx,
729
+ & mut remaining_deps,
730
+ & mut parent,
731
+ & mut cur,
732
+ & mut dep,
733
+ & mut features,
734
+ & mut remaining_candidates,
735
+ & mut conflicting,
736
+ ) . ok_or_else ( || {
737
+ activation_error (
738
+ & cx,
739
+ registry,
740
+ & parent,
741
+ & dep,
742
+ conflicting,
743
+ & candidates,
744
+ config,
745
+ )
746
+ } )
747
+ } ) ?;
748
+
749
+ // We have a candidate. Add an entry to the `backtrack_stack` so
750
+ // we can try the next one if this one fails.
751
+ if has_another {
752
+ backtrack_stack. push ( BacktrackFrame {
753
+ cur,
754
+ context_backup : Context :: clone ( & cx) ,
755
+ deps_backup : <BinaryHeap < DepsFrame > >:: clone ( & remaining_deps) ,
756
+ remaining_candidates,
757
+ parent : Summary :: clone ( & parent) ,
758
+ dep : Dependency :: clone ( & dep) ,
759
+ features : Rc :: clone ( & features) ,
760
+ } ) ;
761
+ }
750
762
751
763
let method = Method :: Required {
752
764
dev_deps : false ,
753
765
features : & features,
754
766
uses_default_features : dep. uses_default_features ( ) ,
755
767
} ;
756
- trace ! ( "{}[{}]>{} trying {}" , parent. name( ) , cur, dep. name( ) ,
757
- candidate. summary. version( ) ) ;
768
+ trace ! ( "{}[{}]>{} trying {}" , parent. name( ) , cur, dep. name( ) , candidate. summary. version( ) ) ;
758
769
let res = activate ( & mut cx, registry, Some ( & parent) , candidate, & method) ?;
759
770
if let Some ( ( frame, dur) ) = res {
760
771
remaining_deps. push ( frame) ;
@@ -784,16 +795,11 @@ fn find_candidate<'a>(
784
795
cur : & mut usize ,
785
796
dep : & mut Dependency ,
786
797
features : & mut Rc < Vec < String > > ,
798
+ remaining_candidates : & mut RemainingCandidates ,
787
799
conflicting_activations : & mut HashMap < PackageId , ConflictReason > ,
788
- ) -> Option < Candidate > {
800
+ ) -> Option < ( Candidate , bool ) > {
789
801
while let Some ( mut frame) = backtrack_stack. pop ( ) {
790
- let ( next, has_another) = {
791
- let prev_active = frame. context_backup . prev_active ( & frame. dep ) ;
792
- (
793
- frame. remaining_candidates . next ( prev_active, & frame. context_backup . links ) ,
794
- frame. remaining_candidates . clone ( ) . next ( prev_active, & frame. context_backup . links ) . is_ok ( ) ,
795
- )
796
- } ;
802
+ let next= frame. remaining_candidates . next ( frame. context_backup . prev_active ( & frame. dep ) , & frame. context_backup . links ) ;
797
803
if frame. context_backup . is_active ( parent. package_id ( ) )
798
804
&& conflicting_activations
799
805
. iter ( )
@@ -802,23 +808,15 @@ fn find_candidate<'a>(
802
808
{
803
809
continue ;
804
810
}
805
- if let Ok ( candidate) = next {
811
+ if let Ok ( ( candidate, has_another ) ) = next {
806
812
* cur = frame. cur ;
807
- if has_another {
808
- * cx = frame. context_backup . clone ( ) ;
809
- * remaining_deps = frame. deps_backup . clone ( ) ;
810
- * parent = frame. parent . clone ( ) ;
811
- * dep = frame. dep . clone ( ) ;
812
- * features = Rc :: clone ( & frame. features ) ;
813
- backtrack_stack. push ( frame) ;
814
- } else {
815
- * cx = frame. context_backup ;
816
- * remaining_deps = frame. deps_backup ;
817
- * parent = frame. parent ;
818
- * dep = frame. dep ;
819
- * features = frame. features ;
820
- }
821
- return Some ( candidate) ;
813
+ * cx = frame. context_backup ;
814
+ * remaining_deps = frame. deps_backup ;
815
+ * parent = frame. parent ;
816
+ * dep = frame. dep ;
817
+ * features = frame. features ;
818
+ * remaining_candidates = frame. remaining_candidates ;
819
+ return Some ( ( candidate, has_another) ) ;
822
820
}
823
821
}
824
822
None
0 commit comments