lean4-htt/tests/lean/run/eqnOptions.lean
Joachim Breitner d975e4302e
feat: fine-grained equational lemmas for non-recursive functions (#4154)
This is part of #3983.

Fine-grained equational lemmas are useful even for non-recursive
functions, so this adds them.

The new option `eqns.nonrecursive` can be set to `false` to have the old
behavior.

### Breaking channge

This is a breaking change: Previously, `rw [Option.map]` would rewrite
`Option.map f o` to `match o with … `. Now this rewrite will fail
because the equational lemmas require constructors here (like they do
for, say, `List.map`).

Remedies:

 * Split on `o` before rewriting.
* Use `rw [Option.map.eq_def]`, which rewrites any (saturated)
application of `Option.map`
* Use `set_option eqns.nonrecursive false` when *defining* the function
in question.

### Interaction with simp

The `simp` tactic so far had a special provision for non-recursive
functions so that `simp [f]` will try to use the equational lemmas, but
will also unfold `f` else, so less breakage here (but maybe performance
improvements with functions with many cases when applied to a
constructor, as the simplifier will no longer unfold to a large
`match`-statement and then collapse it right away).

For projection functions and functions marked `[reducible]`, `simp [f]`
won’t use the equational theorems, and will only use its internal
unfolding machinery.

### Implementation notes

It uses the same `mkEqnTypes` function as for recursive functions, so we
are close to a consistency here. There is still the wrinkle that for
recursive functions we don't split matches without an interesting
recursive call inside. Unifying that is future work.
2024-08-22 13:26:58 +00:00

55 lines
951 B
Text

/-! Tests that options affecting equational theorems work as expected. -/
namespace Test1
def nonrecfun : Bool → Nat
| false => 0
| true => 0
/--
info: equations:
theorem Test1.nonrecfun.eq_1 : nonrecfun false = 0
theorem Test1.nonrecfun.eq_2 : nonrecfun true = 0
-/
#guard_msgs in
#print equations nonrecfun
end Test1
namespace Test2
set_option eqns.nonrecursive false in
def nonrecfun : Bool → Nat
| false => 0
| true => 0
/--
info: equations:
theorem Test2.nonrecfun.eq_def : ∀ (x : Bool),
nonrecfun x =
match x with
| false => 0
| true => 0
-/
#guard_msgs in
#print equations nonrecfun
end Test2
namespace Test3
def nonrecfun : Bool → Nat
| false => 0
| true => 0
-- should have no effect
set_option eqns.nonrecursive false
/--
info: equations:
theorem Test3.nonrecfun.eq_1 : nonrecfun false = 0
theorem Test3.nonrecfun.eq_2 : nonrecfun true = 0
-/
#guard_msgs in
#print equations nonrecfun
end Test3