lean4-htt/tests/lean/run/9322.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

56 lines
1.2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

structure CompoundName where
module : String
name : String
structure T where
name : CompoundName
placeholder : Nat
/--
Value whose size is bounded by a constant offset of another value.
-/
abbrev Bounded (α : Type _) [SizeOf α] {β} [SizeOf β] (e : β) (c : Int) := { a : α // sizeOf a ≤ sizeOf e + c }
def getArg (e : T) : Bounded T e (-1) := sorry
mutual
inductive A where
| a : A
| b : C → A
inductive C
| c : A → C
end
mutual
def mkA (x : T) : A :=
match x.name with
| CompoundName.mk "LongName" "a" => .a
| CompoundName.mk "LongName" "b" => .a
| CompoundName.mk "LongName" "c" => .a
| CompoundName.mk "LongName" "d" => .a
| CompoundName.mk "LongName" "e" => .a
| CompoundName.mk "LongName" "f" => .a
| CompoundName.mk "LongName" "g" => .a
| CompoundName.mk "LongName" "h" => .a
| CompoundName.mk "LongName" "i" => .a
| CompoundName.mk "LongName" "j" => .a
| CompoundName.mk "LongName" "k" => .a
| CompoundName.mk "LongName" "z" =>
let ⟨y, _⟩ := getArg x
.b (mkC y)
| _ => sorry
termination_by sizeOf x
def mkC (x : T) : C :=
match x.name with
| CompoundName.mk "LongName" "b" =>
let ⟨y, _⟩ := getArg x
.c (mkA y)
| f => sorry
termination_by sizeOf x
end