summaryrefslogtreecommitdiff
path: root/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@mit.edu>2016-05-30 17:58:02 -0400
committerGravatar Benjamin Barenblat <bbaren@mit.edu>2016-05-30 17:58:02 -0400
commite67c951ad9c5c637e36a6f025ba3d6e3ad945416 (patch)
tree0cfb5c339602e4bdebf4bf97f3f0ccc3923c14d1 /Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy
parent000aa762e1fee4b9bd83ec3d7c8b61fd203e2c9d (diff)
parentdf5c5f547990c1f80ab7594a1f9287ee03a61754 (diff)
Merge commit 'df5c5f5'
Diffstat (limited to 'Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy')
-rw-r--r--Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy32
1 files changed, 32 insertions, 0 deletions
diff --git a/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy b/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy
new file mode 100644
index 00000000..c54089f2
--- /dev/null
+++ b/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy
@@ -0,0 +1,32 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file shows cases where loops could hide behind equalities. In all three
+// cases we behave the same; that is, we don't warn for loops that would only
+// exist in the presence of an equality. The easiest way to understand the
+// issue, I (CPC) feel, is to look at the old case: f(x) could very well loop
+// with old(f(f(x))) if f(f(x)) did not change the heap at all.
+
+// This equality issue is generally undecidable. It could make sense to special
+// case `old`, but KRML and CPC decided against it on 2015-08-21. Future
+// experiences could cause a change of mind.
+
+class C { }
+function f(c: C): C
+function g(c: C): C
+function h(c: C, i: int): C
+
+// With explicit arguments
+method M0(i: int, j: int, sc: set<C>) {
+ assert forall c | c in sc :: true || h(c, i) == h(h(c, j), j);
+}
+
+// With implicit arguments (f and g respectively, to Apply)
+method M1(f: int -> int, g: int -> int) {
+ assert forall x :: true || f(x) == g(f(x));
+}
+
+// With implicit arguments (the heap, to old)
+method M2(sc: set<C>) {
+ assert forall c | c in sc :: true || f(c) == old(f(f(c)));
+}