Skip to content

Commit

Permalink
test: strengthen "failing_sccs_test", rename to "sccs" as it's not fa…
Browse files Browse the repository at this point in the history
…iling! (#660)

* Include situation with two loops
* Strengthen to point that test would fail if we reversed order of the
`sccs`
* Thus, update comment on order of sccs
* Driveby switch a lambda `|a,b| a.union(b)` to just
`ExtensionSet::union`
  • Loading branch information
acl-cqc committed Nov 8, 2023
1 parent 5bcb185 commit bf7a988
Showing 1 changed file with 25 additions and 12 deletions.
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]))
);
}
}

0 comments on commit bf7a988

Please sign in to comment.