-
Notifications
You must be signed in to change notification settings - Fork 402
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: Float RecApp out of applications #2818
Conversation
Open question: Should there be one |
Great question. I don't see any reason why it would hurt well-founded recursion. |
Will do (tomorrow) |
60aaeb4
to
996452c
Compare
(Apologies for force pushing to your branch, I am still diagnosing some CI weirdnesses!) |
|
This didn't work before ``` def f (n : Nat) : Nat := match n with | 0 => 0 | n + 1 => (f) n ``` because the `RecApp` metadata marker gets in the way. More practically relevant, such code is to be produced when using `rw` or `simp` in recursive theorems (see included test case). We can fix this by preprocessing the definitions and floating the `.mdata` marker out of applications. For structural recursion, there already exists a `preprocess` function; this now also floats out `.mdata` markers. For well-founded recursion, this introduces an analogous `preprocess` function. Fixes #2810. One test case output changes: With the `.mdata` out of the way, we get a different error message. Seems fine. Alternative approaches are: * Leaving the `.mdata` marker where it is, and looking around it. Tried in #2813, but not nice (many many places where `withApp` etc. need to be adjusted). * Moving the `.mdata` _inside_ the application, so that `withApp` still works. Tried in #2814. Also not nice, the invariant that the `.mdata` is around the `.const` is tedious to maintain.
996452c
to
044c3ec
Compare
Tried in #2823. Beta-reduction (if done as it is defined now) can remove
Maybe one could use a more careful form of beta-reduction that works for both, but I’d say it’s not worth for the gain, and who knows, maybe the next derecursifier that comes along may need some other set of preprocessors again. I left a note in the code that the difference between the two functions is deliberate. |
Note: the fact that the WF preprocessor does not remove beta redexes during preprocessing is a bug, which causes It may or may not be possible to remove betas without breaking the WF termination prover with the current preprocessor design, I have not looked in detail. Perhaps we need a postprocessor too. |
Thanks! That sounds indeed like you want to post-process them. Separate issue, I’d say? |
!bench |
Here are the benchmark results for commit 47d1e07. |
Will merge this on Wednesday. |
both Structural and WF recursion have a preprocess module (since #2818 at least). Back then I found that betareducing in WF, like it happens for structural, bytes because it would drop `let_fun` annotations, which are of course worth preserving. Now that #2973 is landed let's see if we can do it now. I hope that this fixes an issue where code like ``` theorem size_rev {α} (arr : Array α) (i : Nat) : (rev arr i).size = arr.size := by unfold rev split · rw [size_rev] rw [Array.size_swap] · rfl termination_by arr.size - i decreasing_by simp_wf; omega ``` fails but works with `size_rev _ _`. It fails due to some lambda-redexes that maybe go away. (Maybe we can also/additinally/alternatively track down where that redex is created and use `.beta` instead of `.app`.)
…cations (#3204) Recursive predefinitions contains “rec app” markers as mdata in the predefinitions, but sometimes these get in the way of termination checking, when you have ``` [mdata (fun x => f)] arg ``` Therefore, the `preprocess` pass floats them out of applications (originally only for structural recursion, since #2818 also for well-founded recursion). But the code was incomplete: Because `Meta.transform` calls `post` on `f x y` only once (and not also on `f x`) one has to float out of nested applications as well. A consequence of this can be that in a recursive proof, `rw [foo]` does not work although `rw [foo _ _]` does. Also adding the testcase where @david-christiansen and I stumbled over this (Maybe the two preprocess modules can be combined, now that #2973 is landed, will try that in a follow-up).
This didn't work before
because the
RecApp
metadata marker gets in the way. More practicallyrelevant, such code is to be produced when using
rw
orsimp
inrecursive theorems (see included test case).
We can fix this by preprocessing the definitions and floating the
.mdata
marker out of applications.For structural recursion, there already exists a
preprocess
function;this now also floats out
.mdata
markers.For well-founded recursion, this introduces an analogous
preprocess
function.
Fixes #2810.
One test case output changes: With the
.mdata
out of the way, we get adifferent error message. Seems fine.
Alternative approaches are:
.mdata
marker where it is, and looking around it.Tried in fix: Structural recursion in the presence of parentheses #2813, but not nice (many many places where
withApp
etc.need to be adjusted).
.mdata
inside the application, so thatwithApp
stillworks. Tried in fix: Move RecApp marker further inside the expression #2814. Also not nice, the invariant that the
.mdata
is around the
.const
is tedious to maintain.