@@ -532,6 +532,12 @@ impl Ord for DepsFrame {
532
532
}
533
533
}
534
534
535
+ #[ derive( Clone , PartialOrd , Ord , PartialEq , Eq ) ]
536
+ enum ConflictReason {
537
+ Semver ,
538
+ Links ( String ) ,
539
+ }
540
+
535
541
struct BacktrackFrame < ' a > {
536
542
cur : usize ,
537
543
context_backup : Context < ' a > ,
@@ -540,18 +546,18 @@ struct BacktrackFrame<'a> {
540
546
parent : Summary ,
541
547
dep : Dependency ,
542
548
features : Rc < Vec < String > > ,
543
- conflicting_activations : HashSet < PackageId > ,
549
+ conflicting_activations : HashMap < PackageId , ConflictReason > ,
544
550
}
545
551
546
552
#[ derive( Clone ) ]
547
553
struct RemainingCandidates {
548
554
remaining : RcVecIter < Candidate > ,
549
555
// note: change to RcList or something if clone is to expensive
550
- conflicting_prev_active : HashSet < PackageId > ,
556
+ conflicting_prev_active : HashMap < PackageId , ConflictReason > ,
551
557
}
552
558
553
559
impl RemainingCandidates {
554
- fn next ( & mut self , prev_active : & [ Summary ] , links : & HashMap < String , PackageId > ) -> Result < Candidate , HashSet < PackageId > > {
560
+ fn next ( & mut self , prev_active : & [ Summary ] , links : & HashMap < String , PackageId > ) -> Result < Candidate , HashMap < PackageId , ConflictReason > > {
555
561
// Filter the set of candidates based on the previously activated
556
562
// versions for this dependency. We can actually use a version if it
557
563
// precisely matches an activated version or if it is otherwise
@@ -565,15 +571,17 @@ impl RemainingCandidates {
565
571
// that conflicted with the ones we tried. If any of these change
566
572
// then we would have considered different candidates.
567
573
for ( _, b) in self . remaining . by_ref ( ) {
568
- if let Some ( a) = b. summary . links ( ) . and_then ( |l| links. get ( l) ) {
569
- if a != b. summary . package_id ( ) {
570
- self . conflicting_prev_active . insert ( a. clone ( ) ) ;
571
- continue
574
+ if let Some ( link) = b. summary . links ( ) {
575
+ if let Some ( a) = links. get ( link) {
576
+ if a != b. summary . package_id ( ) {
577
+ self . conflicting_prev_active . insert ( a. clone ( ) , ConflictReason :: Links ( link. to_owned ( ) ) ) ;
578
+ continue
579
+ }
572
580
}
573
581
}
574
582
if let Some ( a) = prev_active. iter ( ) . find ( |a| compatible ( a. version ( ) , b. summary . version ( ) ) ) {
575
583
if * a != b. summary {
576
- self . conflicting_prev_active . insert ( a. package_id ( ) . clone ( ) ) ;
584
+ self . conflicting_prev_active . insert ( a. package_id ( ) . clone ( ) , ConflictReason :: Semver ) ;
577
585
continue
578
586
}
579
587
}
@@ -673,9 +681,9 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>,
673
681
dep. name( ) , prev_active. len( ) ) ;
674
682
let mut candidates = RemainingCandidates {
675
683
remaining : RcVecIter :: new ( Rc :: clone ( & candidates) ) ,
676
- conflicting_prev_active : HashSet :: new ( ) ,
684
+ conflicting_prev_active : HashMap :: new ( ) ,
677
685
} ;
678
- conflicting_activations = HashSet :: new ( ) ;
686
+ conflicting_activations = HashMap :: new ( ) ;
679
687
( candidates. next ( prev_active, & cx. links ) ,
680
688
candidates. clone ( ) . next ( prev_active, & cx. links ) . is_ok ( ) ,
681
689
candidates)
@@ -772,7 +780,7 @@ fn find_candidate<'a>(
772
780
cur : & mut usize ,
773
781
dep : & mut Dependency ,
774
782
features : & mut Rc < Vec < String > > ,
775
- conflicting_activations : & mut HashSet < PackageId > ,
783
+ conflicting_activations : & mut HashMap < PackageId , ConflictReason > ,
776
784
) -> Option < Candidate > {
777
785
while let Some ( mut frame) = backtrack_stack. pop ( ) {
778
786
let ( next, has_another) = {
@@ -786,7 +794,7 @@ fn find_candidate<'a>(
786
794
&& conflicting_activations
787
795
. iter ( )
788
796
// note: a lot of redundant work in is_active for similar debs
789
- . all ( |con| frame. context_backup . is_active ( con) )
797
+ . all ( |( con, _ ) | frame. context_backup . is_active ( con) )
790
798
{
791
799
continue ;
792
800
}
@@ -818,7 +826,7 @@ fn activation_error(cx: &Context,
818
826
registry : & mut Registry ,
819
827
parent : & Summary ,
820
828
dep : & Dependency ,
821
- conflicting_activations : HashSet < PackageId > ,
829
+ conflicting_activations : HashMap < PackageId , ConflictReason > ,
822
830
candidates : & [ Candidate ] ,
823
831
config : Option < & Config > ) -> CargoError {
824
832
let graph = cx. graph ( ) ;
@@ -842,9 +850,17 @@ fn activation_error(cx: &Context,
842
850
msg. push_str ( & describe_path ( parent. package_id ( ) ) ) ;
843
851
let mut conflicting_activations: Vec < _ > = conflicting_activations. iter ( ) . collect ( ) ;
844
852
conflicting_activations. sort_unstable ( ) ;
845
- for v in conflicting_activations. iter ( ) . rev ( ) {
853
+ for & ( p, r) in conflicting_activations. iter ( ) . rev ( ) {
854
+ match r {
855
+ & ConflictReason :: Links ( ref link) => {
856
+ msg. push_str ( "\n multiple packages link to native library `" ) ;
857
+ msg. push_str ( link) ;
858
+ msg. push_str ( "`, but a native library can be linked only once." )
859
+ } ,
860
+ _ => ( ) ,
861
+ }
846
862
msg. push_str ( "\n previously selected " ) ;
847
- msg. push_str ( & describe_path ( v ) ) ;
863
+ msg. push_str ( & describe_path ( p ) ) ;
848
864
}
849
865
850
866
msg. push_str ( "\n possible versions to select: " ) ;
0 commit comments