diff --git a/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java b/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java
index c885b5d1..07d14976 100644
--- a/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java
+++ b/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java
@@ -734,12 +734,13 @@ else if (values instanceof Set) {
throw new IllegalArgumentException("Unexpected map entry");
}
// we mark ourselves as done before we did it,
- // so we don't do the that causes an extra round
+ // so we don't do the that causes an useless round
done.add(lhs);
IValue rhs;
while ((rhs = todo.poll()) != null) {
+ boolean rhsFull = done.contains(rhs);
for (IValue composed : result.get(rhs)) {
- if (result.__insert(lhs, composed) && !done.contains(composed)) {
+ if (result.__insert(lhs, composed) && !rhsFull) {
todo.push(composed);
}
}
diff --git a/src/test/java/io/usethesource/vallang/specification/IRelationTests.java b/src/test/java/io/usethesource/vallang/specification/IRelationTests.java
index 4a14f8b2..e192b7ba 100644
--- a/src/test/java/io/usethesource/vallang/specification/IRelationTests.java
+++ b/src/test/java/io/usethesource/vallang/specification/IRelationTests.java
@@ -12,6 +12,7 @@
import io.usethesource.vallang.ExpectedType;
import io.usethesource.vallang.GivenValue;
import io.usethesource.vallang.IList;
+import io.usethesource.vallang.IRelation;
import io.usethesource.vallang.ISet;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.ITuple;
@@ -55,7 +56,30 @@ public void transClosureLocs(@ExpectedType("rel[loc,loc]") ISet src) {
assertEquals(src.asRelation().closure().intersect(src), src);
}
-
+ @ParameterizedTest @ArgumentsSource(ValueProvider.class)
+ public void deepClosure(IValueFactory vf) {
+ IValue prev = vf.integer(0);
+ var rBuilder = vf.setWriter();
+ for (int i=1; i < 100; i++) {
+ IValue next = vf.integer(i);
+ rBuilder.appendTuple(prev, next);
+ prev = next;
+ }
+ var r = rBuilder.done().asRelation();
+
+ assertEquals(slowClosure(vf, r),r.closure(),() -> "Failed with input: " + r.toString());
+ }
+
+ private ISet slowClosure(IValueFactory vf, IRelation r) {
+ var prev = vf.set();
+ ISet result = r.asContainer();
+ while (!prev.equals(result)) {
+ prev = result;
+ result = result.union( r.compose(result.asRelation()));
+ }
+ return result;
+ }
+
@ParameterizedTest @ArgumentsSource(ValueProvider.class)
public void carrierForTriples(@ExpectedType("rel[int,int,int]") ISet src) {
ISet carrier = src.asRelation().carrier();