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
56 lines
1.2 KiB
Text
56 lines
1.2 KiB
Text
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
|