diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index 755dfc66b18..d43aacaa425 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -218,6 +218,21 @@ fn sat_at_most_one(solver: &mut impl varisat::ExtendFormula, vars: &[varisat::Va } } +fn sat_at_most_one_by_key( + cnf: &mut impl varisat::ExtendFormula, + data: impl Iterator, +) -> HashMap> { + // no two packages with the same links set + let mut by_keys: HashMap> = HashMap::new(); + for (p, v) in data { + by_keys.entry(p).or_default().push(v) + } + for key in by_keys.values() { + sat_at_most_one(cnf, key); + } + by_keys +} + /// Resolution can be reduced to the SAT problem. So this is an alternative implementation /// of the resolver that uses a SAT library for the hard work. This is intended to be easy to read, /// as compared to the real resolver. @@ -243,30 +258,21 @@ impl SatResolve { .collect(); // no two packages with the same links set - let mut by_links: HashMap<_, Vec> = HashMap::new(); - for p in registry.iter() { - if let Some(l) = p.links() { - by_links - .entry(l) - .or_default() - .push(var_for_is_packages_used[&p.package_id()]) - } - } - for link in by_links.values() { - sat_at_most_one(&mut cnf, link); - } + sat_at_most_one_by_key( + &mut cnf, + registry + .iter() + .map(|s| (s.links(), var_for_is_packages_used[&s.package_id()])) + .filter(|(l, _)| l.is_some()), + ); // no two semver compatible versions of the same package - let mut by_activations_keys: HashMap<_, Vec> = HashMap::new(); - for p in registry.iter() { - by_activations_keys - .entry(p.package_id().as_activations_key()) - .or_default() - .push(var_for_is_packages_used[&p.package_id()]) - } - for key in by_activations_keys.values() { - sat_at_most_one(&mut cnf, key); - } + let by_activations_keys = sat_at_most_one_by_key( + &mut cnf, + var_for_is_packages_used + .iter() + .map(|(p, &v)| (p.as_activations_key(), v)), + ); let mut by_name: HashMap<&'static str, Vec> = HashMap::new(); @@ -389,13 +395,7 @@ impl SatResolve { // a package `can_see` only one version by each name for (_, see) in can_see.iter() { - let mut by_name: HashMap<&'static str, Vec> = HashMap::new(); - for ((name, _, _), &var) in see { - by_name.entry(name.as_str()).or_default().push(var); - } - for same_name in by_name.values() { - sat_at_most_one(&mut cnf, same_name); - } + sat_at_most_one_by_key(&mut cnf, see.iter().map(|((name, _, _), &v)| (name, v))); } let mut solver = varisat::Solver::new(); solver.add_formula(&cnf);