diff --git a/src/Lean/Meta/AbstractMVars.lean b/src/Lean/Meta/AbstractMVars.lean index f4b63f138d..da60e24bcd 100644 --- a/src/Lean/Meta/AbstractMVars.lean +++ b/src/Lean/Meta/AbstractMVars.lean @@ -67,6 +67,9 @@ private partial def abstractLevelMVars (u : Level) : M Level := do modify fun s => { s with nextParamIdx := s.nextParamIdx + 1, lmap := s.lmap.insert mvarId u, paramNames := s.paramNames.push paramId } return u +/-- +Abstracts metavariables in `e`. Assumes `instantiateMVars` has been applied to `e`. +-/ partial def abstractExprMVars (e : Expr) : M Expr := do if !e.hasMVar then return e @@ -88,28 +91,24 @@ partial def abstractExprMVars (e : Expr) : M Expr := do if decl.depth != (← getMCtx).depth then return e else - let eNew ← instantiateMVars e - if e != eNew then - abstractExprMVars eNew - else - match (← get).emap[mvarId]? with - | some e => - return e - | none => - let type ← abstractExprMVars decl.type - let fvarId ← mkFreshFVarId - let fvar := mkFVar fvarId; - let userName ← if decl.userName.isAnonymous then - pure <| (`x).appendIndexAfter (← get).fvars.size - else - pure decl.userName - modify fun s => { - s with - emap := s.emap.insert mvarId fvar - fvars := s.fvars.push fvar - mvars := s.mvars.push e - lctx := s.lctx.mkLocalDecl fvarId userName type } - return fvar + match (← get).emap[mvarId]? with + | some e => + return e + | none => + let type ← abstractExprMVars (← instantiateMVars decl.type) + let fvarId ← mkFreshFVarId + let fvar := mkFVar fvarId; + let userName ← if decl.userName.isAnonymous then + pure <| (`x).appendIndexAfter (← get).fvars.size + else + pure decl.userName + modify fun s => { + s with + emap := s.emap.insert mvarId fvar + fvars := s.fvars.push fvar + mvars := s.mvars.push e + lctx := s.lctx.mkLocalDecl fvarId userName type } + return fvar end AbstractMVars diff --git a/tests/lean/run/abstractMVars.lean b/tests/lean/run/abstractMVars.lean new file mode 100644 index 0000000000..c90c48782e --- /dev/null +++ b/tests/lean/run/abstractMVars.lean @@ -0,0 +1,23 @@ +import Lean +/-! +# Tests of the `Lean.Meta.abstractMVars` procedure +-/ + +open Lean Meta + +/-! +The following example used to abstract `levelMVar` even though it was assigned. +The issue was that the procedure failed to instantiateMVars in the types of metavariables. + +Reported on Zulip: https://leanprover.zulipchat.com/#narrow/channel/239415-metaprogramming-.2F-tactics/topic/.60abstractMVars.60.20not.20instantiating.20level.20mvars/near/541918246 +-/ + +/-- info: [] -/ +#guard_msgs in +run_meta + let levelMVar ← mkFreshLevelMVar + let mvar ← mkFreshExprMVar (some (mkSort levelMVar)) + discard <| isDefEq (mkSort levelMVar) (mkSort (mkLevelParam `u)) + let mvar ← instantiateMVars mvar + let abstractResult ← abstractMVars mvar + Lean.logInfo m!"{abstractResult.paramNames}"