Skip to content

Commit c208f29

Browse files
committed
fix: instantiate mvars in types of mvars in abstractMVars
This PR fixes an issue reported [on Zulip](https://leanprover.zulipchat.com/#narrow/channel/239415-metaprogramming-.2F-tactics/topic/.60abstractMVars.60.20not.20instantiating.20level.20mvars/near/541918246) where `abstractMVars` (which is used in typeclass inference and `simp` argument elaboration) was not instantiating metavariables in the types of metavariables, causing it to abstract already-assigned metavariables.
1 parent ac0b829 commit c208f29

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

src/Lean/Meta/AbstractMVars.lean

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ private partial def abstractLevelMVars (u : Level) : M Level := do
6767
modify fun s => { s with nextParamIdx := s.nextParamIdx + 1, lmap := s.lmap.insert mvarId u, paramNames := s.paramNames.push paramId }
6868
return u
6969

70+
/--
71+
Abstracts metavariables in `e`. Assumes `instantiateMVars` has been applied to `e`.
72+
-/
7073
partial def abstractExprMVars (e : Expr) : M Expr := do
7174
if !e.hasMVar then
7275
return e
@@ -88,28 +91,24 @@ partial def abstractExprMVars (e : Expr) : M Expr := do
8891
if decl.depth != (← getMCtx).depth then
8992
return e
9093
else
91-
let eNew ← instantiateMVars e
92-
if e != eNew then
93-
abstractExprMVars eNew
94-
else
95-
match (← get).emap[mvarId]? with
96-
| some e =>
97-
return e
98-
| none =>
99-
let type ← abstractExprMVars decl.type
100-
let fvarId ← mkFreshFVarId
101-
let fvar := mkFVar fvarId;
102-
let userName ← if decl.userName.isAnonymous then
103-
pure <| (`x).appendIndexAfter (← get).fvars.size
104-
else
105-
pure decl.userName
106-
modify fun s => {
107-
s with
108-
emap := s.emap.insert mvarId fvar
109-
fvars := s.fvars.push fvar
110-
mvars := s.mvars.push e
111-
lctx := s.lctx.mkLocalDecl fvarId userName type }
112-
return fvar
94+
match (← get).emap[mvarId]? with
95+
| some e =>
96+
return e
97+
| none =>
98+
let type ← abstractExprMVars (← instantiateMVars decl.type)
99+
let fvarId ← mkFreshFVarId
100+
let fvar := mkFVar fvarId;
101+
let userName ← if decl.userName.isAnonymous then
102+
pure <| (`x).appendIndexAfter (← get).fvars.size
103+
else
104+
pure decl.userName
105+
modify fun s => {
106+
s with
107+
emap := s.emap.insert mvarId fvar
108+
fvars := s.fvars.push fvar
109+
mvars := s.mvars.push e
110+
lctx := s.lctx.mkLocalDecl fvarId userName type }
111+
return fvar
113112

114113
end AbstractMVars
115114

tests/lean/run/abstractMVars.lean

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Lean
2+
/-!
3+
# Tests of the `Lean.Meta.abstractMVars` procedure
4+
-/
5+
6+
open Lean Meta
7+
8+
/-!
9+
The following example used to abstract `levelMVar` even though it was assigned.
10+
The issue was that the procedure failed to instantiateMVars in the types of metavariables.
11+
12+
Reported on Zulip: https://leanprover.zulipchat.com/#narrow/channel/239415-metaprogramming-.2F-tactics/topic/.60abstractMVars.60.20not.20instantiating.20level.20mvars/near/541918246
13+
-/
14+
15+
/-- info: [] -/
16+
#guard_msgs in
17+
run_meta
18+
let levelMVar ← mkFreshLevelMVar
19+
let mvar ← mkFreshExprMVar (some (mkSort levelMVar))
20+
discard <| isDefEq (mkSort levelMVar) (mkSort (mkLevelParam `u))
21+
let mvar ← instantiateMVars mvar
22+
let abstractResult ← abstractMVars mvar
23+
Lean.logInfo m!"{abstractResult.paramNames}"

0 commit comments

Comments
 (0)