Skip to content

Commit 60f3328

Browse files
author
Sebastian Graf
committed
fix: Make split work with metavariables in the target
The fix consists of replacing an internal use of `apply` for instantiating match splitters by a new, simpler variant `applyN`. This new `applyN` is not prone to #8436, which is the ultimate cause for `split` failing on targets containing metavariables.
1 parent 4eccb5b commit 60f3328

File tree

4 files changed

+34
-6
lines changed

4 files changed

+34
-6
lines changed

src/Lean/Meta/Tactic/Apply.lean

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ private def reorderGoals (mvars : Array Expr) : ApplyNewGoals → MetaM (List MV
155155
| ApplyNewGoals.all => return mvars.toList.map Lean.Expr.mvarId!
156156

157157
/-- Custom `isDefEq` for the `apply` tactic -/
158-
private def isDefEqApply (cfg : ApplyConfig) (a b : Expr) : MetaM Bool := do
159-
if cfg.approx then
158+
private def isDefEqApply (approx : Bool) (a b : Expr) : MetaM Bool := do
159+
if approx then
160160
approxDefEq <| isDefEqGuarded a b
161161
else
162162
isDefEqGuarded a b
@@ -201,7 +201,7 @@ def _root_.Lean.MVarId.apply (mvarId : MVarId) (e : Expr) (cfg : ApplyConfig :=
201201
if i < rangeNumArgs.stop then
202202
let s ← saveState
203203
let (newMVars, binderInfos, eType) ← forallMetaTelescopeReducing eType i
204-
if (← isDefEqApply cfg eType targetType) then
204+
if (← isDefEqApply cfg.approx eType targetType) then
205205
return (newMVars, binderInfos)
206206
else
207207
s.restore
@@ -231,6 +231,21 @@ def _root_.Lean.MVarId.apply (mvarId : MVarId) (e : Expr) (cfg : ApplyConfig :=
231231
def _root_.Lean.MVarId.applyConst (mvar : MVarId) (c : Name) (cfg : ApplyConfig := {}) : MetaM (List MVarId) := do
232232
mvar.apply (← mkConstWithFreshMVarLevels c) cfg (term? := m!"'{.ofConstName c}'")
233233

234+
/-- Close the given goal using `e`, instantiated with `n` metavariables. -/
235+
def _root_.Lean.MVarId.applyN (mvarId : MVarId) (e : Expr) (n : Nat) (useApproxDefEq := true) : MetaM (List MVarId) :=
236+
mvarId.withContext do
237+
mvarId.checkNotAssigned `apply
238+
let targetType ← mvarId.getType
239+
let eType ← inferType e
240+
let (mvarIds, _, eType) ← forallMetaBoundedTelescope eType n
241+
unless mvarIds.size == n do
242+
throwError "Applied type takes fewer than {n} arguments:\n{indentExpr eType}"
243+
unless (← isDefEqApply useApproxDefEq eType targetType) do
244+
throwError "Type mismatch: target is\n{indentExpr targetType}\nbut applied expression has \
245+
type\n{indentExpr eType}\nafter applying {n} arguments."
246+
mvarId.assign (e.beta mvarIds)
247+
return (mvarIds.map (·.mvarId!)).toList
248+
234249
end Meta
235250

236251
open Meta

src/Lean/Meta/Tactic/Split.lean

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,7 @@ def applyMatchSplitter (mvarId : MVarId) (matcherDeclName : Name) (us : Array Le
248248
let splitter := mkAppN (mkApp splitter motive) discrsNew
249249
check splitter
250250
trace[split.debug] "after check splitter"
251-
let mvarIds ← mvarId.apply splitter
252-
unless mvarIds.length == matchEqns.size do
253-
throwError "internal error in `split` tactic: unexpected number of goals created after applying splitter auxiliary theorem `{matchEqns.splitterName}` for `{matcherDeclName}`"
251+
let mvarIds ← mvarId.applyN splitter matchEqns.size
254252
let (_, mvarIds) ← mvarIds.foldlM (init := (0, [])) fun (i, mvarIds) mvarId => do
255253
let numParams := matchEqns.splitterAltNumParams[i]!
256254
let (_, mvarId) ← mvarId.introN numParams

tests/lean/split_mvars_target.lean

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/-!
2+
Tests that `split` works when there are metavariables in the target.
3+
-/
4+
theorem split_subgoals {x : Option Nat × Nat} :
5+
match x.fst with
6+
| some _ => True
7+
| none => True
8+
:= by
9+
have h {P : Prop} {x'} : (x' = 4 ∧ P) → P := by simp
10+
apply h
11+
split
12+
rotate_right
13+
· exact 4
14+
· trivial
15+
· trivial

tests/lean/split_mvars_target.lean.expected.out

Whitespace-only changes.

0 commit comments

Comments
 (0)