Zulip Chat Archive

Stream: lean4

Topic: Tactic.SavedState.restore


Marcus Rossel (Feb 01 2024 at 13:35):

The result of calling Tactic.SavedState.restore is different depending on how variables were introduced into the local context:

import Lean
open Lean Meta Elab Tactic

elab "ex" : tactic => do
  let t  getMainTarget
  let s  saveState
  evalTactic <|  `(tactic|simp only [Nat.zero_add])
  s.restore
  logInfo <|  ppExpr t

example (a b : Nat) : 0 + a = b := by
  ex -- 0 + a = b

example :  (a b : Nat), 0 + a = b := by
  intro a b
  ex -- 0 + _uniq.2298 = _uniq.2301

How can I restore the correct context in the second example?

Siddhartha Gadgil (Feb 01 2024 at 14:15):

I would guess that you need to also restore the Core, Meta and Elabstates.

Kyle Miller (Feb 01 2024 at 17:09):

When you see _uniq.1234 variables, that indicates that you have the wrong local context in the current state -- this is how fvars are pretty printed if the local context is wrong.

Since you're working with the main goal, you could do this:

elab "ex" : tactic => withMainContext do
  let t  getMainTarget
  let s  saveState
  evalTactic <|  `(tactic|simp only [Nat.zero_add])
  s.restore
  logInfo <|  ppExpr t

Kyle Miller (Feb 01 2024 at 17:10):

Also, no need to do ppExpr yourself if you use m! message strings.

logInfo m!"{t}"

Eric Wieser (Feb 01 2024 at 19:16):

Siddhartha Gadgil said:

I would guess that you need to also restore the Core, Meta and Elabstates.

These are already included in docs#Tactic.SavedState

Kyle Miller (Feb 01 2024 at 19:18):

By the way, there's a combinator wrapping up saveState/restoreState:

  withoutModifyingState do
    evalTactic <|  `(tactic|simp only [Nat.zero_add])

Eric Wieser (Feb 01 2024 at 19:21):

@Kyle Miller, how is the wrong local context showing up in the original version? Is it not being restored correctly with the rest of the state?

Kyle Miller (Feb 01 2024 at 19:25):

That's a good question, and I'm not sure. The local context is part of the reader state, so I thought it wasn't supposed to be modifiable.

Kyle Miller (Feb 01 2024 at 19:26):

I know though that in a tactic you can't count on the local context being set to anything sensible.

Jannis Limperg (Feb 01 2024 at 19:58):

The restoreState is a red herring:

import Lean
open Lean Meta Elab Tactic

elab "ex" : tactic => do
  let t  getMainTarget
  logInfo <|  ppExpr t

example (a b : Nat) : 0 + a = b := by
  ex -- 0 + a = b

example :  (a b : Nat), 0 + a = b := by
  intro a b
  ex -- 0 + _uniq.924 = _uniq.927

The real issue is that in both examples, the local context in which ex is run is that of the initial goal. But in the second example, the printed expression lives in the local context of the goal produced by intro a b.

In general, as Kyle says, the local context is not mutable and is therefore not part of the SavedState that gets saved by saveState and restored by restoreState.

Patrick Massot (Feb 02 2024 at 18:27):

To be clear, the normal way to fix Jannis' example is

elab "ex" : tactic => do
  let t  getMainTarget
  withMainContext do
  logInfo <|  ppExpr t

Last updated: May 02 2025 at 03:31 UTC