-
Notifications
You must be signed in to change notification settings - Fork 257
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
[Feature request]: Weakest Precondition calculus (a.k.a. verification debugging or "Move assert up") with Code Actions #3102
Comments
In the advanced example you describe refactorings that simplify expressions, but that seems like a feature that's quite different from using WP rules to move assertions up. Could you put that in a separate issue? I think it would be good to have a crisp scope for this one. Also, one cool feature of moving assertion using WP rules is that it can cause a program to verify when it did not do so before, if it moves assertions are into loop invariants or requires clauses, since both of those are proof boundaries. You mention this at the end of your advanced example, but I would highlight this early and show a simple example where this works. Also, I would mention that we can choose to either copy or move assertions, and choose to take steps of 1 statement or step until the requires, and say something about which one we would like to offer and why. |
Issue created. Good idea, although the mechanisms are the same, we could make it two different projects given their nature.
Done, I edited the description.
I added all the possible envisioned alternatives and my currently favorite. |
What is the feature you would like to see in a future version of Dafny?
I would like to be able to "move assertions up" a.k.a. weakest precondition calculus.
There is a whole chapter in the doc that could simply be automated by code actions
https://dafny.org/latest/DafnyRef/DafnyRef#sec-verification-debugging
We also need to decide whether or not we keep the implied assertion, and how to offer this affordance to users. Our choices are the following:
With my experience, I would be inclined to vote for 1 and 3 together, until we have something automatic to clean up useless assertions.
Move an assertion to a requires or an invariant
To a requires clause
could become, after a code action on hovering the failing assertion:
To an invariant
could become, after a code action on hovering the failing assertion:
Simple example: if-then-else
Propagate assertions up
In the following code, every time an assertion
n
is failing, a code action could insert the assertionn+1
(andn+1
b if relevant)Advanced example: Quantum precondition
Here is an interesting example I came across of where automated back-propagation of assertions could be useful. Let's say we have this function, and we want to know what's missing to prove the requirement of the last function call:
First step, we could explicit the failing precondition using a code action that would replace the variable "s" by the expression
Since we have the definition of pairs, we can replace
pairs
with that definition using a code action that would insert a new assertionAnother code action could then simplify this expression idiomatically by inserting a new assertion again, as described in #3114 :
Another code action now can simplify this forall further by inlining the definition of k:
One more code action can simplify the code an add an assertion above.
With two code actions, one could inline the definition of
init
andlast
, like this:Another code action could help simplification
Last but not least, another code action could simply move the first assert to a requires, making the function to verify:
Another idea then is to automatically detect redundant assertions to clean up this code, but this is another issue.
Heap-sensitive weakest precondition calculus
Answer to this problem: https://stackoverflow.com/questions/74677214/dafny-verification-of-the-most-simple-array-summation-does-not-work-can-somebo/74691162#74691162
Consider the following code:
Making the assertion explicit would result in
Now, we cannot just "move the assert up", because we would otherwise have to reason about the state of the heap after the assignment, and old@ cannot refer to a label defined afterwards yet (right, @RustanLeino ?)
So, the next step would be to introduce the label and do the weakest precondition calculus below the assignment
The nice thing about that is that it would help the user discover the "old" syntax in a natural way.
Because the weakest precondition now sees two more potentially conflicting references, it could suggest the following code action to remove the reference to the heap after the assignment:
Now, because this expression does not refer at all to the heap after the assignment
c[j}
, the weakest precondition calculus would be able to move this assertion before and remove theold@
expressions.and eventually move it to a requires of the method. The user can then refine this weakest precondition so that they only keep
a != c && b != c
if they wanted to. Or not.The text was updated successfully, but these errors were encountered: