Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: strengthen "failing_sccs_test", rename to "sccs" as it's not failing! #660

Merged
merged 7 commits into from
Nov 8, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions src/extension/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ impl UnificationContext {
});

let (rs, other_ms): (Vec<_>, Vec<_>) = plus_constraints.unzip();
let solution = rs.iter().fold(ExtensionSet::new(), |e1, e2| e1.union(e2));
let solution = rs.iter().fold(ExtensionSet::new(), ExtensionSet::union);
let unresolved_metas = other_ms
.into_iter()
.filter(|other_m| m != *other_m)
Expand All @@ -705,9 +705,8 @@ impl UnificationContext {
println!("{:?}", relations.node_map);
println!("{:?}", relations.graph);

// Process the strongly-connected components. We need to deal with these
// depended-upon before depender. ccs() gives them back in some order
// - this might need to be reversed????
// Process the strongly-connected components. petgraph/sccs() returns these
// depended-upon before dependant, as we need.
for cc in relations.sccs() {
// Strongly connected components are looping constraint dependencies.
// This means that each metavariable in the CC has the same solution.
Expand Down Expand Up @@ -1664,22 +1663,36 @@ mod test {
// Test that logic for dealing with self-referential constraints doesn't
// fall over when a self-referencing group of metas also references a meta
// outside the group
fn failing_sccs_test() {
fn sccs() {
let hugr = Hugr::default();
let mut ctx = UnificationContext::new(&hugr);
// Make a strongly-connected component (loop)
let m1 = ctx.fresh_meta();
let m2 = ctx.fresh_meta();
let m3 = ctx.fresh_meta();
// Outside of the connected component
let m_other = ctx.fresh_meta();
// These 3 metavariables form a loop
ctx.add_constraint(m1, Constraint::Plus(ExtensionSet::singleton(&A), m3));
ctx.add_constraint(m2, Constraint::Plus(ExtensionSet::singleton(&A), m1));
ctx.add_constraint(m2, Constraint::Plus(ExtensionSet::singleton(&B), m1));
ctx.add_constraint(m3, Constraint::Plus(ExtensionSet::singleton(&A), m2));
// This other meta is outside the loop, but depended on by one of the loop metas
ctx.add_constraint(m2, Constraint::Plus(ExtensionSet::singleton(&A), m_other));
// And a second scc
let m4 = ctx.fresh_meta();
let m5 = ctx.fresh_meta();
ctx.add_constraint(m4, Constraint::Plus(ExtensionSet::singleton(&C), m5));
ctx.add_constraint(m5, Constraint::Plus(ExtensionSet::singleton(&C), m4));
// Make second component depend upon first
ctx.add_constraint(
m4,
Constraint::Plus(ExtensionSet::singleton(&UNKNOWN_EXTENSION), m3),
);
ctx.variables.insert(m1);
ctx.variables.insert(m_other);
ctx.variables.insert(m4);
ctx.instantiate_variables();
assert_eq!(
ctx.get_solution(&m1),
Some(&ExtensionSet::from_iter([A, B]))
);
assert_eq!(
ctx.get_solution(&m4),
Some(&ExtensionSet::from_iter([A, B, C, UNKNOWN_EXTENSION]))
);
}
}