@@ -218,6 +218,21 @@ fn sat_at_most_one(solver: &mut impl varisat::ExtendFormula, vars: &[varisat::Va
218218 }
219219}
220220
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+
221236/// Resolution can be reduced to the SAT problem. So this is an alternative implementation
222237/// of the resolver that uses a SAT library for the hard work. This is intended to be easy to read,
223238/// as compared to the real resolver.
@@ -243,30 +258,21 @@ impl SatResolve {
243258 . collect ( ) ;
244259
245260 // 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+ ) ;
258268
259269 // 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+ ) ;
270276
271277 let mut by_name: HashMap < & ' static str , Vec < PackageId > > = HashMap :: new ( ) ;
272278
@@ -389,13 +395,7 @@ impl SatResolve {
389395
390396 // a package `can_see` only one version by each name
391397 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) ) ) ;
399399 }
400400 let mut solver = varisat:: Solver :: new ( ) ;
401401 solver. add_formula ( & cnf) ;
0 commit comments