diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b6ee6bb9576..ce58db128ea 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -17,6 +17,7 @@ (https://github.com/dafny-lang/dafny/pull/2522) - feat: `predicate P(x: int): (y: bool) ...` is now valid syntax (https://github.com/dafny-lang/dafny/pull/2454) - fix: Improve the performance of proofs involving bit vector shifts (https://github.com/dafny-lang/dafny/pull/2520) +- fix: Perform well-definedness checks for ensures clauses of forall statements (https://github.com/dafny-lang/dafny/pull/2606) # 3.7.3 diff --git a/Source/Dafny/Verifier/Translator.TrStatement.cs b/Source/Dafny/Verifier/Translator.TrStatement.cs index 4331a7cbe8d..73627bd280c 100644 --- a/Source/Dafny/Verifier/Translator.TrStatement.cs +++ b/Source/Dafny/Verifier/Translator.TrStatement.cs @@ -993,9 +993,9 @@ void TrForallProof(ForallStmt s, BoogieStmtListBuilder definedness, BoogieStmtLi // havoc x,y; // CheckWellformed( Range ); // assume Range(x,y); - // Tr( Body ); // CheckWellformed( Post ); - // assert Post; + // Tr( Body ); // include only if there is a Body + // assert Post; // include only if there is a Body // assume false; // } else { // assume (forall x,y :: Range(x,y) ==> Post(x,y)); @@ -1022,12 +1022,18 @@ void TrForallProof(ForallStmt s, BoogieStmtListBuilder definedness, BoogieStmtLi TrStmt_CheckWellformed(s.Range, definedness, locals, etran, false); definedness.Add(TrAssumeCmd(s.Range.tok, etran.TrExpr(s.Range))); + var ensuresDefinedness = new BoogieStmtListBuilder(this); + foreach (var ens in s.Ens) { + TrStmt_CheckWellformed(ens.E, ensuresDefinedness, locals, etran, false); + ensuresDefinedness.Add(TrAssumeCmd(ens.E.tok, etran.TrExpr(ens.E))); + } + PathAsideBlock(s.Tok, ensuresDefinedness, definedness); + if (s.Body != null) { TrStmt(s.Body, definedness, locals, etran); // check that postconditions hold foreach (var ens in s.Ens) { - bool splitHappened; // we actually don't care foreach (var split in TrSplitExpr(ens.E, etran, true, out splitHappened)) { if (split.IsChecked) { diff --git a/Test/git-issues/git-issue-2605.dfy b/Test/git-issues/git-issue-2605.dfy new file mode 100644 index 00000000000..395dcb72279 --- /dev/null +++ b/Test/git-issues/git-issue-2605.dfy @@ -0,0 +1,12 @@ +// RUN: %dafny_0 /compile:0 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +method M(a: array, j: int) { + forall n | 0 <= n < 100 + ensures n / 0 == n / 0 // error (x2): division by zero + ensures a[j] == a[j] // error (x2): array index out of bounds + { + assert false; // error + } + assert false; // error +} diff --git a/Test/git-issues/git-issue-2605.dfy.expect b/Test/git-issues/git-issue-2605.dfy.expect new file mode 100644 index 00000000000..2c8cc2e51ad --- /dev/null +++ b/Test/git-issues/git-issue-2605.dfy.expect @@ -0,0 +1,7 @@ +git-issue-2605.dfy(6,14): Error: possible division by zero +git-issue-2605.dfy(6,23): Error: possible division by zero +git-issue-2605.dfy(7,13): Error: index out of range +git-issue-2605.dfy(7,21): Error: index out of range +git-issue-2605.dfy(9,11): Error: assertion might not hold + +Dafny program verifier finished with 0 verified, 5 errors