@@ -57,7 +57,7 @@ partial def genVCs (goal : MVarId) (ctx : Context) (fuel : Fuel) : MetaM Result
5757 mv.setTag (Name.mkSimple ("inv" ++ toString (idx + 1 )))
5858 for h : idx in [:state.vcs.size] do
5959 let mv := state.vcs[idx]
60- mv.setTag (Name.mkSimple ("vc" ++ toString (idx + 1 )) ++ (← mv.getTag))
60+ mv.setTag (Name.mkSimple ("vc" ++ toString (idx + 1 )) ++ (← mv.getTag).eraseMacroScopes )
6161 return { invariants := state.invariants, vcs := state.vcs }
6262where
6363 onFail (goal : MGoal) (name : Name) : VCGenM Expr := do
8585 let ty ← mvar.getType
8686 if ← isProp ty then
8787 -- Might contain more `P ⊢ₛ wp⟦prog⟧ Q` apps. Try and prove it!
88- mvar.assign (← tryGoal ty (← mvar.getTag))
88+ let prf ← tryGoal ty (← mvar.getTag)
89+ if ← mvar.isAssigned then
90+ throwError "Tried to assign already assigned metavariable `{← mvar.getTag}` while `tryGoal`. MVar: {mvar}\n Assignment: {mkMVar mvar}\n New assignment: {prf}"
91+ mvar.assign prf
8992 return
90-
9193 if ty.isAppOf ``PostCond || ty.isAppOf ``Invariant || ty.isAppOf ``SPred then
9294 -- Here we make `mvar` a synthetic opaque goal upon discharge failure.
9395 -- This is the right call for (previously natural) holes such as loop invariants, which
@@ -124,7 +126,7 @@ where
124126 let e ← instantiateMVarsIfMVarApp e
125127 let e := e.headBeta
126128 let goal := goal.withNewProg e -- to persist the instantiation of `e` and `trans`
127- trace[ Elab.Tactic.Do.vcgen] "Program: {e}"
129+ withTraceNode ` Elab.Tactic.Do.vcgen (msg := fun _ => return m! "Program: {e}" ) do
128130
129131 -- let-expressions
130132 if let .letE x ty val body _nonDep := e.getAppFn' then
@@ -179,6 +181,7 @@ where
179181 let res ← Simp.mkCongrArg context res
180182 return ← res.mkEqMPR prf
181183 assignMVars specHoles.toList
184+ trace[Elab.Tactic.Do.vcgen] "Unassigned specHoles: {(← specHoles.filterM (not <$> ·.isAssigned)).map fun m => (m.name, mkMVar m)}"
182185 return prf
183186 return ← onFail goal name
184187
@@ -373,36 +376,36 @@ def elabInvariants (stx : Syntax) (invariants : Array MVarId) (suggestInvariant
373376
374377 let mut dotOrCase := LBool.undef -- .true => dot
375378 for h : n in 0 ...alts.size do
376- let alt := alts[n]
377- match alt with
378- | `(invariantDotAlt| · $rhs) =>
379- if dotOrCase matches .false then
380- logErrorAt alt m!"Alternation between labelled and bulleted invariants is not supported."
381- break
382- dotOrCase := .true
383- let some mv := invariants[n]? | do
384- logErrorAt alt m!"More invariants have been defined ({alts.size}) than there were unassigned invariants goals `inv<n>` ({invariants.size})."
385- continue
386- withRef rhs do
387- discard <| evalTacticAt (← `(tactic| exact $rhs)) mv
388- | `(invariantCaseAlt| | $tag $args* => $rhs) =>
389- if dotOrCase matches .true then
390- logErrorAt alt m!"Alternation between labelled and bulleted invariants is not supported."
391- break
392- dotOrCase := .false
393- let n? : Option Nat := do
394- let `(binderIdent| $tag:ident) := tag | some n -- fall back to ordinal
395- let .str .anonymous s := tag.getId | none
396- s.dropPrefix? "inv" >>= Substring.toNat?
397- let some mv := do invariants[(← n?) - 1 ]? | do
398- logErrorAt alt m!"No invariant with label {tag} {repr tag}."
399- continue
400- if ← mv.isAssigned then
401- logErrorAt alt m!"Invariant {n?.get!} is already assigned."
402- continue
403- withRef rhs do
404- discard <| evalTacticAt (← `(tactic| rename_i $args*; exact $rhs)) mv
405- | _ => logErrorAt alt m!"Expected `invariantDotAlt`, got {alt}"
379+ let alt := alts[n]
380+ match alt with
381+ | `(invariantDotAlt| · $rhs) =>
382+ if dotOrCase matches .false then
383+ logErrorAt alt m!"Alternation between labelled and bulleted invariants is not supported."
384+ break
385+ dotOrCase := .true
386+ let some mv := invariants[n]? | do
387+ logErrorAt alt m!"More invariants have been defined ({alts.size}) than there were unassigned invariants goals `inv<n>` ({invariants.size})."
388+ continue
389+ withRef rhs do
390+ discard <| evalTacticAt (← `(tactic| exact $rhs)) mv
391+ | `(invariantCaseAlt| | $tag $args* => $rhs) =>
392+ if dotOrCase matches .true then
393+ logErrorAt alt m!"Alternation between labelled and bulleted invariants is not supported."
394+ break
395+ dotOrCase := .false
396+ let n? : Option Nat := do
397+ let `(binderIdent| $tag:ident) := tag | some n -- fall back to ordinal
398+ let .str .anonymous s := tag.getId | none
399+ s.dropPrefix? "inv" >>= Substring.toNat?
400+ let some mv := do invariants[(← n?) - 1 ]? | do
401+ logErrorAt alt m!"No invariant with label {tag} {repr tag}."
402+ continue
403+ if ← mv.isAssigned then
404+ logErrorAt alt m!"Invariant {n?.get!} is already assigned."
405+ continue
406+ withRef rhs do
407+ discard <| evalTacticAt (← `(tactic| rename_i $args*; exact $rhs)) mv
408+ | _ => logErrorAt alt m!"Expected `invariantDotAlt`, got {alt}"
406409
407410 if let `(invariantsKW| invariants) := invariantsKW then
408411 if alts.size < invariants.size then
@@ -469,18 +472,25 @@ def elabMVCGen : Tactic := fun stx => withMainContext do
469472 let goal ← getMainGoal
470473 let goal ← if ctx.config.elimLets then elimLets goal else pure goal
471474 let { invariants, vcs } ← VCGen.genVCs goal ctx fuel
475+ trace[Elab.Tactic.Do.vcgen] "after genVCs {← (invariants ++ vcs).mapM fun m => m.getTag}"
472476 let runOnVCs (tac : TSyntax `tactic) (vcs : Array MVarId) : TermElabM (Array MVarId) :=
473477 vcs.flatMapM fun vc => List.toArray <$> Term.withSynthesize do
474478 Tactic.run vc (Tactic.evalTactic tac *> Tactic.pruneSolvedGoals)
475479 let invariants ← Term.TermElabM.run' do
476480 let invariants ← if ctx.config.leave then runOnVCs (← `(tactic| try mleave)) invariants else pure invariants
481+ trace[Elab.Tactic.Do.vcgen] "before elabInvariants {← (invariants ++ vcs).mapM fun m => m.getTag}"
477482 elabInvariants stx[3 ] invariants (suggestInvariant vcs)
483+ let invariants ← invariants.filterM (not <$> ·.isAssigned)
484+ trace[Elab.Tactic.Do.vcgen] "before trying trivial VCs {← (invariants ++ vcs).mapM fun m => m.getTag}"
478485 let vcs ← Term.TermElabM.run' do
479486 let vcs ← if ctx.config.trivial then runOnVCs (← `(tactic| try mvcgen_trivial)) vcs else pure vcs
480487 let vcs ← if ctx.config.leave then runOnVCs (← `(tactic| try mleave)) vcs else pure vcs
481488 return vcs
482489 -- Eliminating lets here causes some metavariables in `mkFreshPair_triple` to become nonassignable
483490 -- so we don't do it. Presumably some weird delayed assignment thing is going on.
484491 -- let vcs ← if ctx.config.elimLets then liftMetaM <| vcs.mapM elimLets else pure vcs
492+ trace[Elab.Tactic.Do.vcgen] "before elabVCs {← (invariants ++ vcs).mapM fun m => m.getTag}"
485493 let vcs ← elabVCs stx[4 ] vcs
494+ trace[Elab.Tactic.Do.vcgen] "before replacing main goal {← (invariants ++ vcs).mapM fun m => m.getTag}"
486495 replaceMainGoal (invariants ++ vcs).toList
496+ -- trace[ Elab.Tactic.Do.vcgen ] "replaced main goal, new: {← getGoals}"
0 commit comments