@@ -288,6 +288,7 @@ fn activate_deps_loop(
288
288
& cx,
289
289
registry,
290
290
& mut past_conflicting_activations,
291
+ & parent,
291
292
& dep,
292
293
& conflicting_activations,
293
294
) {
@@ -854,10 +855,11 @@ fn generalize_conflicting(
854
855
cx : & Context ,
855
856
registry : & mut RegistryQueryer < ' _ > ,
856
857
past_conflicting_activations : & mut conflict_cache:: ConflictCache ,
858
+ parent : & Summary ,
857
859
dep : & Dependency ,
858
860
conflicting_activations : & ConflictMap ,
859
861
) -> Option < ConflictMap > {
860
- if conflicting_activations. len ( ) != 1 {
862
+ if conflicting_activations. is_empty ( ) {
861
863
return None ;
862
864
}
863
865
// We need to determine the `ContextAge` that this `conflicting_activations` will jump to, and why.
@@ -869,6 +871,16 @@ fn generalize_conflicting(
869
871
let backtrack_critical_reason: ConflictReason =
870
872
conflicting_activations[ & backtrack_critical_id] . clone ( ) ;
871
873
874
+ if cx
875
+ . parents
876
+ . is_path_from_to ( & parent. package_id ( ) , & backtrack_critical_id)
877
+ {
878
+ // We are a descendant of the trigger of the problem.
879
+ // The best generalization of this is to let things bubble up
880
+ // and let `backtrack_critical_id` figure this out.
881
+ return None ;
882
+ }
883
+
872
884
// we will need to know the range of versions we can use
873
885
let our_candidates = registry
874
886
. query ( dep)
@@ -905,10 +917,6 @@ fn generalize_conflicting(
905
917
None
906
918
} ;
907
919
908
- if !( our_activation_key. is_some ( ) || our_link. is_some ( ) ) {
909
- return None ;
910
- }
911
-
912
920
let our_candidates: HashSet < PackageId > =
913
921
our_candidates. iter ( ) . map ( |our| our. package_id ( ) ) . collect ( ) ;
914
922
@@ -920,6 +928,9 @@ fn generalize_conflicting(
920
928
} )
921
929
{
922
930
' dep: for critical_parents_dep in critical_parents_deps. iter ( ) {
931
+ // A dep is equivalent to one of the things it can resolve to.
932
+ // Thus, if all the things it can resolve to have already ben determined
933
+ // to be conflicting, then we can just say that we conflict with the parent.
923
934
let mut con = conflicting_activations. clone ( ) ;
924
935
con. remove ( & backtrack_critical_id) ;
925
936
con. insert ( * critical_parent, backtrack_critical_reason. clone ( ) ) ;
@@ -928,6 +939,8 @@ fn generalize_conflicting(
928
939
. query ( critical_parents_dep)
929
940
. expect ( "an already used dep now error!?" )
930
941
. iter ( )
942
+ . rev ( )
943
+ // the last one to be tried is the least likely to be in the cache, so start with that.
931
944
{
932
945
if ( our_activation_key
933
946
. map_or ( false , |our| other. package_id ( ) . as_activations_key ( ) == our)
@@ -950,9 +963,32 @@ fn generalize_conflicting(
950
963
) {
951
964
con. extend ( conflicting. into_iter ( ) ) ;
952
965
continue ;
953
- } else {
954
- continue ' dep;
955
966
}
967
+
968
+ if let Some ( conflicting) = past_conflicting_activations. find (
969
+ dep,
970
+ & |id| {
971
+ if id == other. package_id ( ) {
972
+ // we are imagining that we used other instead
973
+ Some ( backtrack_critical_age)
974
+ } else {
975
+ cx. is_active ( id) . filter ( |& age|
976
+ // we only care about things that are older then critical_age
977
+ age < backtrack_critical_age)
978
+ }
979
+ } ,
980
+ Some ( other. package_id ( ) ) ,
981
+ ) {
982
+ con. extend (
983
+ conflicting
984
+ . iter ( )
985
+ . filter ( |( & id, _) | id != other. package_id ( ) )
986
+ . map ( |( & id, r) | ( id, r. clone ( ) ) ) ,
987
+ ) ;
988
+ continue ;
989
+ }
990
+
991
+ continue ' dep;
956
992
}
957
993
958
994
if cfg ! ( debug_assertions) {
0 commit comments