@@ -257,7 +257,12 @@ fn activate_deps_loop(
257
257
let mut backtracked = false ;
258
258
259
259
loop {
260
- let next = remaining_candidates. next ( & mut conflicting_activations, & cx, & dep) ;
260
+ let next = remaining_candidates. next (
261
+ & mut conflicting_activations,
262
+ & cx,
263
+ & dep,
264
+ parent. package_id ( ) ,
265
+ ) ;
261
266
262
267
let ( candidate, has_another) = next. ok_or ( ( ) ) . or_else ( |_| {
263
268
// If we get here then our `remaining_candidates` was just
@@ -596,6 +601,33 @@ fn activate(
596
601
. link ( candidate. summary . package_id ( ) , parent. package_id ( ) ) ,
597
602
)
598
603
. push ( dep. clone ( ) ) ;
604
+ let mut stack = vec ! [ ( parent. package_id( ) , dep. is_public( ) ) ] ;
605
+ while let Some ( ( p, public) ) = stack. pop ( ) {
606
+ match cx
607
+ . public_dependency
608
+ . entry ( p)
609
+ . or_default ( )
610
+ . entry ( candidate. summary . name ( ) )
611
+ {
612
+ im_rc:: hashmap:: Entry :: Occupied ( mut o) => {
613
+ assert_eq ! ( o. get( ) . 0 , candidate. summary. package_id( ) ) ;
614
+ if o. get ( ) . 1 {
615
+ continue ;
616
+ }
617
+ if public {
618
+ o. insert ( ( candidate. summary . package_id ( ) , public) ) ;
619
+ }
620
+ }
621
+ im_rc:: hashmap:: Entry :: Vacant ( v) => {
622
+ v. insert ( ( candidate. summary . package_id ( ) , public) ) ;
623
+ }
624
+ }
625
+ if public {
626
+ for & ( grand, ref d) in cx. parents . edges ( & p) {
627
+ stack. push ( ( grand, d. iter ( ) . any ( |x| x. is_public ( ) ) ) ) ;
628
+ }
629
+ }
630
+ }
599
631
}
600
632
601
633
let activated = cx. flag_activated ( & candidate. summary , method) ?;
@@ -692,10 +724,11 @@ impl RemainingCandidates {
692
724
conflicting_prev_active : & mut BTreeMap < PackageId , ConflictReason > ,
693
725
cx : & Context ,
694
726
dep : & Dependency ,
727
+ parent : PackageId ,
695
728
) -> Option < ( Candidate , bool ) > {
696
729
let prev_active = cx. prev_active ( dep) ;
697
730
698
- for ( _, b) in self . remaining . by_ref ( ) {
731
+ ' main : for ( _, b) in self . remaining . by_ref ( ) {
699
732
// The `links` key in the manifest dictates that there's only one
700
733
// package in a dependency graph, globally, with that particular
701
734
// `links` key. If this candidate links to something that's already
@@ -731,6 +764,26 @@ impl RemainingCandidates {
731
764
}
732
765
}
733
766
767
+ let mut stack = vec ! [ ( parent, dep. is_public( ) ) ] ;
768
+ while let Some ( ( p, public) ) = stack. pop ( ) {
769
+ // TODO: dont look at the same thing more then once
770
+ if let Some ( o) = cx
771
+ . public_dependency
772
+ . get ( & p)
773
+ . and_then ( |x| x. get ( & b. summary . name ( ) ) )
774
+ {
775
+ if o. 0 != b. summary . package_id ( ) {
776
+ // TODO: conflicting_prev_active
777
+ continue ' main;
778
+ }
779
+ }
780
+ if public {
781
+ for & ( grand, ref d) in cx. parents . edges ( & p) {
782
+ stack. push ( ( grand, d. iter ( ) . any ( |x| x. is_public ( ) ) ) ) ;
783
+ }
784
+ }
785
+ }
786
+
734
787
// Well if we made it this far then we've got a valid dependency. We
735
788
// want this iterator to be inherently "peekable" so we don't
736
789
// necessarily return the item just yet. Instead we stash it away to
@@ -789,6 +842,7 @@ fn find_candidate(
789
842
& mut frame. conflicting_activations ,
790
843
& frame. context ,
791
844
& frame. dep ,
845
+ frame. parent . package_id ( ) ,
792
846
) ;
793
847
let ( candidate, has_another) = match next {
794
848
Some ( pair) => pair,
0 commit comments