lean4-htt/tests/lean/run/splitOrderIssue.lean
Leonardo de Moura 96e7ab078d
fix: performance issue when elaborating match-expressions with many literals (#9372)
This PR fixes a performance issue that occurs when generating equation
lemmas for functions that use match-expressions containing several
literals. This issue was exposed by #9322 and arises from a combination
of factors:

1. Literal values are compiled into a chain of dependent if-then-else
expressions.
2. Dependent if-then-else expressions are significantly more expensive
to simplify than regular ones.
3. The `split` tactic selects a target, splits it, and then invokes
`simp` on the resulting subgoals. Moreover, `simp` traverses the entire
goal bottom-up and does not stop after reaching the target.

This PR addresses the issue by introducing a custom simproc that avoids
recursively simplifying nested if-then-else expressions. It does **not**
alter the user-facing behavior of the `split` tactic because such a
change would be highly disruptive. Instead, the PR adds a new flag,
`backward.split` to control the behavior of the user-facing `split`
tactic. It is currently set to `true`, i.e., the old behavior is still
the default one. In a future PR, we should set this flag to `false` by
default and begin repairing all affected proofs.

closes #9322
2025-07-15 03:52:23 +00:00

64 lines
1.6 KiB
Text

example (b : Bool) : (if (if b then true else true) then 1 else 2) = 1 := by
split
next h =>
guard_target =ₛ (if true = true then 1 else 2) = 1
guard_hyp h : b = true
simp
next h =>
guard_target =ₛ (if true = true then 1 else 2) = 1
guard_hyp h : ¬b = true
simp
example (b : Bool) : (if h : (if b then true else true) then 1 else 2) = 1 := by
split
next h' =>
guard_target = (if h : true = true then 1 else 2) = 1
guard_hyp h' : b = true
simp
next h' =>
guard_target = (if h : true = true then 1 else 2) = 1
guard_hyp h' : ¬b = true
simp
opaque f (a : Nat) (h : a > 0) : Nat
axiom fax : f a h = a
example : (if h : (if true then a > 0 else False) then f a (by grind) else a) = a := by
split
next =>
split
next => simp [fax]
next => simp
next => simp
set_option backward.split false
example (b : Bool) : (if (if b then true else true) then 1 else 2) = 1 := by
split
next h =>
guard_target =ₛ (if true = true then 1 else 2) = 1
guard_hyp h : b = true
simp
next h =>
guard_target =ₛ (if true = true then 1 else 2) = 1
guard_hyp h : ¬b = true
simp
example (b : Bool) : (if h : (if b then true else true) then 1 else 2) = 1 := by
split
next h' =>
guard_target = (if h : true = true then 1 else 2) = 1
guard_hyp h' : b = true
simp
next h' =>
guard_target = (if h : true = true then 1 else 2) = 1
guard_hyp h' : ¬b = true
simp
example : (if h : (if true then a > 0 else False) then f a (by grind) else a) = a := by
split
next =>
split
next => simp [fax]
next => simp
next => simp