decreases via_fns are unusable #1521
Replies: 6 comments 1 reply
|
you need to use the turbofish syntax: |
|
you might also find it useful to use |
|
I very much appreciate the suggestions; they'll unblock my immediate need. I think the discussion point still stands. "m.dom().choose()" is a dark magic trigger that's unguessable (even by an experienced user). The turbofish syntax will let me declare the via_fn, but the UI for via_fns -- in which you have to construct expressions and imagine how they'll get pasted into the VC -- is still very opaque. The documentation doesn't explain it, and I doubt even proper documentation would make it usable without expert guidance, much less diagnosable. |
|
I agree -- it seems like there are a couple of issues here. One is that the automation provided by (and Dafny automatically infers the decreases clause of The second issue is that the current documentation of The third issue is that writing a separate
Jon offers one suggestion for achieving a more unified, Dafny-like experience, which would eliminate all of this boilerplate. A smaller step in that direction might be to change the syntax so that you can write |
|
In the department of funny coincidences, once I was unblocked by Travis' reply, I chased the triggers down and ended up realizing I'd fallen into another finiteness trap (discussion #1512). But yes, Bryan's breakdown of issues is valuable. Thanks to both of you. |
|
Please note that we (primarily @Chris-Hawblitzel) have refactored VC gen towards allowing @jonhnet I suspect you'd be happy if you could just write the termination proof inline, correct? |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Let's make a little recursive spec fn to transform a map into a sequence of pairs:
Verus reasonably demands a decreases clause, so we add:
Verus says "error: could not prove termination". From here, we can go in two directions.
First, we can try to guess how to prove termination. I happen to already know the set library bowels well enough to diagnose that I need trigger
axiom_set_remove_len, so I try rewriting the if condition into a statement aboutm.dom().len().That doesn't work, but I notice a hint that I haven't satisfied the recommends for
choose, so I try rewriting the if condition to!exists.That doesn't happen to work, either. I tried a few more variations on syntaxes hoping to trigger the axiom, such as rewriting the sub map to be a
Map::newclosure, but nothing happens to work, and there's no way to diagnose why I've missed the trigger.So let's try the alternative direction: I try to follow the rather cryptic description of
decreases. So I add a signature:Verus complains
cannot infer type of the type parameterK``, so I change it:And now the error is
This last problem is probably a fixable bug in the via parsing mechanism, and maybe we should fix that because, right now, this code isn't writable even with all the dark magical knowledge I already applied. However, the overall experience is completely inaccessible to a non-insider, and that's before we get to the weird way to actually express the proof inside the
#[via_fn], which even I don't actually understand. It's some dark magic where the expressions in the proof fn get pasted inline into the spec fn.It's worth contrasting this experience with the experience in Dafny: If you need a decreases clause, and it doesn't prove out of the box, you do what you'd do in any other proof text anywhere else in the language: you write
asserts and callproof fns from the appropriate branches of the definition until the proof obligation is retired.I'm not sure what technical challenges stand in the way of accomplishing a more usable approach. Perhaps
spec fns withdecreasesdeclarations could be parsed in two passes: In one pass, the assert text stripped out, which is the mode we have today that gives the definition of the fn. In a second pass, the text is transformed into aproof fn;requiresis inserted based ondecreases when, assertions about the decreases clause are inserted at recursive invocations, and asserts and proof fn invocations are left in place to allow the user to explore and complete the proof.All reactions