@@ -414,7 +414,7 @@ fn activate(cx: &mut Context,
414
414
parent : Option < & Summary > ,
415
415
candidate : Candidate ,
416
416
method : & Method )
417
- -> CargoResult < Option < ( DepsFrame , Duration ) > > {
417
+ -> ActivateResult < Option < ( DepsFrame , Duration ) > > {
418
418
if let Some ( parent) = parent {
419
419
cx. resolve_graph . push ( GraphNode :: Link ( parent. package_id ( ) . clone ( ) ,
420
420
candidate. summary . package_id ( ) . clone ( ) ) ) ;
@@ -536,14 +536,40 @@ impl Ord for DepsFrame {
536
536
enum ConflictReason {
537
537
Semver ,
538
538
Links ( String ) ,
539
+ MissingFeatures ( String ) ,
540
+ }
541
+
542
+ enum ActivateError {
543
+ Error ( :: failure:: Error ) ,
544
+ Conflict ( PackageId , ConflictReason ) ,
545
+ }
546
+ type ActivateResult < T > = Result < T , ActivateError > ;
547
+
548
+ impl From < :: failure:: Error > for ActivateError {
549
+ fn from ( t : :: failure:: Error ) -> Self {
550
+ ActivateError :: Error ( t)
551
+ }
552
+ }
553
+
554
+ impl From < ( PackageId , ConflictReason ) > for ActivateError {
555
+ fn from ( t : ( PackageId , ConflictReason ) ) -> Self {
556
+ ActivateError :: Conflict ( t. 0 , t. 1 )
557
+ }
539
558
}
540
559
541
560
impl ConflictReason {
542
561
fn is_links ( & self ) -> bool {
543
- match * self {
544
- ConflictReason :: Semver => false ,
545
- ConflictReason :: Links ( _) => true ,
562
+ if let ConflictReason :: Links ( _) = * self {
563
+ return true ;
564
+ }
565
+ false
566
+ }
567
+
568
+ fn is_missing_features ( & self ) -> bool {
569
+ if let ConflictReason :: MissingFeatures ( _) = * self {
570
+ return true ;
546
571
}
572
+ false
547
573
}
548
574
}
549
575
@@ -556,6 +582,7 @@ struct BacktrackFrame<'a> {
556
582
parent : Summary ,
557
583
dep : Dependency ,
558
584
features : Rc < Vec < String > > ,
585
+ conflicting_activations : HashMap < PackageId , ConflictReason > ,
559
586
}
560
587
561
588
#[ derive( Clone ) ]
@@ -652,9 +679,17 @@ fn activate_deps_loop<'a>(
652
679
summary : summary. clone ( ) ,
653
680
replace : None ,
654
681
} ;
655
- let res = activate ( & mut cx, registry, None , candidate, method) ?;
656
- if let Some ( ( frame, _) ) = res {
657
- remaining_deps. push ( frame) ;
682
+ let res = activate ( & mut cx, registry, None , candidate, method) ;
683
+ match res {
684
+ Ok ( Some ( ( frame, _) ) ) => remaining_deps. push ( frame) ,
685
+ Ok ( None ) => ( ) ,
686
+ Err ( ActivateError :: Error ( e) ) => return Err ( e) ,
687
+ Err ( ActivateError :: Conflict ( id, reason) ) => {
688
+ match reason {
689
+ ConflictReason :: MissingFeatures ( features) => bail ! ( "Package `{}` does not have these features: `{}`" , id, features) ,
690
+ _ => panic ! ( "bad error from activate" ) ,
691
+ }
692
+ }
658
693
}
659
694
}
660
695
@@ -713,6 +748,7 @@ fn activate_deps_loop<'a>(
713
748
714
749
let mut remaining_candidates = RemainingCandidates :: new ( & candidates) ;
715
750
let mut successfully_activated = false ;
751
+ let mut conflicting_activations = HashMap :: new ( ) ;
716
752
717
753
while !successfully_activated {
718
754
let next = remaining_candidates. next ( cx. prev_active ( & dep) , & cx. links ) ;
@@ -729,7 +765,8 @@ fn activate_deps_loop<'a>(
729
765
// This means that we're going to attempt to activate each candidate in
730
766
// turn. We could possibly fail to activate each candidate, so we try
731
767
// each one in turn.
732
- let ( candidate, has_another) = next. or_else ( |mut conflicting| {
768
+ let ( candidate, has_another) = next. or_else ( |conflicting| {
769
+ conflicting_activations. extend ( conflicting) ;
733
770
// This dependency has no valid candidate. Backtrack until we
734
771
// find a dependency that does have a candidate to try, and try
735
772
// to activate that one. This resets the `remaining_deps` to
@@ -744,14 +781,16 @@ fn activate_deps_loop<'a>(
744
781
& mut dep,
745
782
& mut features,
746
783
& mut remaining_candidates,
747
- & mut conflicting ,
784
+ & mut conflicting_activations ,
748
785
) . ok_or_else ( || {
786
+ // if we hit an activation error and we are out of other combinations
787
+ // then just report that error
749
788
activation_error (
750
789
& cx,
751
790
registry,
752
791
& parent,
753
792
& dep,
754
- & conflicting ,
793
+ & conflicting_activations ,
755
794
& candidates,
756
795
config,
757
796
)
@@ -770,6 +809,7 @@ fn activate_deps_loop<'a>(
770
809
parent : Summary :: clone ( & parent) ,
771
810
dep : Dependency :: clone ( & dep) ,
772
811
features : Rc :: clone ( & features) ,
812
+ conflicting_activations : conflicting_activations. clone ( ) ,
773
813
} ) ;
774
814
}
775
815
@@ -781,12 +821,14 @@ fn activate_deps_loop<'a>(
781
821
trace ! ( "{}[{}]>{} trying {}" , parent. name( ) , cur, dep. name( ) , candidate. summary. version( ) ) ;
782
822
let res = activate ( & mut cx, registry, Some ( & parent) , candidate, & method) ;
783
823
successfully_activated = res. is_ok ( ) ;
784
- // TODO: disable fast-backtracking
785
- // TODO: save that disable status in backtrack frame
786
- // TODO: integrate with error messages
787
- if let Ok ( Some ( ( frame, dur) ) ) = res {
788
- remaining_deps. push ( frame) ;
789
- deps_time += dur;
824
+ match res {
825
+ Ok ( Some ( ( frame, dur) ) ) => {
826
+ remaining_deps. push ( frame) ;
827
+ deps_time += dur;
828
+ }
829
+ Ok ( None ) => ( ) ,
830
+ Err ( ActivateError :: Error ( e) ) => return Err ( e) ,
831
+ Err ( ActivateError :: Conflict ( id, reason) ) => { conflicting_activations. insert ( id, reason) ; } ,
790
832
}
791
833
}
792
834
}
@@ -834,6 +876,7 @@ fn find_candidate<'a>(
834
876
* dep = frame. dep ;
835
877
* features = frame. features ;
836
878
* remaining_candidates = frame. remaining_candidates ;
879
+ * conflicting_activations = frame. conflicting_activations ;
837
880
return Some ( ( candidate, has_another) ) ;
838
881
}
839
882
}
@@ -875,9 +918,9 @@ fn activation_error(cx: &Context,
875
918
876
919
let mut conflicting_activations: Vec < _ > = conflicting_activations. iter ( ) . collect ( ) ;
877
920
conflicting_activations. sort_unstable ( ) ;
878
- let ( links_errors, other_errors) : ( Vec < _ > , Vec < _ > ) = conflicting_activations. drain ( ..) . rev ( ) . partition ( |& ( _, r) | r. is_links ( ) ) ;
921
+ let ( links_errors, mut other_errors) : ( Vec < _ > , Vec < _ > ) = conflicting_activations. drain ( ..) . rev ( ) . partition ( |& ( _, r) | r. is_links ( ) ) ;
879
922
880
- for & ( p, r) in & links_errors {
923
+ for & ( p, r) in links_errors. iter ( ) {
881
924
if let ConflictReason :: Links ( ref link) = * r {
882
925
msg. push_str ( "\n \n the package `" ) ;
883
926
msg. push_str ( dep. name ( ) ) ;
@@ -890,12 +933,27 @@ fn activation_error(cx: &Context,
890
933
msg. push_str ( & describe_path ( p) ) ;
891
934
}
892
935
936
+ let ( features_errors, other_errors) : ( Vec < _ > , Vec < _ > ) = other_errors. drain ( ..) . partition ( |& ( _, r) | r. is_missing_features ( ) ) ;
937
+
938
+ for & ( p, r) in features_errors. iter ( ) {
939
+ if let ConflictReason :: MissingFeatures ( ref features) = * r {
940
+ msg. push_str ( "\n \n the package `" ) ;
941
+ msg. push_str ( dep. name ( ) ) ;
942
+ msg. push_str ( "` depends on `" ) ;
943
+ msg. push_str ( p. name ( ) ) ;
944
+ msg. push_str ( "`, with features: `" ) ;
945
+ msg. push_str ( features) ;
946
+ msg. push_str ( "` but it does not have these features.\n " ) ;
947
+ }
948
+ msg. push_str ( & describe_path ( p) ) ;
949
+ }
950
+
893
951
if links_errors. is_empty ( ) {
894
952
msg. push_str ( "\n \n all possible versions conflict with \
895
953
previously selected packages.") ;
896
954
}
897
955
898
- for & ( p, _) in & other_errors {
956
+ for & ( p, _) in other_errors. iter ( ) {
899
957
msg. push_str ( "\n \n previously selected " ) ;
900
958
msg. push_str ( & describe_path ( p) ) ;
901
959
}
@@ -1158,7 +1216,7 @@ impl<'a> Context<'a> {
1158
1216
fn build_deps ( & mut self ,
1159
1217
registry : & mut Registry ,
1160
1218
candidate : & Summary ,
1161
- method : & Method ) -> CargoResult < Vec < DepInfo > > {
1219
+ method : & Method ) -> ActivateResult < Vec < DepInfo > > {
1162
1220
// First, figure out our set of dependencies based on the requested set
1163
1221
// of features. This also calculates what features we're going to enable
1164
1222
// for our own dependencies.
@@ -1275,7 +1333,7 @@ impl<'a> Context<'a> {
1275
1333
fn resolve_features < ' b > ( & mut self ,
1276
1334
s : & ' b Summary ,
1277
1335
method : & ' b Method )
1278
- -> CargoResult < Vec < ( Dependency , Vec < String > ) > > {
1336
+ -> ActivateResult < Vec < ( Dependency , Vec < String > ) > > {
1279
1337
let dev_deps = match * method {
1280
1338
Method :: Everything => true ,
1281
1339
Method :: Required { dev_deps, .. } => dev_deps,
@@ -1310,7 +1368,7 @@ impl<'a> Context<'a> {
1310
1368
base. extend ( dep. features ( ) . iter ( ) . cloned ( ) ) ;
1311
1369
for feature in base. iter ( ) {
1312
1370
if feature. contains ( '/' ) {
1313
- bail ! ( "feature names may not contain slashes: `{}`" , feature) ;
1371
+ return Err ( format_err ! ( "feature names may not contain slashes: `{}`" , feature) . into ( ) ) ;
1314
1372
}
1315
1373
}
1316
1374
ret. push ( ( dep. clone ( ) , base) ) ;
@@ -1324,8 +1382,7 @@ impl<'a> Context<'a> {
1324
1382
. map ( |s| & s[ ..] )
1325
1383
. collect :: < Vec < & str > > ( ) ;
1326
1384
let features = unknown. join ( ", " ) ;
1327
- bail ! ( "Package `{}` does not have these features: `{}`" ,
1328
- s. package_id( ) , features)
1385
+ return Err ( ( s. package_id ( ) . clone ( ) , ConflictReason :: MissingFeatures ( features) ) ) ?;
1329
1386
}
1330
1387
1331
1388
// Record what list of features is active for this package.
0 commit comments