-
Notifications
You must be signed in to change notification settings - Fork 261
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add test file * Don't remove Lit brackets when assert/assume By removing this optimization (?), a condition like `false` is no longer passed to Boogie that way, but instead of `Lit(false)`. * Refactor Assert helper methods This change also removes a redundant `this.assertionCount++;`. This increment is done by the `builder.Add` method anyway. * Redo changes lost in the merge Co-authored-by: Robin Salkeld <salkeldr@amazon.com> Co-authored-by: Remy Willems <rgv.willems@gmail.com>
- Loading branch information
1 parent
3b53cc4
commit 2d4176b
Showing
10 changed files
with
270 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
// RUN: %dafny "%s" > "%t" | ||
// RUN: %diff "%s.expect" "%t" | ||
|
||
// This file tests various ways of writing the equivalent of "assume false;" or "assert false;" inside a loop. | ||
// It used to be that Dafny's translation of such statements into Boogie could cause Boogie to cut off the | ||
// loop back edge, which would turn a loop into something that wasn't a loop. In particular, it would cause | ||
// the expected "havoc loop_targets;" statement never to be generated, whose dramatic impact on what gets | ||
// verified would be both mysterious and surprising to most Dafny users. | ||
// | ||
// The equally mysterious workaround for this problem used to be for Dafny users to replace their "assume false;" | ||
// with something like "assume 2 < 2;", which Boogie wouldn't recognize in the same way. | ||
// | ||
// The current translation to Boogie makes sure that no user-supplied expression turns into exactly an | ||
// "assume false;" or "assert false;". This means that Dafny users can use a statement like "assume false;" | ||
// without chopping off back edges. | ||
// | ||
// It is still possible (in situations that would be rare in practice) to get some initially-surprising behavior | ||
// from Boogie, because it is possible to introduce a "false" condition that will be detected by the control-flow | ||
// handling in Boogie's abstract interpreter. Method Conjuncts4 below shows such an example. | ||
|
||
method M0(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method M1(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assume false; | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method M2(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assume 2 < 2; | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method M3(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assert false; // error | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method M4(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assert 2 < 2; // error | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method M5(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assert false by { // error | ||
} | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
predicate P() { true } | ||
predicate Q() { true } | ||
predicate R(n: nat) { true } | ||
predicate False() { false } | ||
|
||
method Conjuncts0(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assume P() && false && Q(); | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method Conjuncts1(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assert P() && false && Q(); // error | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method Conjuncts2(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assume False(); | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method Conjuncts3(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
assert False(); // error | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method Conjuncts4(n: nat, m: nat) { | ||
var i := 0; | ||
while i < n { | ||
assert R(m) && false; // error | ||
i := i + 1; | ||
} | ||
// The following assertion is provable, because the "false" in the assertion above | ||
// gets noticed by Boogie's abstract interpreter, which then (correctly) figures out | ||
// that no control leads from inside the loop back to the loop head. Therefore, it | ||
// infers the loop invariant i == 0. | ||
// It takes a special (and unusual) condition to get this behavior. This example | ||
// uses two conjuncts, one of which is "false" and one of which is a non-Lit expression. | ||
assert n == 0; | ||
} | ||
|
||
method LoopInvariants(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
for j := 0 to 5 | ||
invariant false // error | ||
{ | ||
} | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method Calls0(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
FalsePre(); // error | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method Calls1(n: nat) { | ||
var i := 0; | ||
while i < n { | ||
FalsePost(); | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method FalsePre() | ||
requires false | ||
|
||
method FalsePost() | ||
ensures false | ||
|
||
method LabeledExpressions0(n: nat) | ||
requires A: false | ||
{ | ||
var i := 0; | ||
while i < n { | ||
reveal A; | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method LabeledExpressions1(n: nat) | ||
{ | ||
assert A: false; // error | ||
var i := 0; | ||
while i < n { | ||
reveal A; | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} | ||
|
||
method LabeledExpressions2(n: nat) | ||
{ | ||
assert A: false by { // error | ||
} | ||
var i := 0; | ||
while i < n { | ||
reveal A; | ||
i := i + 1; | ||
} | ||
assert n == 0; // error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
NoMoreAssume2Less2.dfy(26,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(35,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(44,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(50,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(53,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(59,13): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(62,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(68,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(72,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(86,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(92,18): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(95,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(104,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(110,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(78,20): Related location | ||
NoMoreAssume2Less2.dfy(113,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(119,19): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(135,16): Error: This loop invariant might not hold on entry. | ||
NoMoreAssume2Less2.dfy(135,16): Related message: loop invariant violation | ||
NoMoreAssume2Less2.dfy(140,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(146,12): Error: A precondition for this call might not hold. | ||
NoMoreAssume2Less2.dfy(162,11): Related location: This is the precondition that might not hold. | ||
NoMoreAssume2Less2.dfy(149,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(158,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(175,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(180,12): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(186,11): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(191,12): Error: assertion violation | ||
NoMoreAssume2Less2.dfy(198,11): Error: assertion violation | ||
|
||
Dafny program verifier finished with 0 verified, 26 errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.