@@ -282,49 +282,60 @@ impl SatResolve {
282
282
283
283
let mut version_selected_for: HashMap <
284
284
PackageId ,
285
- HashMap < Dependency , HashMap < PackageId , varisat:: Var > > ,
285
+ HashMap < Dependency , HashMap < _ , varisat:: Var > > ,
286
286
> = HashMap :: new ( ) ;
287
287
// active packages need each of there `deps` to be satisfied
288
288
for p in registry. iter ( ) {
289
289
graph. add ( p. package_id ( ) ) ;
290
290
for dep in p. dependencies ( ) {
291
- let version: HashMap < PackageId , varisat:: Var > = by_name
291
+ let mut by_key: HashMap < _ , Vec < varisat:: Lit > > = HashMap :: new ( ) ;
292
+ for & m in by_name
292
293
. get ( dep. package_name ( ) . as_str ( ) )
293
294
. unwrap_or ( & empty_vec)
294
295
. iter ( )
295
296
. filter ( |& p| dep. matches_id ( * p) )
296
- . map ( |& p| ( p, solver. new_var ( ) ) )
297
- . collect ( ) ;
298
- // if `p` is active then we need to select one of the versions
299
- let matches: Vec < _ > = version
297
+ {
298
+ by_key
299
+ . entry ( m. as_activations_key ( ) )
300
+ . or_default ( )
301
+ . push ( var_for_is_packages_used[ & m] . positive ( ) ) ;
302
+ }
303
+ let keys: HashMap < _ , _ > = by_key. keys ( ) . map ( |& k| ( k, solver. new_var ( ) ) ) . collect ( ) ;
304
+
305
+ // if `p` is active then we need to select one of the keys
306
+ let matches: Vec < _ > = keys
300
307
. values ( )
301
308
. map ( |v| v. positive ( ) )
302
309
. chain ( Some ( var_for_is_packages_used[ & p. package_id ( ) ] . negative ( ) ) )
303
310
. collect ( ) ;
304
311
solver. add_clause ( & matches) ;
305
- for ( pid, var) in version. iter ( ) {
306
- // if a version is selected then it needs to be activated
307
- solver. add_clause ( & [ var. negative ( ) , var_for_is_packages_used[ pid] . positive ( ) ] ) ;
308
- graph. link ( p. package_id ( ) , * pid) ;
312
+
313
+ // if a key is active then we need to select one of the versions
314
+ for ( key, vars) in by_key. iter ( ) {
315
+ let mut matches = vars. clone ( ) ;
316
+ matches. push ( keys[ key] . negative ( ) ) ;
317
+ solver. add_clause ( & matches) ;
309
318
}
319
+
310
320
version_selected_for
311
321
. entry ( p. package_id ( ) )
312
322
. or_default ( )
313
- . insert ( dep. clone ( ) , version ) ;
323
+ . insert ( dep. clone ( ) , keys ) ;
314
324
}
315
325
}
316
326
317
327
let topological_order = graph. sort ( ) ;
318
328
319
- let mut publicly_exports: HashMap < PackageId , HashMap < PackageId , varisat:: Var > > =
320
- HashMap :: new ( ) ;
329
+ // we already ensure there is only one version for each `activations_key` so we can think of
330
+ // `publicly_exports` as being in terms of a set of `activations_key`s
331
+ let mut publicly_exports: HashMap < _ , HashMap < _ , varisat:: Var > > = HashMap :: new ( ) ;
321
332
322
- for s in registry . iter ( ) {
333
+ for & key in by_activations_keys . keys ( ) {
323
334
// everything publicly depends on itself
324
335
let var = publicly_exports
325
- . entry ( s . package_id ( ) )
336
+ . entry ( key )
326
337
. or_default ( )
327
- . entry ( s . package_id ( ) )
338
+ . entry ( key )
328
339
. or_insert_with ( || solver. new_var ( ) ) ;
329
340
solver. add_clause ( & [ var. positive ( ) ] ) ;
330
341
}
@@ -336,7 +347,7 @@ impl SatResolve {
336
347
for ( ver, sel) in versions {
337
348
for ( & export_pid, & export_var) in publicly_exports[ ver] . clone ( ) . iter ( ) {
338
349
let our_var = publicly_exports
339
- . entry ( p)
350
+ . entry ( p. as_activations_key ( ) )
340
351
. or_default ( )
341
352
. entry ( export_pid)
342
353
. or_insert_with ( || solver. new_var ( ) ) ;
@@ -351,7 +362,9 @@ impl SatResolve {
351
362
}
352
363
}
353
364
354
- let mut can_see: HashMap < PackageId , HashMap < PackageId , varisat:: Var > > = HashMap :: new ( ) ;
365
+ // we already ensure there is only one version for each `activations_key` so we can think of
366
+ // `can_see` as being in terms of a set of `activations_key`s
367
+ let mut can_see: HashMap < _ , HashMap < _ , varisat:: Var > > = HashMap :: new ( ) ;
355
368
356
369
// if `p` `publicly_exports` `export` then it `can_see` `export`
357
370
for ( & p, exports) in & publicly_exports {
@@ -368,10 +381,10 @@ impl SatResolve {
368
381
// if `p` has a `dep` that selected `ver` then it `can_see` all the things that the selected version `publicly_exports`
369
382
for ( & p, deps) in version_selected_for. iter ( ) {
370
383
for ( _, versions) in deps {
371
- for ( ver, sel) in versions {
372
- for ( & export_pid, & export_var) in publicly_exports[ ver] . iter ( ) {
384
+ for ( & ver, sel) in versions {
385
+ for ( & export_pid, & export_var) in publicly_exports[ & ver] . iter ( ) {
373
386
let our_var = can_see
374
- . entry ( p)
387
+ . entry ( p. as_activations_key ( ) )
375
388
. or_default ( )
376
389
. entry ( export_pid)
377
390
. or_insert_with ( || solver. new_var ( ) ) ;
@@ -387,9 +400,12 @@ impl SatResolve {
387
400
388
401
// a package `can_see` only one version by each name
389
402
for ( _, see) in can_see. iter ( ) {
390
- for ( _, vers) in by_name. iter ( ) {
391
- let same_name: Vec < _ > = vers. iter ( ) . filter_map ( |p| see. get ( p) . cloned ( ) ) . collect ( ) ;
392
- sat_at_most_one ( & mut solver, & same_name) ;
403
+ let mut by_name: HashMap < & ' static str , Vec < varisat:: Var > > = HashMap :: new ( ) ;
404
+ for ( ( name, _, _) , & var) in see {
405
+ by_name. entry ( name. as_str ( ) ) . or_default ( ) . push ( var) ;
406
+ }
407
+ for same_name in by_name. values ( ) {
408
+ sat_at_most_one ( & mut solver, same_name) ;
393
409
}
394
410
}
395
411
0 commit comments