-
Notifications
You must be signed in to change notification settings - Fork 261
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
Failure of existential introduction #2721
Comments
This issue has to do with how quantifiers are instantiated, see https://github.com/dafny-lang/dafny/wiki/FAQ#how-does-dafny-handle-quantifiers-ive-heard-about-triggers-what-are-those. (More precisely, how universal quantifiers are instantiated and how witnesses for existential quantifiers are found.) Essentially, the There may be a way to change Dafny's verification-condition generation so that some of these examples would go through automatically. For example, Dafny already is able to verify var x: nat :| a == x; whose proof obligation is the same as the postcondition of There are workarounds to make the examples above verify. Each one involves either manually giving triggers or changing the expressions involved in such a way that Dafny can find triggers for them automatically. Manual triggers are to be used very sparingly, if at all, but they can be effective in examples like those above. Depending on your taste, you may have objections to either workaround. In the following, I will show solutions using both. ghost function Id<X>(x: X): X { x }
lemma example_failing_1'(a: nat)
ensures exists x: nat :: a == Id(x) // Dafny picks Id(x) as the matching pattern
{
assert Id(a) == a; // this occurrence of Id(a) triggers the matching pattern
assert a == a;
} ghost predicate LookAtMe<X>(x: X) { true }
lemma example_failing_1''(a: nat)
ensures exists x: nat {:trigger LookAtMe(x)} :: a == x
{
assert LookAtMe(a);
assert a == a;
} ghost predicate Outer<X>(x: X) { true }
ghost predicate Inner<X>(x: X) { true }
lemma example_failing_2()
ensures forall a: nat :: Outer(a) ==> exists x: nat :: Inner(x) && a == x
{
forall a: nat | Outer(a)
ensures exists x: nat :: Inner(x) && a == x
{
assert Inner(a);
assert a == a;
}
} |
Also, you don't need to modify the inner part of the exists to prove it, you can also manually set up a trigger like this: function Trigger<T>(t: T): T { t }
lemma example_failing_1(a: nat)
ensures exists x: nat {:trigger Trigger(x)}:: a == x
{
var _ := Trigger(a);
} |
The following two examples give: Error: A postcondition might not hold on this return path.
Note for reference that the following does work:
Finally, a Coq reference:
The text was updated successfully, but these errors were encountered: