lean4-htt/tests/lean/run/wfEqns2.lean
Joachim Breitner d1174e10e6
feat: always run clean_wf, even before decreasing_by (#5016)
Previously, the tactic state shown at `decreasing_by` would leak lots of
details about the translation, and mention `invImage`, `PSigma` etc.
This is not nice.
  
So this introduces `clean_wf`, which is like `simp_wf` but using
`simp`'s `only` mode, and runs this unconditionally. This should clean
up the goal to a reasonable extent.
  
Previously `simp_wf` was an unrestricted `simp […]` call, but we
probably don’t want arbitrary simplification to happen at this point, so
this now became `simp only` call. For backwards compatibility,
`decreasing_with` begins with `try simp`. The `simp_wf` tactic
is still available to not break too much existing code; it’s docstring
suggests to no longer use it.

With `set_option cleanDecreasingByGoal false` one can disable the use of
`clean_wf`. I hope this is only needed for debugging and understanding.
  
Migration advise: If your `decreasing_by` proof begins with `simp_wf`,
either remove that (if the proof still goes through), or replace with
`simp`.
  
I am a bit anxious about running even `simp only` unconditionally here,
as it may do more than some user might want, e.g. because of options
like `zetaDelta := true`. We'll see if we need to reign in this tactic
some more.

I wonder if in corner cases the `simp_wf` tactic might be able to close
the goal, and if that is a problem. If so, we may have to promote simp’s
internal `mayCloseGoal` parameter to a simp configuration option and use
that here.
  
fixes #4928
2024-08-15 14:42:15 +00:00

68 lines
1.2 KiB
Text

mutual
def g (i j : Nat) : Nat :=
if i < 5 then 0 else
match j with
| Nat.zero => 1
| Nat.succ j => h i j
termination_by (i + j, 0)
decreasing_by
· apply Prod.Lex.left
apply Nat.lt_succ_self
def h (i j : Nat) : Nat :=
match j with
| 0 => g i 0
| Nat.succ j => g i j
termination_by (i + j, 1)
decreasing_by
· apply Prod.Lex.right
decide
· apply Prod.Lex.left
apply Nat.lt_succ_self
end
/-- info: g.eq_1 (i : Nat) : g i Nat.zero = if i < 5 then 0 else 1 -/
#guard_msgs in
#check g.eq_1
/-- info: g.eq_2 (i j_2 : Nat) : g i j_2.succ = if i < 5 then 0 else h i j_2 -/
#guard_msgs in
#check g.eq_2
/--
info: g.eq_def (i j : Nat) :
g i j =
if i < 5 then 0
else
match j with
| Nat.zero => 1
| j.succ => h i j
-/
#guard_msgs in
#check g.eq_def
/-- error: unknown identifier 'g.eq_3' -/
#guard_msgs in
#check g.eq_3
/-- info: h.eq_1 (i : Nat) : h i 0 = g i 0 -/
#guard_msgs in
#check h.eq_1
/-- info: h.eq_2 (i j_2 : Nat) : h i j_2.succ = g i j_2 -/
#guard_msgs in
#check h.eq_2
/--
info: h.eq_def (i j : Nat) :
h i j =
match j with
| 0 => g i 0
| j.succ => g i j
-/
#guard_msgs in
#check h.eq_def
/-- error: unknown identifier 'h.eq_3' -/
#guard_msgs in
#check h.eq_3