@@ -326,7 +326,7 @@ enum GraphNode {
326
326
// risk of being cloned *a lot* so we want to make this as cheap to clone as
327
327
// possible.
328
328
#[ derive( Clone ) ]
329
- struct Context < ' a > {
329
+ struct Context {
330
330
// TODO: Both this and the two maps below are super expensive to clone. We should
331
331
// switch to persistent hash maps if we can at some point or otherwise
332
332
// make these much cheaper to clone in general.
@@ -340,8 +340,6 @@ struct Context<'a> {
340
340
resolve_graph : RcList < GraphNode > ,
341
341
resolve_replacements : RcList < ( PackageId , PackageId ) > ,
342
342
343
- replacements : & ' a [ ( PackageIdSpec , Dependency ) ] ,
344
-
345
343
// These warnings are printed after resolution.
346
344
warnings : RcList < String > ,
347
345
}
@@ -360,11 +358,10 @@ pub fn resolve(summaries: &[(Summary, Method)],
360
358
links : HashMap :: new ( ) ,
361
359
resolve_replacements : RcList :: new ( ) ,
362
360
activations : HashMap :: new ( ) ,
363
- replacements,
364
361
warnings : RcList :: new ( ) ,
365
362
} ;
366
363
let _p = profile:: start ( "resolving" ) ;
367
- let cx = activate_deps_loop ( cx, registry, summaries, config) ?;
364
+ let cx = activate_deps_loop ( cx, & mut RegistryQueryer :: new ( registry, replacements ) , summaries, config) ?;
368
365
369
366
let mut resolve = Resolve {
370
367
graph : cx. graph ( ) ,
@@ -410,7 +407,7 @@ pub fn resolve(summaries: &[(Summary, Method)],
410
407
/// If `candidate` was activated, this function returns the dependency frame to
411
408
/// iterate through next.
412
409
fn activate ( cx : & mut Context ,
413
- registry : & mut Registry ,
410
+ registry : & mut RegistryQueryer ,
414
411
parent : Option < & Summary > ,
415
412
candidate : Candidate ,
416
413
method : & Method )
@@ -573,10 +570,112 @@ impl ConflictReason {
573
570
}
574
571
}
575
572
573
+ struct RegistryQueryer < ' a > {
574
+ registry : & ' a mut ( Registry + ' a ) ,
575
+ replacements : & ' a [ ( PackageIdSpec , Dependency ) ] ,
576
+ // TODO: with nll the Rc can be removed
577
+ cache : HashMap < Dependency , Rc < Vec < Candidate > > > ,
578
+ }
579
+
580
+ impl < ' a > RegistryQueryer < ' a > {
581
+ fn new ( registry : & ' a mut Registry , replacements : & ' a [ ( PackageIdSpec , Dependency ) ] , ) -> Self {
582
+ RegistryQueryer {
583
+ registry,
584
+ replacements,
585
+ cache : HashMap :: new ( ) ,
586
+ }
587
+ }
588
+
589
+ /// Queries the `registry` to return a list of candidates for `dep`.
590
+ ///
591
+ /// This method is the location where overrides are taken into account. If
592
+ /// any candidates are returned which match an override then the override is
593
+ /// applied by performing a second query for what the override should
594
+ /// return.
595
+ fn query ( & mut self , dep : & Dependency ) -> CargoResult < Rc < Vec < Candidate > > > {
596
+ if let Some ( out) = self . cache . get ( dep) . cloned ( ) {
597
+ return Ok ( out) ;
598
+ }
599
+
600
+ let mut ret = Vec :: new ( ) ;
601
+ self . registry . query ( dep, & mut |s| {
602
+ ret. push ( Candidate { summary : s, replace : None } ) ;
603
+ } ) ?;
604
+ for candidate in ret. iter_mut ( ) {
605
+ let summary = & candidate. summary ;
606
+
607
+ let mut potential_matches = self . replacements . iter ( )
608
+ . filter ( |& & ( ref spec, _) | spec. matches ( summary. package_id ( ) ) ) ;
609
+
610
+ let & ( ref spec, ref dep) = match potential_matches. next ( ) {
611
+ None => continue ,
612
+ Some ( replacement) => replacement,
613
+ } ;
614
+ debug ! ( "found an override for {} {}" , dep. name( ) , dep. version_req( ) ) ;
615
+
616
+ let mut summaries = self . registry . query_vec ( dep) ?. into_iter ( ) ;
617
+ let s = summaries. next ( ) . ok_or_else ( || {
618
+ format_err ! ( "no matching package for override `{}` found\n \
619
+ location searched: {}\n \
620
+ version required: {}",
621
+ spec, dep. source_id( ) , dep. version_req( ) )
622
+ } ) ?;
623
+ let summaries = summaries. collect :: < Vec < _ > > ( ) ;
624
+ if !summaries. is_empty ( ) {
625
+ let bullets = summaries. iter ( ) . map ( |s| {
626
+ format ! ( " * {}" , s. package_id( ) )
627
+ } ) . collect :: < Vec < _ > > ( ) ;
628
+ bail ! ( "the replacement specification `{}` matched \
629
+ multiple packages:\n * {}\n {}", spec, s. package_id( ) ,
630
+ bullets. join( "\n " ) ) ;
631
+ }
632
+
633
+ // The dependency should be hard-coded to have the same name and an
634
+ // exact version requirement, so both of these assertions should
635
+ // never fail.
636
+ assert_eq ! ( s. version( ) , summary. version( ) ) ;
637
+ assert_eq ! ( s. name( ) , summary. name( ) ) ;
638
+
639
+ let replace = if s. source_id ( ) == summary. source_id ( ) {
640
+ debug ! ( "Preventing\n {:?}\n from replacing\n {:?}" , summary, s) ;
641
+ None
642
+ } else {
643
+ Some ( s)
644
+ } ;
645
+ let matched_spec = spec. clone ( ) ;
646
+
647
+ // Make sure no duplicates
648
+ if let Some ( & ( ref spec, _) ) = potential_matches. next ( ) {
649
+ bail ! ( "overlapping replacement specifications found:\n \n \
650
+ * {}\n * {}\n \n both specifications match: {}",
651
+ matched_spec, spec, summary. package_id( ) ) ;
652
+ }
653
+
654
+ for dep in summary. dependencies ( ) {
655
+ debug ! ( "\t {} => {}" , dep. name( ) , dep. version_req( ) ) ;
656
+ }
657
+
658
+ candidate. replace = replace;
659
+ }
660
+
661
+ // When we attempt versions for a package, we'll want to start at
662
+ // the maximum version and work our way down.
663
+ ret. sort_unstable_by ( |a, b| {
664
+ b. summary . version ( ) . cmp ( a. summary . version ( ) )
665
+ } ) ;
666
+
667
+ let out = Rc :: new ( ret) ;
668
+
669
+ self . cache . insert ( dep. clone ( ) , out. clone ( ) ) ;
670
+
671
+ Ok ( out)
672
+ }
673
+ }
674
+
576
675
#[ derive( Clone ) ]
577
- struct BacktrackFrame < ' a > {
676
+ struct BacktrackFrame {
578
677
cur : usize ,
579
- context_backup : Context < ' a > ,
678
+ context_backup : Context ,
580
679
deps_backup : BinaryHeap < DepsFrame > ,
581
680
remaining_candidates : RemainingCandidates ,
582
681
parent : Summary ,
@@ -658,12 +757,12 @@ impl RemainingCandidates {
658
757
///
659
758
/// If all dependencies can be activated and resolved to a version in the
660
759
/// dependency graph, cx.resolve is returned.
661
- fn activate_deps_loop < ' a > (
662
- mut cx : Context < ' a > ,
663
- registry : & mut Registry ,
760
+ fn activate_deps_loop (
761
+ mut cx : Context ,
762
+ registry : & mut RegistryQueryer ,
664
763
summaries : & [ ( Summary , Method ) ] ,
665
764
config : Option < & Config > ,
666
- ) -> CargoResult < Context < ' a > > {
765
+ ) -> CargoResult < Context > {
667
766
// Note that a `BinaryHeap` is used for the remaining dependencies that need
668
767
// activation. This heap is sorted such that the "largest value" is the most
669
768
// constrained dependency, or the one with the least candidates.
@@ -780,7 +879,7 @@ fn activate_deps_loop<'a>(
780
879
) . ok_or_else ( || {
781
880
activation_error (
782
881
& cx,
783
- registry,
882
+ registry. registry ,
784
883
& parent,
785
884
& dep,
786
885
& conflicting_activations,
@@ -850,9 +949,9 @@ fn activate_deps_loop<'a>(
850
949
/// If the outcome could differ, resets `cx` and `remaining_deps` to that
851
950
/// level and returns the next candidate.
852
951
/// If all candidates have been exhausted, returns None.
853
- fn find_candidate < ' a > (
854
- backtrack_stack : & mut Vec < BacktrackFrame < ' a > > ,
855
- cx : & mut Context < ' a > ,
952
+ fn find_candidate (
953
+ backtrack_stack : & mut Vec < BacktrackFrame > ,
954
+ cx : & mut Context ,
856
955
remaining_deps : & mut BinaryHeap < DepsFrame > ,
857
956
parent : & mut Summary ,
858
957
cur : & mut usize ,
@@ -1176,7 +1275,7 @@ fn build_requirements<'a, 'b: 'a>(s: &'a Summary, method: &'b Method)
1176
1275
Ok ( reqs)
1177
1276
}
1178
1277
1179
- impl < ' a > Context < ' a > {
1278
+ impl Context {
1180
1279
/// Activate this summary by inserting it into our list of known activations.
1181
1280
///
1182
1281
/// Returns true if this summary with the given method is already activated.
@@ -1219,7 +1318,7 @@ impl<'a> Context<'a> {
1219
1318
}
1220
1319
1221
1320
fn build_deps ( & mut self ,
1222
- registry : & mut Registry ,
1321
+ registry : & mut RegistryQueryer ,
1223
1322
parent : Option < & Summary > ,
1224
1323
candidate : & Summary ,
1225
1324
method : & Method ) -> ActivateResult < Vec < DepInfo > > {
@@ -1231,13 +1330,8 @@ impl<'a> Context<'a> {
1231
1330
// Next, transform all dependencies into a list of possible candidates
1232
1331
// which can satisfy that dependency.
1233
1332
let mut deps = deps. into_iter ( ) . map ( |( dep, features) | {
1234
- let mut candidates = self . query ( registry, & dep) ?;
1235
- // When we attempt versions for a package, we'll want to start at
1236
- // the maximum version and work our way down.
1237
- candidates. sort_by ( |a, b| {
1238
- b. summary . version ( ) . cmp ( a. summary . version ( ) )
1239
- } ) ;
1240
- Ok ( ( dep, Rc :: new ( candidates) , Rc :: new ( features) ) )
1333
+ let candidates = registry. query ( & dep) ?;
1334
+ Ok ( ( dep, candidates, Rc :: new ( features) ) )
1241
1335
} ) . collect :: < CargoResult < Vec < DepInfo > > > ( ) ?;
1242
1336
1243
1337
// Attempt to resolve dependencies with fewer candidates before trying
@@ -1249,78 +1343,6 @@ impl<'a> Context<'a> {
1249
1343
Ok ( deps)
1250
1344
}
1251
1345
1252
- /// Queries the `registry` to return a list of candidates for `dep`.
1253
- ///
1254
- /// This method is the location where overrides are taken into account. If
1255
- /// any candidates are returned which match an override then the override is
1256
- /// applied by performing a second query for what the override should
1257
- /// return.
1258
- fn query ( & self ,
1259
- registry : & mut Registry ,
1260
- dep : & Dependency ) -> CargoResult < Vec < Candidate > > {
1261
- let mut ret = Vec :: new ( ) ;
1262
- registry. query ( dep, & mut |s| {
1263
- ret. push ( Candidate { summary : s, replace : None } ) ;
1264
- } ) ?;
1265
- for candidate in ret. iter_mut ( ) {
1266
- let summary = & candidate. summary ;
1267
-
1268
- let mut potential_matches = self . replacements . iter ( )
1269
- . filter ( |& & ( ref spec, _) | spec. matches ( summary. package_id ( ) ) ) ;
1270
-
1271
- let & ( ref spec, ref dep) = match potential_matches. next ( ) {
1272
- None => continue ,
1273
- Some ( replacement) => replacement,
1274
- } ;
1275
- debug ! ( "found an override for {} {}" , dep. name( ) , dep. version_req( ) ) ;
1276
-
1277
- let mut summaries = registry. query_vec ( dep) ?. into_iter ( ) ;
1278
- let s = summaries. next ( ) . ok_or_else ( || {
1279
- format_err ! ( "no matching package for override `{}` found\n \
1280
- location searched: {}\n \
1281
- version required: {}",
1282
- spec, dep. source_id( ) , dep. version_req( ) )
1283
- } ) ?;
1284
- let summaries = summaries. collect :: < Vec < _ > > ( ) ;
1285
- if !summaries. is_empty ( ) {
1286
- let bullets = summaries. iter ( ) . map ( |s| {
1287
- format ! ( " * {}" , s. package_id( ) )
1288
- } ) . collect :: < Vec < _ > > ( ) ;
1289
- bail ! ( "the replacement specification `{}` matched \
1290
- multiple packages:\n * {}\n {}", spec, s. package_id( ) ,
1291
- bullets. join( "\n " ) ) ;
1292
- }
1293
-
1294
- // The dependency should be hard-coded to have the same name and an
1295
- // exact version requirement, so both of these assertions should
1296
- // never fail.
1297
- assert_eq ! ( s. version( ) , summary. version( ) ) ;
1298
- assert_eq ! ( s. name( ) , summary. name( ) ) ;
1299
-
1300
- let replace = if s. source_id ( ) == summary. source_id ( ) {
1301
- debug ! ( "Preventing\n {:?}\n from replacing\n {:?}" , summary, s) ;
1302
- None
1303
- } else {
1304
- Some ( s)
1305
- } ;
1306
- let matched_spec = spec. clone ( ) ;
1307
-
1308
- // Make sure no duplicates
1309
- if let Some ( & ( ref spec, _) ) = potential_matches. next ( ) {
1310
- bail ! ( "overlapping replacement specifications found:\n \n \
1311
- * {}\n * {}\n \n both specifications match: {}",
1312
- matched_spec, spec, summary. package_id( ) ) ;
1313
- }
1314
-
1315
- for dep in summary. dependencies ( ) {
1316
- debug ! ( "\t {} => {}" , dep. name( ) , dep. version_req( ) ) ;
1317
- }
1318
-
1319
- candidate. replace = replace;
1320
- }
1321
- Ok ( ret)
1322
- }
1323
-
1324
1346
fn prev_active ( & self , dep : & Dependency ) -> & [ Summary ] {
1325
1347
self . activations . get ( dep. name ( ) )
1326
1348
. and_then ( |v| v. get ( dep. source_id ( ) ) )
0 commit comments