-
Notifications
You must be signed in to change notification settings - Fork 262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Don't generate the "assume T.F(ins) == C.F(ins)" statement in the function override ensures check #2504
base: master
Are you sure you want to change the base?
Conversation
# Conflicts: # Source/Dafny/Verifier/Translator.cs
argsT.Add(etran.HeapExpr); | ||
} | ||
// add "ordinary" parameters (including "this", if any) | ||
var prefixCount = implInParams.Count - f.Formals.Count; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to imply that an implementing function can have more parameters than the trait-declared version. Given that this broke zero tests, it either a) doesn't exist as a feature (anymore?), or b) has no testing coverage. My gut tells me this was implemented optimistically but never used. If no one knows the history here I can dig into it.
@@ -3475,53 +3475,29 @@ public enum StmtType { NONE, ASSERT, ASSUME }; | |||
builder.Add(TrAssumeCmd(f.tok, etran.TrExpr(en.E))); | |||
} | |||
|
|||
//generating assume J.F(ins) == C.F(ins) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diff here is deceptive: removing the builder.Add(TrAssumeCmd(...))
line makes half of the lines here unused, but the other half is still needed if there is a result variable declared. Consider this as a two step edit: first removing those interspersed unneeded lines, and then moving the remainder inside the if (resultVariable != null)
block.
@@ -12,6 +12,7 @@ | |||
- feat: *Less code navigation when verifying code*: In the IDE, failing postconditions and preconditions error messages now immediately display the sub-conditions that Dafny could not prove. Both on hover and in the Problems window. (https://github.com/dafny-lang/dafny/pull/2434) | |||
- feat: Whitespaces and comments are kept in relevant parts of the AST (https://github.com/dafny-lang/dafny/pull/1801) | |||
- fix: NuGet packages no longer depend on specific patch releases of the .NET frameworks. | |||
- fix: Resolved unsoundness issue related to overriding functions declared in traits with `{:termination false}`. (https://github.com/dafny-lang/dafny/pull/2504) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong section of the release notes.
// Missing: ensures ret != 0 | ||
{ | ||
0 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you give a version of this example that doesn't use {:termination false}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, this fix isn't sufficient, as the fixed Dafny still accepts the following example:
module A {
trait {:termination false} Trait {
function method TotallyNotZero() : (ret: int)
ensures TotallyNotZero() != 0
}
}
module Main {
import opened A
class Class extends Trait {
function method TotallyNotZero() : (ret: int) {
0
}
}
method Boom() ensures false {
var c := new Class;
assert c.TotallyNotZero() == 0;
assert (c as Trait).TotallyNotZero() != 0;
}
}
(Notice the fact that ensures
now mentions TotallyNotZero
)
The problem really is linked to :termination false
, and specifically the fact that the postcondition of the trait function "leaks" into the override check.
After reading it, I also expected your patch to break the following case:
Since we would get the following:
… and how would Boogie prove
(And indeed uncommenting this axiom while keeping your patch makes the valid example above fail.) |
The reason I mention the override axiom is that it is "as powerful", modulo fuel issues, as the
The mere mention of |
I think this PR solves the actual issue at hand. That is incorrectly performing the overrides check in a multi module setting, while correctly doing so in a single module. All the counterexamples I've seen, also rely on the lack of termination checking, which is documented. |
Fixes #2500.
As described in #2500, this assume statement (
assume B.Class.TotallyNotZero(this) == A.Trait.TotallyNotZero(this);
in the example) may create a contradiction if the implementation violates the trait's function specification. It is also not necessary to form the proof obligation correctly, since the trait's declaration has to have no body and therefore assuming equivalence doesn't add any additional constraint anyway.By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.