@@ -607,7 +607,11 @@ fn activate(
607
607
// TODO: this disable is not a long term solution.
608
608
// This needs to be removed before public dependencies are stabilized!
609
609
if dep. platform ( ) . is_none ( ) && dep. explicit_name_in_toml ( ) . is_none ( ) {
610
- let cs: Vec < PackageId > = cx
610
+ // one tricky part is that `candidate_pid` may already be active and
611
+ // have public dependencies of its own. So we not only need to mark
612
+ // `candidate_pid` as visible to its parents but also all of its existing
613
+ // public dependencies.
614
+ let existing_public_deps: Vec < PackageId > = cx
611
615
. public_dependency
612
616
. get ( & candidate_pid)
613
617
. iter ( )
@@ -616,24 +620,34 @@ fn activate(
616
620
. chain ( & Some ( candidate_pid) )
617
621
. cloned ( )
618
622
. collect ( ) ;
619
- for c in cs {
623
+ for c in existing_public_deps {
624
+ // for each (transitive) parent that can newly see `t`
620
625
let mut stack = vec ! [ ( parent_pid, dep. is_public( ) ) ] ;
621
626
while let Some ( ( p, public) ) = stack. pop ( ) {
622
627
match cx. public_dependency . entry ( p) . or_default ( ) . entry ( c. name ( ) ) {
623
628
im_rc:: hashmap:: Entry :: Occupied ( mut o) => {
629
+ // the (transitive) parent can already see something by `c`s name, it had better be `c`.
624
630
assert_eq ! ( o. get( ) . 0 , c) ;
625
631
if o. get ( ) . 1 {
632
+ // The previous time the parent saw `c`, it was a public dependency.
633
+ // So all of its parents already know about `c`
634
+ // and we can save some time by stopping now.
626
635
continue ;
627
636
}
628
637
if public {
638
+ // Mark that `c` has now bean seen publicly
629
639
o. insert ( ( c, public) ) ;
630
640
}
631
641
}
632
642
im_rc:: hashmap:: Entry :: Vacant ( v) => {
643
+ // The (transitive) parent does not have anything by `c`s name,
644
+ // so we add `c`.
633
645
v. insert ( ( c, public) ) ;
634
646
}
635
647
}
648
+ // if `candidate_pid` was a private dependency of `p` then `p` parents can't see `c` thru `p`
636
649
if public {
650
+ // if it was public, then we add all of `p`s parents to be checked
637
651
for & ( grand, ref d) in cx. parents . edges ( & p) {
638
652
stack. push ( ( grand, d. iter ( ) . any ( |x| x. is_public ( ) ) ) ) ;
639
653
}
@@ -788,25 +802,32 @@ impl RemainingCandidates {
788
802
// TODO: this disable is not a long term solution.
789
803
// This needs to be removed before public dependencies are stabilized!
790
804
if dep. platform ( ) . is_none ( ) && dep. explicit_name_in_toml ( ) . is_none ( ) {
791
- for & t in cx
805
+ let existing_public_deps : Vec < PackageId > = cx
792
806
. public_dependency
793
807
. get ( & b. summary . package_id ( ) )
794
808
. iter ( )
795
809
. flat_map ( |x| x. values ( ) )
796
810
. filter_map ( |x| if x. 1 { Some ( & x. 0 ) } else { None } )
797
811
. chain ( & Some ( b. summary . package_id ( ) ) )
798
- {
812
+ . cloned ( )
813
+ . collect ( ) ;
814
+ for t in existing_public_deps {
815
+ // for each (transitive) parent that can newly see `t`
799
816
let mut stack = vec ! [ ( parent, dep. is_public( ) ) ] ;
800
817
while let Some ( ( p, public) ) = stack. pop ( ) {
801
818
// TODO: dont look at the same thing more then once
802
819
if let Some ( o) = cx. public_dependency . get ( & p) . and_then ( |x| x. get ( & t. name ( ) ) )
803
820
{
804
821
if o. 0 != t {
822
+ // the (transitive) parent can already see a different version by `t`s name.
823
+ // So, adding `b` will cause `p` to have a public dependency conflict on `t`.
805
824
conflicting_prev_active. insert ( p, ConflictReason :: PublicDependency ) ;
806
825
continue ' main;
807
826
}
808
827
}
828
+ // if `b` was a private dependency of `p` then `p` parents can't see `t` thru `p`
809
829
if public {
830
+ // if it was public, then we add all of `p`s parents to be checked
810
831
for & ( grand, ref d) in cx. parents . edges ( & p) {
811
832
stack. push ( ( grand, d. iter ( ) . any ( |x| x. is_public ( ) ) ) ) ;
812
833
}
0 commit comments