@@ -218,6 +218,21 @@ fn sat_at_most_one(solver: &mut impl varisat::ExtendFormula, vars: &[varisat::Va
218
218
}
219
219
}
220
220
221
+ fn sat_at_most_one_by_key < K : std:: hash:: Hash + Eq > (
222
+ cnf : & mut impl varisat:: ExtendFormula ,
223
+ data : impl Iterator < Item = ( K , varisat:: Var ) > ,
224
+ ) -> HashMap < K , Vec < varisat:: Var > > {
225
+ // no two packages with the same links set
226
+ let mut by_keys: HashMap < K , Vec < varisat:: Var > > = HashMap :: new ( ) ;
227
+ for ( p, v) in data {
228
+ by_keys. entry ( p) . or_default ( ) . push ( v)
229
+ }
230
+ for key in by_keys. values ( ) {
231
+ sat_at_most_one ( cnf, key) ;
232
+ }
233
+ by_keys
234
+ }
235
+
221
236
/// Resolution can be reduced to the SAT problem. So this is an alternative implementation
222
237
/// of the resolver that uses a SAT library for the hard work. This is intended to be easy to read,
223
238
/// as compared to the real resolver.
@@ -243,30 +258,21 @@ impl SatResolve {
243
258
. collect ( ) ;
244
259
245
260
// no two packages with the same links set
246
- let mut by_links: HashMap < _ , Vec < varisat:: Var > > = HashMap :: new ( ) ;
247
- for p in registry. iter ( ) {
248
- if let Some ( l) = p. links ( ) {
249
- by_links
250
- . entry ( l)
251
- . or_default ( )
252
- . push ( var_for_is_packages_used[ & p. package_id ( ) ] )
253
- }
254
- }
255
- for link in by_links. values ( ) {
256
- sat_at_most_one ( & mut cnf, link) ;
257
- }
261
+ sat_at_most_one_by_key (
262
+ & mut cnf,
263
+ registry
264
+ . iter ( )
265
+ . map ( |s| ( s. links ( ) , var_for_is_packages_used[ & s. package_id ( ) ] ) )
266
+ . filter ( |( l, _) | l. is_some ( ) ) ,
267
+ ) ;
258
268
259
269
// no two semver compatible versions of the same package
260
- let mut by_activations_keys: HashMap < _ , Vec < varisat:: Var > > = HashMap :: new ( ) ;
261
- for p in registry. iter ( ) {
262
- by_activations_keys
263
- . entry ( p. package_id ( ) . as_activations_key ( ) )
264
- . or_default ( )
265
- . push ( var_for_is_packages_used[ & p. package_id ( ) ] )
266
- }
267
- for key in by_activations_keys. values ( ) {
268
- sat_at_most_one ( & mut cnf, key) ;
269
- }
270
+ let by_activations_keys = sat_at_most_one_by_key (
271
+ & mut cnf,
272
+ var_for_is_packages_used
273
+ . iter ( )
274
+ . map ( |( p, & v) | ( p. as_activations_key ( ) , v) ) ,
275
+ ) ;
270
276
271
277
let mut by_name: HashMap < & ' static str , Vec < PackageId > > = HashMap :: new ( ) ;
272
278
@@ -389,13 +395,7 @@ impl SatResolve {
389
395
390
396
// a package `can_see` only one version by each name
391
397
for ( _, see) in can_see. iter ( ) {
392
- let mut by_name: HashMap < & ' static str , Vec < varisat:: Var > > = HashMap :: new ( ) ;
393
- for ( ( name, _, _) , & var) in see {
394
- by_name. entry ( name. as_str ( ) ) . or_default ( ) . push ( var) ;
395
- }
396
- for same_name in by_name. values ( ) {
397
- sat_at_most_one ( & mut cnf, same_name) ;
398
- }
398
+ sat_at_most_one_by_key ( & mut cnf, see. iter ( ) . map ( |( ( name, _, _) , & v) | ( name, v) ) ) ;
399
399
}
400
400
let mut solver = varisat:: Solver :: new ( ) ;
401
401
solver. add_formula ( & cnf) ;
0 commit comments