@@ -72,6 +72,7 @@ pub use self::encode::{EncodableDependency, EncodablePackageId, EncodableResolve
72
72
pub use self :: encode:: { Metadata , WorkspaceResolve } ;
73
73
74
74
mod encode;
75
+ mod conflict_cache;
75
76
76
77
/// Represents a fully resolved package dependency graph. Each node in the graph
77
78
/// is a package and edges represent dependencies between packages.
@@ -594,6 +595,15 @@ impl DepsFrame {
594
595
. map ( |( _, ( _, candidates, _) ) | candidates. len ( ) )
595
596
. unwrap_or ( 0 )
596
597
}
598
+
599
+ fn flatten < ' s > ( & ' s self ) -> Box < Iterator < Item = ( PackageId , Dependency ) > + ' s > {
600
+ // TODO: with impl Trait the Box can be removed
601
+ Box :: new (
602
+ self . remaining_siblings
603
+ . clone ( )
604
+ . map ( move |( _, ( d, _, _) ) | ( self . parent . package_id ( ) . clone ( ) , d) ) ,
605
+ )
606
+ }
597
607
}
598
608
599
609
impl PartialEq for DepsFrame {
@@ -975,42 +985,8 @@ fn activate_deps_loop(
975
985
let mut remaining_deps = BinaryHeap :: new ( ) ;
976
986
977
987
// `past_conflicting_activations` is a cache of the reasons for each time we
978
- // backtrack. For example after several backtracks we may have:
979
- //
980
- // past_conflicting_activations[`foo = "^1.0.2"`] = vec![
981
- // map!{`foo=1.0.1`: Semver},
982
- // map!{`foo=1.0.0`: Semver},
983
- // ];
984
- //
985
- // This can be read as "we cannot find a candidate for dep `foo = "^1.0.2"`
986
- // if either `foo=1.0.1` OR `foo=1.0.0` are activated".
987
- //
988
- // Another example after several backtracks we may have:
989
- //
990
- // past_conflicting_activations[`foo = ">=0.8.2, <=0.9.3"`] = vec![
991
- // map!{`foo=0.8.1`: Semver, `foo=0.9.4`: Semver},
992
- // ];
993
- //
994
- // This can be read as "we cannot find a candidate for dep `foo = ">=0.8.2,
995
- // <=0.9.3"` if both `foo=0.8.1` AND `foo=0.9.4` are activated".
996
- //
997
- // This is used to make sure we don't queue work we know will fail. See the
998
- // discussion in https://github.com/rust-lang/cargo/pull/5168 for why this
999
- // is so important, and there can probably be a better data structure here
1000
- // but for now this works well enough!
1001
- //
1002
- // Also, as a final note, this map is *not* ever removed from. This remains
1003
- // as a global cache which we never delete from. Any entry in this map is
1004
- // unconditionally true regardless of our resolution history of how we got
1005
- // here.
1006
- let mut past_conflicting_activations: HashMap <
1007
- Dependency ,
1008
- Vec < HashMap < PackageId , ConflictReason > > ,
1009
- > = HashMap :: new ( ) ;
1010
-
1011
- // `past_conflict_triggers` is an inverse-index of `past_conflicting_activations`.
1012
- // For every `PackageId` this lists the `Dependency`s that mention it in `past_conflicting_activations`.
1013
- let mut past_conflict_triggers: HashMap < PackageId , HashSet < Dependency > > = HashMap :: new ( ) ;
988
+ // backtrack.
989
+ let mut past_conflicting_activations = conflict_cache:: ConflictCache :: new ( ) ;
1014
990
1015
991
// Activate all the initial summaries to kick off some work.
1016
992
for & ( ref summary, ref method) in summaries {
@@ -1100,12 +1076,7 @@ fn activate_deps_loop(
1100
1076
1101
1077
let just_here_for_the_error_messages = just_here_for_the_error_messages
1102
1078
&& past_conflicting_activations
1103
- . get ( & dep)
1104
- . and_then ( |past_bad| {
1105
- past_bad
1106
- . iter ( )
1107
- . find ( |conflicting| cx. is_conflicting ( None , conflicting) )
1108
- } )
1079
+ . conflicting ( & cx, & dep)
1109
1080
. is_some ( ) ;
1110
1081
1111
1082
let mut remaining_candidates = RemainingCandidates :: new ( & candidates) ;
@@ -1157,25 +1128,7 @@ fn activate_deps_loop(
1157
1128
// local is set to `true` then our `conflicting_activations` may
1158
1129
// not be right, so we can't push into our global cache.
1159
1130
if !just_here_for_the_error_messages && !backtracked {
1160
- let past = past_conflicting_activations
1161
- . entry ( dep. clone ( ) )
1162
- . or_insert_with ( Vec :: new) ;
1163
- if !past. contains ( & conflicting_activations) {
1164
- trace ! (
1165
- "{}[{}]>{} adding a skip {:?}" ,
1166
- parent. name( ) ,
1167
- cur,
1168
- dep. name( ) ,
1169
- conflicting_activations
1170
- ) ;
1171
- past. push ( conflicting_activations. clone ( ) ) ;
1172
- for c in conflicting_activations. keys ( ) {
1173
- past_conflict_triggers
1174
- . entry ( c. clone ( ) )
1175
- . or_insert_with ( HashSet :: new)
1176
- . insert ( dep. clone ( ) ) ;
1177
- }
1178
- }
1131
+ past_conflicting_activations. insert ( & dep, & conflicting_activations) ;
1179
1132
}
1180
1133
1181
1134
match find_candidate ( & mut backtrack_stack, & parent, & conflicting_activations) {
@@ -1280,11 +1233,10 @@ fn activate_deps_loop(
1280
1233
if let Some ( conflicting) = frame
1281
1234
. remaining_siblings
1282
1235
. clone ( )
1283
- . filter_map ( |( _, ( new_dep, _, _) ) | {
1284
- past_conflicting_activations. get ( & new_dep)
1236
+ . filter_map ( |( _, ( ref new_dep, _, _) ) | {
1237
+ past_conflicting_activations. conflicting ( & cx , & new_dep)
1285
1238
} )
1286
- . flat_map ( |x| x)
1287
- . find ( |con| cx. is_conflicting ( None , con) )
1239
+ . next ( )
1288
1240
{
1289
1241
let mut conflicting = conflicting. clone ( ) ;
1290
1242
@@ -1309,33 +1261,23 @@ fn activate_deps_loop(
1309
1261
// ourselves are incompatible with that dep, so we know that deps
1310
1262
// parent conflict with us.
1311
1263
if !has_past_conflicting_dep {
1312
- if let Some ( rel_deps) = past_conflict_triggers. get ( & pid) {
1264
+ if let Some ( rel_deps) = past_conflicting_activations. get_dep_from_pid ( & pid)
1265
+ {
1313
1266
if let Some ( ( other_parent, conflict) ) = remaining_deps
1314
1267
. iter ( )
1315
- . flat_map ( |other| {
1316
- other
1317
- . remaining_siblings
1318
- // search thru all `remaining_deps`
1319
- . clone ( )
1320
- // for deps related to us
1321
- . filter ( |& ( _, ( ref d, _, _) ) | rel_deps. contains ( d) )
1322
- . map ( move |( _, ( d, _, _) ) | {
1323
- ( other. parent . package_id ( ) . clone ( ) , d)
1324
- } )
1325
- } )
1326
- . filter_map ( |( other_parent, other_deps) | {
1268
+ . flat_map ( |other| other. flatten ( ) )
1269
+ // for deps related to us
1270
+ . filter ( |& ( _, ref other_dep) | rel_deps. contains ( other_dep) )
1271
+ . filter_map ( |( other_parent, other_dep) | {
1327
1272
past_conflicting_activations
1328
- . get ( & other_deps)
1329
- . map ( |v| ( other_parent, v) )
1330
- } )
1331
- . flat_map ( |( other_parent, past_bad) | {
1332
- past_bad
1333
- . iter ( )
1334
- // for deps that refer to us
1335
- . filter ( |con| con. contains_key ( & pid) )
1336
- . map ( move |c| ( other_parent. clone ( ) , c) )
1273
+ . filter_conflicting (
1274
+ & cx,
1275
+ & other_dep,
1276
+ |con| con. contains_key ( & pid)
1277
+ )
1278
+ . map ( |con| ( other_parent, con) )
1337
1279
} )
1338
- . find ( | & ( _ , ref con ) | cx . is_conflicting ( None , con ) )
1280
+ . next ( )
1339
1281
{
1340
1282
let mut conflict = conflict. clone ( ) ;
1341
1283
let rel = conflict. get ( & pid) . unwrap ( ) . clone ( ) ;
0 commit comments