Skip to content

Commit a25d8e9

Browse files
committed
use a topological_order to only make a var where needed
1 parent 6454efd commit a25d8e9

File tree

1 file changed

+58
-51
lines changed

1 file changed

+58
-51
lines changed

tests/testsuite/support/resolver.rs

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use cargo::core::resolver::{self, Method};
1111
use cargo::core::source::{GitReference, SourceId};
1212
use cargo::core::Resolve;
1313
use cargo::core::{Dependency, PackageId, Registry, Summary};
14-
use cargo::util::{CargoResult, Config, ToUrl};
14+
use cargo::util::{CargoResult, Config, Graph, ToUrl};
1515

1616
use proptest::collection::{btree_map, vec};
1717
use proptest::prelude::*;
@@ -278,12 +278,15 @@ impl SatResolve {
278278

279279
let empty_vec = vec![];
280280

281+
let mut graph: Graph<PackageId, ()> = Graph::new();
282+
281283
let mut version_selected_for: HashMap<
282-
(PackageId, Dependency),
283-
HashMap<PackageId, varisat::Var>,
284+
PackageId,
285+
HashMap<Dependency, HashMap<PackageId, varisat::Var>>,
284286
> = HashMap::new();
285287
// active packages need each of there `deps` to be satisfied
286288
for p in registry.iter() {
289+
graph.add(p.package_id());
287290
for dep in p.dependencies() {
288291
let version: HashMap<PackageId, varisat::Var> = by_name
289292
.get(dep.package_name().as_str())
@@ -302,76 +305,80 @@ impl SatResolve {
302305
for (pid, var) in version.iter() {
303306
// if a version is selected then it needs to be activated
304307
solver.add_clause(&[var.negative(), var_for_is_packages_used[pid].positive()]);
308+
graph.link(p.package_id(), *pid);
305309
}
306-
version_selected_for.insert((p.package_id(), dep.clone()), version);
310+
version_selected_for
311+
.entry(p.package_id())
312+
.or_default()
313+
.insert(dep.clone(), version);
307314
}
308315
}
309316

310-
let publicly_exports: HashMap<PackageId, HashMap<PackageId, varisat::Var>> = registry
311-
.iter()
312-
.map(|s| {
313-
(
314-
s.package_id(),
315-
registry
316-
.iter()
317-
.map(|s| (s.package_id(), solver.new_var()))
318-
.collect(),
319-
)
320-
})
321-
.collect();
317+
let topological_order = graph.sort();
318+
319+
let mut publicly_exports: HashMap<PackageId, HashMap<PackageId, varisat::Var>> =
320+
HashMap::new();
322321

323322
for s in registry.iter() {
324323
// everything publicly depends on itself
325-
solver.add_clause(&[publicly_exports[&s.package_id()][&s.package_id()].positive()]);
324+
let var = publicly_exports
325+
.entry(s.package_id())
326+
.or_default()
327+
.entry(s.package_id())
328+
.or_insert_with(|| solver.new_var());
329+
solver.add_clause(&[var.positive()]);
326330
}
327331

328332
// if a `dep` is public then `p` `publicly_exports` all the things that the selected version `publicly_exports`
329-
for p in registry.iter() {
330-
for dep in p.dependencies().iter().filter(|d| d.is_public()) {
331-
for (ver, sel) in version_selected_for[&(p.package_id(), dep.clone())].iter() {
332-
for export in registry.iter() {
333-
solver.add_clause(&[
334-
sel.negative(),
335-
publicly_exports[ver][&export.package_id()].negative(),
336-
publicly_exports[&p.package_id()][&export.package_id()].positive(),
337-
]);
333+
for &p in topological_order.iter() {
334+
if let Some(deps) = version_selected_for.get(&p) {
335+
for (_, versions) in deps.iter().filter(|(d, _)| d.is_public()) {
336+
for (ver, sel) in versions {
337+
for (&export_pid, &export_var) in publicly_exports[ver].clone().iter() {
338+
let our_var = publicly_exports
339+
.entry(p)
340+
.or_default()
341+
.entry(export_pid)
342+
.or_insert_with(|| solver.new_var());
343+
solver.add_clause(&[
344+
sel.negative(),
345+
export_var.negative(),
346+
our_var.positive(),
347+
]);
348+
}
338349
}
339350
}
340351
}
341352
}
342353

343-
let can_see: HashMap<PackageId, HashMap<PackageId, varisat::Var>> = registry
344-
.iter()
345-
.map(|s| {
346-
(
347-
s.package_id(),
348-
registry
349-
.iter()
350-
.map(|s| (s.package_id(), solver.new_var()))
351-
.collect(),
352-
)
353-
})
354-
.collect();
354+
let mut can_see: HashMap<PackageId, HashMap<PackageId, varisat::Var>> = HashMap::new();
355355

356356
// if `p` `publicly_exports` `export` then it `can_see` `export`
357-
for p in registry.iter() {
358-
for export in registry.iter() {
359-
solver.add_clause(&[
360-
publicly_exports[&p.package_id()][&export.package_id()].negative(),
361-
can_see[&p.package_id()][&export.package_id()].positive(),
362-
]);
357+
for (&p, exports) in &publicly_exports {
358+
for (&export_pid, export_var) in exports {
359+
let our_var = can_see
360+
.entry(p)
361+
.or_default()
362+
.entry(export_pid)
363+
.or_insert_with(|| solver.new_var());
364+
solver.add_clause(&[export_var.negative(), our_var.positive()]);
363365
}
364366
}
365367

366368
// if `p` has a `dep` that selected `ver` then it `can_see` all the things that the selected version `publicly_exports`
367-
for p in registry.iter() {
368-
for dep in p.dependencies().iter() {
369-
for (ver, sel) in version_selected_for[&(p.package_id(), dep.clone())].iter() {
370-
for export in registry.iter() {
369+
for (&p, deps) in version_selected_for.iter() {
370+
for (_, versions) in deps {
371+
for (ver, sel) in versions {
372+
for (&export_pid, &export_var) in publicly_exports[ver].iter() {
373+
let our_var = can_see
374+
.entry(p)
375+
.or_default()
376+
.entry(export_pid)
377+
.or_insert_with(|| solver.new_var());
371378
solver.add_clause(&[
372379
sel.negative(),
373-
publicly_exports[ver][&export.package_id()].negative(),
374-
can_see[&p.package_id()][&export.package_id()].positive(),
380+
export_var.negative(),
381+
our_var.positive(),
375382
]);
376383
}
377384
}
@@ -381,7 +388,7 @@ impl SatResolve {
381388
// a package `can_see` only one version by each name
382389
for (_, see) in can_see.iter() {
383390
for (_, vers) in by_name.iter() {
384-
let same_name: Vec<_> = vers.iter().map(|p| see[p]).collect();
391+
let same_name: Vec<_> = vers.iter().filter_map(|p| see.get(p).cloned()).collect();
385392
sat_at_most_one(&mut solver, &same_name);
386393
}
387394
}

0 commit comments

Comments
 (0)