@@ -11,7 +11,7 @@ use cargo::core::resolver::{self, Method};
11
11
use cargo:: core:: source:: { GitReference , SourceId } ;
12
12
use cargo:: core:: Resolve ;
13
13
use cargo:: core:: { Dependency , PackageId , Registry , Summary } ;
14
- use cargo:: util:: { CargoResult , Config , ToUrl } ;
14
+ use cargo:: util:: { CargoResult , Config , Graph , ToUrl } ;
15
15
16
16
use proptest:: collection:: { btree_map, vec} ;
17
17
use proptest:: prelude:: * ;
@@ -278,12 +278,15 @@ impl SatResolve {
278
278
279
279
let empty_vec = vec ! [ ] ;
280
280
281
+ let mut graph: Graph < PackageId , ( ) > = Graph :: new ( ) ;
282
+
281
283
let mut version_selected_for: HashMap <
282
- ( PackageId , Dependency ) ,
283
- HashMap < PackageId , varisat:: Var > ,
284
+ PackageId ,
285
+ HashMap < Dependency , HashMap < PackageId , varisat:: Var > > ,
284
286
> = HashMap :: new ( ) ;
285
287
// active packages need each of there `deps` to be satisfied
286
288
for p in registry. iter ( ) {
289
+ graph. add ( p. package_id ( ) ) ;
287
290
for dep in p. dependencies ( ) {
288
291
let version: HashMap < PackageId , varisat:: Var > = by_name
289
292
. get ( dep. package_name ( ) . as_str ( ) )
@@ -302,76 +305,80 @@ impl SatResolve {
302
305
for ( pid, var) in version. iter ( ) {
303
306
// if a version is selected then it needs to be activated
304
307
solver. add_clause ( & [ var. negative ( ) , var_for_is_packages_used[ pid] . positive ( ) ] ) ;
308
+ graph. link ( p. package_id ( ) , * pid) ;
305
309
}
306
- version_selected_for. insert ( ( p. package_id ( ) , dep. clone ( ) ) , version) ;
310
+ version_selected_for
311
+ . entry ( p. package_id ( ) )
312
+ . or_default ( )
313
+ . insert ( dep. clone ( ) , version) ;
307
314
}
308
315
}
309
316
310
- let publicly_exports: HashMap < PackageId , HashMap < PackageId , varisat:: Var > > = registry
311
- . iter ( )
312
- . map ( |s| {
313
- (
314
- s. package_id ( ) ,
315
- registry
316
- . iter ( )
317
- . map ( |s| ( s. package_id ( ) , solver. new_var ( ) ) )
318
- . collect ( ) ,
319
- )
320
- } )
321
- . collect ( ) ;
317
+ let topological_order = graph. sort ( ) ;
318
+
319
+ let mut publicly_exports: HashMap < PackageId , HashMap < PackageId , varisat:: Var > > =
320
+ HashMap :: new ( ) ;
322
321
323
322
for s in registry. iter ( ) {
324
323
// everything publicly depends on itself
325
- solver. add_clause ( & [ publicly_exports[ & s. package_id ( ) ] [ & s. package_id ( ) ] . positive ( ) ] ) ;
324
+ let var = publicly_exports
325
+ . entry ( s. package_id ( ) )
326
+ . or_default ( )
327
+ . entry ( s. package_id ( ) )
328
+ . or_insert_with ( || solver. new_var ( ) ) ;
329
+ solver. add_clause ( & [ var. positive ( ) ] ) ;
326
330
}
327
331
328
332
// if a `dep` is public then `p` `publicly_exports` all the things that the selected version `publicly_exports`
329
- for p in registry. iter ( ) {
330
- for dep in p. dependencies ( ) . iter ( ) . filter ( |d| d. is_public ( ) ) {
331
- for ( ver, sel) in version_selected_for[ & ( p. package_id ( ) , dep. clone ( ) ) ] . iter ( ) {
332
- for export in registry. iter ( ) {
333
- solver. add_clause ( & [
334
- sel. negative ( ) ,
335
- publicly_exports[ ver] [ & export. package_id ( ) ] . negative ( ) ,
336
- publicly_exports[ & p. package_id ( ) ] [ & export. package_id ( ) ] . positive ( ) ,
337
- ] ) ;
333
+ for & p in topological_order. iter ( ) {
334
+ if let Some ( deps) = version_selected_for. get ( & p) {
335
+ for ( _, versions) in deps. iter ( ) . filter ( |( d, _) | d. is_public ( ) ) {
336
+ for ( ver, sel) in versions {
337
+ for ( & export_pid, & export_var) in publicly_exports[ ver] . clone ( ) . iter ( ) {
338
+ let our_var = publicly_exports
339
+ . entry ( p)
340
+ . or_default ( )
341
+ . entry ( export_pid)
342
+ . or_insert_with ( || solver. new_var ( ) ) ;
343
+ solver. add_clause ( & [
344
+ sel. negative ( ) ,
345
+ export_var. negative ( ) ,
346
+ our_var. positive ( ) ,
347
+ ] ) ;
348
+ }
338
349
}
339
350
}
340
351
}
341
352
}
342
353
343
- let can_see: HashMap < PackageId , HashMap < PackageId , varisat:: Var > > = registry
344
- . iter ( )
345
- . map ( |s| {
346
- (
347
- s. package_id ( ) ,
348
- registry
349
- . iter ( )
350
- . map ( |s| ( s. package_id ( ) , solver. new_var ( ) ) )
351
- . collect ( ) ,
352
- )
353
- } )
354
- . collect ( ) ;
354
+ let mut can_see: HashMap < PackageId , HashMap < PackageId , varisat:: Var > > = HashMap :: new ( ) ;
355
355
356
356
// if `p` `publicly_exports` `export` then it `can_see` `export`
357
- for p in registry. iter ( ) {
358
- for export in registry. iter ( ) {
359
- solver. add_clause ( & [
360
- publicly_exports[ & p. package_id ( ) ] [ & export. package_id ( ) ] . negative ( ) ,
361
- can_see[ & p. package_id ( ) ] [ & export. package_id ( ) ] . positive ( ) ,
362
- ] ) ;
357
+ for ( & p, exports) in & publicly_exports {
358
+ for ( & export_pid, export_var) in exports {
359
+ let our_var = can_see
360
+ . entry ( p)
361
+ . or_default ( )
362
+ . entry ( export_pid)
363
+ . or_insert_with ( || solver. new_var ( ) ) ;
364
+ solver. add_clause ( & [ export_var. negative ( ) , our_var. positive ( ) ] ) ;
363
365
}
364
366
}
365
367
366
368
// if `p` has a `dep` that selected `ver` then it `can_see` all the things that the selected version `publicly_exports`
367
- for p in registry. iter ( ) {
368
- for dep in p. dependencies ( ) . iter ( ) {
369
- for ( ver, sel) in version_selected_for[ & ( p. package_id ( ) , dep. clone ( ) ) ] . iter ( ) {
370
- for export in registry. iter ( ) {
369
+ for ( & p, deps) in version_selected_for. iter ( ) {
370
+ for ( _, versions) in deps {
371
+ for ( ver, sel) in versions {
372
+ for ( & export_pid, & export_var) in publicly_exports[ ver] . iter ( ) {
373
+ let our_var = can_see
374
+ . entry ( p)
375
+ . or_default ( )
376
+ . entry ( export_pid)
377
+ . or_insert_with ( || solver. new_var ( ) ) ;
371
378
solver. add_clause ( & [
372
379
sel. negative ( ) ,
373
- publicly_exports [ ver ] [ & export . package_id ( ) ] . negative ( ) ,
374
- can_see [ & p . package_id ( ) ] [ & export . package_id ( ) ] . positive ( ) ,
380
+ export_var . negative ( ) ,
381
+ our_var . positive ( ) ,
375
382
] ) ;
376
383
}
377
384
}
@@ -381,7 +388,7 @@ impl SatResolve {
381
388
// a package `can_see` only one version by each name
382
389
for ( _, see) in can_see. iter ( ) {
383
390
for ( _, vers) in by_name. iter ( ) {
384
- let same_name: Vec < _ > = vers. iter ( ) . map ( |p| see[ p ] ) . collect ( ) ;
391
+ let same_name: Vec < _ > = vers. iter ( ) . filter_map ( |p| see. get ( p ) . cloned ( ) ) . collect ( ) ;
385
392
sat_at_most_one ( & mut solver, & same_name) ;
386
393
}
387
394
}
0 commit comments