Skip to content

Commit 5143c0c

Browse files
committed
Work around accidentally quadratic debug_assert in varisat
1 parent c68334f commit 5143c0c

File tree

1 file changed

+28
-19
lines changed

1 file changed

+28
-19
lines changed

tests/testsuite/support/resolver.rs

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,10 @@ pub struct SatResolve {
235235

236236
impl SatResolve {
237237
pub fn new(registry: &[Summary]) -> Self {
238-
let mut solver = varisat::Solver::new();
238+
let mut cnf = varisat::CnfFormula::new();
239239
let var_for_is_packages_used: HashMap<PackageId, varisat::Var> = registry
240240
.iter()
241-
.map(|s| (s.package_id(), solver.new_var()))
241+
.map(|s| (s.package_id(), cnf.new_var()))
242242
.collect();
243243

244244
// no two packages with the same links set
@@ -252,7 +252,7 @@ impl SatResolve {
252252
}
253253
}
254254
for link in by_links.values() {
255-
sat_at_most_one(&mut solver, link);
255+
sat_at_most_one(&mut cnf, link);
256256
}
257257

258258
// no two semver compatible versions of the same package
@@ -264,7 +264,7 @@ impl SatResolve {
264264
.push(var_for_is_packages_used[&p.package_id()])
265265
}
266266
for key in by_activations_keys.values() {
267-
sat_at_most_one(&mut solver, key);
267+
sat_at_most_one(&mut cnf, key);
268268
}
269269

270270
let mut by_name: HashMap<&'static str, Vec<PackageId>> = HashMap::new();
@@ -288,6 +288,9 @@ impl SatResolve {
288288
for p in registry.iter() {
289289
graph.add(p.package_id());
290290
for dep in p.dependencies() {
291+
// This can more easily be written as:
292+
// !is_active(p) or one of the things that match dep is_active
293+
// All the complexity, from here to the end, is to support public and private dependencies!
291294
let mut by_key: HashMap<_, Vec<varisat::Lit>> = HashMap::new();
292295
for &m in by_name
293296
.get(dep.package_name().as_str())
@@ -300,21 +303,21 @@ impl SatResolve {
300303
.or_default()
301304
.push(var_for_is_packages_used[&m].positive());
302305
}
303-
let keys: HashMap<_, _> = by_key.keys().map(|&k| (k, solver.new_var())).collect();
306+
let keys: HashMap<_, _> = by_key.keys().map(|&k| (k, cnf.new_var())).collect();
304307

305308
// if `p` is active then we need to select one of the keys
306309
let matches: Vec<_> = keys
307310
.values()
308311
.map(|v| v.positive())
309312
.chain(Some(var_for_is_packages_used[&p.package_id()].negative()))
310313
.collect();
311-
solver.add_clause(&matches);
314+
cnf.add_clause(&matches);
312315

313316
// if a key is active then we need to select one of the versions
314317
for (key, vars) in by_key.iter() {
315318
let mut matches = vars.clone();
316319
matches.push(keys[key].negative());
317-
solver.add_clause(&matches);
320+
cnf.add_clause(&matches);
318321
}
319322

320323
version_selected_for
@@ -336,8 +339,8 @@ impl SatResolve {
336339
.entry(key)
337340
.or_default()
338341
.entry(key)
339-
.or_insert_with(|| solver.new_var());
340-
solver.add_clause(&[var.positive()]);
342+
.or_insert_with(|| cnf.new_var());
343+
cnf.add_clause(&[var.positive()]);
341344
}
342345

343346
// if a `dep` is public then `p` `publicly_exports` all the things that the selected version `publicly_exports`
@@ -350,8 +353,8 @@ impl SatResolve {
350353
.entry(p.as_activations_key())
351354
.or_default()
352355
.entry(export_pid)
353-
.or_insert_with(|| solver.new_var());
354-
solver.add_clause(&[
356+
.or_insert_with(|| cnf.new_var());
357+
cnf.add_clause(&[
355358
sel.negative(),
356359
export_var.negative(),
357360
our_var.positive(),
@@ -373,8 +376,8 @@ impl SatResolve {
373376
.entry(p)
374377
.or_default()
375378
.entry(export_pid)
376-
.or_insert_with(|| solver.new_var());
377-
solver.add_clause(&[export_var.negative(), our_var.positive()]);
379+
.or_insert_with(|| cnf.new_var());
380+
cnf.add_clause(&[export_var.negative(), our_var.positive()]);
378381
}
379382
}
380383

@@ -387,8 +390,8 @@ impl SatResolve {
387390
.entry(p.as_activations_key())
388391
.or_default()
389392
.entry(export_pid)
390-
.or_insert_with(|| solver.new_var());
391-
solver.add_clause(&[
393+
.or_insert_with(|| cnf.new_var());
394+
cnf.add_clause(&[
392395
sel.negative(),
393396
export_var.negative(),
394397
our_var.positive(),
@@ -405,9 +408,17 @@ impl SatResolve {
405408
by_name.entry(name.as_str()).or_default().push(var);
406409
}
407410
for same_name in by_name.values() {
408-
sat_at_most_one(&mut solver, same_name);
411+
sat_at_most_one(&mut cnf, same_name);
409412
}
410413
}
414+
let mut solver = varisat::Solver::new();
415+
solver.add_formula(&cnf);
416+
417+
// We dont need to `solve` now. We know that "use nothing" will satisfy all the clauses so far.
418+
// But things run faster if we let it spend some time figuring out how the constraints interact before we add assumptions.
419+
solver
420+
.solve()
421+
.expect("docs say it can't error in default config");
411422

412423
SatResolve {
413424
solver,
@@ -450,9 +461,7 @@ impl SatResolve {
450461

451462
self.solver
452463
.solve()
453-
.expect("docs say it can't error in default config");
454-
455-
self.solver.model().is_some()
464+
.expect("docs say it can't error in default config")
456465
}
457466
}
458467

0 commit comments

Comments
 (0)