Skip to content

Commit ca4cb0c

Browse files
committed
perf: in CaseValues, subst only once
This PR avoids running `substCore` twice in `caseValues`.
1 parent 0173444 commit ca4cb0c

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

src/Lean/Meta/Match/CaseArraySizes.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def caseArraySizes (mvarId : MVarId) (fvarId : FVarId) (sizes : Array Nat) (xNam
6868
let mvarId ← mvarId.assertExt `aSize (mkConst `Nat) aSize
6969
let (aSizeFVarId, mvarId) ← mvarId.intro1
7070
let (hEq, mvarId) ← mvarId.intro1
71-
let subgoals ← caseValues mvarId aSizeFVarId (sizes.map mkRawNatLit) hNamePrefix
71+
let subgoals ← caseValues mvarId aSizeFVarId (sizes.map mkRawNatLit) hNamePrefix (substNewEqs := false)
7272
subgoals.mapIdxM fun i subgoal => do
7373
let subst := subgoal.subst
7474
let mvarId := subgoal.mvarId

src/Lean/Meta/Match/CaseValues.lean

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ structure CaseValueSubgoal where
2626
where `fvarId` is `x`s id.
2727
The type of `x` must have decidable equality.
2828
29+
If `substNewEq = false`, then the first case remains `C x`.
30+
2931
Remark: `subst` field of the second subgoal is equal to the input `subst`. -/
30-
private def caseValueAux (mvarId : MVarId) (fvarId : FVarId) (value : Expr) (hName : Name := `h) (subst : FVarSubst := {})
32+
private def caseValueAux (mvarId : MVarId) (fvarId : FVarId) (value : Expr) (hName : Name := `h)
33+
(subst : FVarSubst := {}) (substNewEq : Bool)
3134
: MetaM (CaseValueSubgoal × CaseValueSubgoal) :=
3235
mvarId.withContext do
3336
let tag ← mvarId.getTag
@@ -44,9 +47,11 @@ private def caseValueAux (mvarId : MVarId) (fvarId : FVarId) (value : Expr) (hNa
4447
let (elseH, elseMVarId) ← elseMVar.mvarId!.intro1P
4548
let elseSubgoal := { mvarId := elseMVarId, newH := elseH, subst := subst : CaseValueSubgoal }
4649
let (thenH, thenMVarId) ← thenMVar.mvarId!.intro1P
47-
let symm := false
48-
let clearH := false
49-
let (thenSubst, thenMVarId) ← substCore thenMVarId thenH symm subst clearH
50+
let (thenSubst, thenMVarId) ←
51+
if substNewEq then
52+
substCore thenMVarId thenH (symm := false) subst (clearH := false)
53+
else
54+
pure (subst, thenMVarId)
5055
thenMVarId.withContext do
5156
trace[Meta] "subst domain: {thenSubst.domain.map (·.name)}"
5257
let thenH := (thenSubst.get thenH).fvarId!
@@ -57,7 +62,7 @@ private def caseValueAux (mvarId : MVarId) (fvarId : FVarId) (value : Expr) (hNa
5762
pure (thenSubgoal, elseSubgoal)
5863

5964
def caseValue (mvarId : MVarId) (fvarId : FVarId) (value : Expr) : MetaM (CaseValueSubgoal × CaseValueSubgoal) := do
60-
let s ← caseValueAux mvarId fvarId value
65+
let s ← caseValueAux mvarId fvarId value (substNewEq := true)
6166
appendTagSuffix s.1.mvarId `thenBranch
6267
appendTagSuffix s.2.mvarId `elseBranch
6368
pure s
@@ -83,19 +88,19 @@ structure CaseValuesSubgoal where
8388
8489
If `substNewEqs = true`, then the new `h_i` equality hypotheses are substituted in the first `n` cases.
8590
-/
86-
def caseValues (mvarId : MVarId) (fvarId : FVarId) (values : Array Expr) (hNamePrefix := `h) (substNewEqs := false) : MetaM (Array CaseValuesSubgoal) :=
91+
def caseValues (mvarId : MVarId) (fvarId : FVarId) (values : Array Expr) (hNamePrefix := `h) (substNewEqs : Bool) : MetaM (Array CaseValuesSubgoal) :=
8792
let rec loop : Nat → MVarId → List Expr → Array FVarId → Array CaseValuesSubgoal → MetaM (Array CaseValuesSubgoal)
8893
| _, mvarId, [], _, _ => throwTacticEx `caseValues mvarId "list of values must not be empty"
8994
| i, mvarId, v::vs, hs, subgoals => do
90-
let (thenSubgoal, elseSubgoal) ← caseValueAux mvarId fvarId v (hNamePrefix.appendIndexAfter i) {}
95+
let (thenSubgoal, elseSubgoal) ← caseValueAux mvarId fvarId v (hNamePrefix.appendIndexAfter i) (substNewEq := !substNewEqs) {}
9196
appendTagSuffix thenSubgoal.mvarId ((`case).appendIndexAfter i)
9297
let thenMVarId ← hs.foldlM
9398
(fun thenMVarId h => match thenSubgoal.subst.get h with
9499
| Expr.fvar fvarId => thenMVarId.tryClear fvarId
95100
| _ => pure thenMVarId)
96101
thenSubgoal.mvarId
97102
let subgoals ← if substNewEqs then
98-
let (subst, mvarId) ← substCore thenMVarId thenSubgoal.newH false thenSubgoal.subst true
103+
let (subst, mvarId) ← substCore thenMVarId thenSubgoal.newH (symm := false) thenSubgoal.subst (clearH := true)
99104
pure <| subgoals.push { mvarId := mvarId, newHs := #[], subst := subst }
100105
else
101106
pure <| subgoals.push { mvarId := thenMVarId, newHs := #[thenSubgoal.newH], subst := thenSubgoal.subst }

tests/lean/run/meta6.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ withLocalDeclD `y nat fun y => do
7171
let vType ← mkAppM `Vec #[nat, x];
7272
withLocalDeclD `v vType fun v => do
7373
let m ← mkFreshExprSyntheticOpaqueMVar vType;
74-
let subgoals ← caseValues m.mvarId! x.fvarId! #[mkNatLit 2, mkNatLit 3, mkNatLit 5];
74+
let subgoals ← caseValues m.mvarId! x.fvarId! #[mkNatLit 2, mkNatLit 3, mkNatLit 5] (substNewEqs := false);
7575
subgoals.forM fun s => do {
7676
print (MessageData.ofGoal s.mvarId);
7777
s.mvarId.assumption

0 commit comments

Comments
 (0)