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).
90 lines
1.5 KiB
Text
90 lines
1.5 KiB
Text
/-!
|
|
Test that parentheses don't get in the way of structural recursion.
|
|
https://github.com/leanprover/lean4/issues/2810
|
|
-/
|
|
|
|
namespace Unary
|
|
|
|
def f (n : Nat) : Nat :=
|
|
match n with
|
|
| 0 => 0
|
|
| n + 1 => (f) n
|
|
|
|
-- TODO: How can we assert that this was compiled structurally?
|
|
|
|
-- with beta-reduction
|
|
def f2 (n : Nat) : Nat :=
|
|
match n with
|
|
| 0 => 0
|
|
| n + 1 => (fun n' => (f2) n') n
|
|
|
|
-- structural recursion
|
|
def f3 (n : Nat) : Nat :=
|
|
match n with
|
|
| 0 => 0
|
|
| n + 1 => (f3) n
|
|
termination_by n
|
|
|
|
-- Same with rewrite
|
|
|
|
theorem f_zero (n : Nat) : f n = 0 := by
|
|
match n with
|
|
| .zero => rfl
|
|
| .succ n =>
|
|
unfold f
|
|
rewrite [f_zero]
|
|
rfl
|
|
|
|
-- Same with simp
|
|
|
|
theorem f_zero' (n : Nat) : f n = 0 := by
|
|
match n with
|
|
| .zero => rfl
|
|
| .succ n =>
|
|
unfold f
|
|
simp only [f_zero']
|
|
|
|
end Unary
|
|
|
|
namespace Binary
|
|
|
|
def f (n m : Nat) : Nat :=
|
|
match n with
|
|
| 0 => 0
|
|
| n + 1 => (f) n m
|
|
|
|
-- TODO: How can we assert that this was compiled structurally?
|
|
|
|
-- with beta-reduction
|
|
def f2 (n m : Nat) : Nat :=
|
|
match n with
|
|
| 0 => 0
|
|
| n + 1 => (fun n' => (f2) n' m) n
|
|
|
|
-- structural recursion
|
|
def f3 (n m : Nat) : Nat :=
|
|
match n with
|
|
| 0 => 0
|
|
| n + 1 => (f3) n m
|
|
termination_by n
|
|
|
|
-- Same with rewrite
|
|
|
|
theorem f_zero (n m : Nat) : f n m = 0 := by
|
|
match n with
|
|
| .zero => rfl
|
|
| .succ n =>
|
|
unfold f
|
|
rewrite [f_zero]
|
|
rfl
|
|
|
|
-- Same with simp
|
|
|
|
theorem f_zero' (n m : Nat) : f n m = 0 := by
|
|
match n with
|
|
| .zero => rfl
|
|
| .succ n =>
|
|
unfold f
|
|
simp only [f_zero']
|
|
|
|
end Binary
|