Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: Persisting hypotheses across tactics
Damiano Testa (Mar 25 2024 at 14:54):
This is not a well-defined question, but I hope that it is specific enough that maybe it can receive some useful comments.
For the purpose of this question, you can limit the set of existing tactics to just simp
, rw
and have
.
When looking at a proof in the infoview, you get the impression that (most) tactics preserve almost all the context and typically modify one location (or an explicit subset of locations in the case of tac at loc1 ... locn
).
From this perspective, it seems straightforward to "track" locations, e.g. persisting the ones on which simp
acted at some point during the proof.
While this heuristic idea is "visually" correct, there are several issues with it:
- the name of the location can become inaccessible (e.g.
have h : ...
makes a previoush
change its username); - the fvarid of a local declaraction can change (e.g.
rw at h
substitutesh
with a new local declaration with the same username, but different fvarid); - in the presence of several concurrent goals, the actual metavariables change name after most tactics act on them.
Thus, tracking in practice a location is very tricky.
My question is: is there some API around this?
Damiano Testa (Mar 25 2024 at 14:55):
My motivation comes from trying to write a version of the "non-terminal simp
" linter that would flag non-robust proofs.
Jannis Limperg (Mar 25 2024 at 18:56):
Tracking lctx changes is a very annoying problem for which I haven't found a good solution yet. There are two approaches:
- Identify hyps by user name. But as you say, this is not guaranteed to be unique or stable. However, if you work with a predetermined set of tactics (which you probably don't), then this can be a good option.
- Identify hyps by unique name (
FVarId
). But as you say, these change all the time:- When the type or value of a hyp is changed in a non-defeq way, the
FVarId
must change, even if the hyp retains the same user name and users would probably view it as "the same hyp, only modified". - Otherwise (even when nothing happens to the hyp), the
FVarId
may still change.revert
-based tactics do this a lot. In cases like these, theMetaM
tactic sometimes returns a docs#Lean.Meta.FVarSubst which maps oldFVarId
s to newFVarId
s. But not allMetaM
tactics report such substitutions, and when you operate at elaborator level and above, you're probably out of luck entirely.
- When the type or value of a hyp is changed in a non-defeq way, the
So yeah, it's tricky. :(
Damiano Testa (Mar 25 2024 at 21:50):
Ok, thank you for confirming that I am not reinventing some tools that already exist.
I'm going to record both the FVarId
and the username
and first scan the local contexts for the FVarId
and fall back on the username
if that fails.
Kyle Miller (Mar 25 2024 at 21:58):
Tactics are supposed to record a ofFVarAliasInfo
in the info trees to connect up fvars
Kyle Miller (Mar 25 2024 at 21:59):
That tracking is used for the unused variable linter and the "find references" editor feature for example.
Damiano Testa (Mar 25 2024 at 22:04):
docs#Lean.Elab.Info.ofFVarAliasInfo
docs#Lean.Elab.FVarAliasInfo
Damiano Testa (Mar 25 2024 at 22:05):
Thanks, Kyle! I'll experiment with this!
Damiano Testa (Mar 26 2024 at 08:22):
Kyle, I tried your suggestion, but trying this on a few "random" proofs, I could find Info
with the following constructors:
CommandInfo
CompletionInfo
MacroExpansionInfo
TacticInfo
TermInfo
OptionInfo
FieldInfo
This means that
UserWidgetInfo
CustomInfo
FVarAliasInfo
FieldRedeclInfo
OmissionInfo
appear very rarely (and actually never in the sample of files that I scanned).
Mario Carneiro (Mar 26 2024 at 10:26):
What proofs did you look at? Obviously the info nodes that appear depend on the proof
Damiano Testa (Mar 26 2024 at 13:28):
I opened a few random files (Data.Int.Lemmas, LinearAlgebra.Determinant, RingTheory.Algebra.Flat
according to my VSCode history) and I collected all the Info
s that I could see in those proofs.
Damiano Testa (Mar 26 2024 at 13:29):
In particular, I could find no appearance of FVarAliasInfo
, that I hoped would help with "persisting" hypotheses, as per Kyle's comment above.
Mario Carneiro (Mar 26 2024 at 21:20):
you should look at proofs that involve fvar changing, of course. That description is a bit generic, it's hard to tell if you actually saw something. For example proofs by induction on List will surely have this behvior
Damiano Testa (Mar 26 2024 at 21:32):
Ok, but the reason for looking for them was to help with persisting hypotheses, so the fact that they did not show up in those files makes me think that FVarAliasInfo
will not actually be useful for this purpose.
Kyle Miller (Mar 26 2024 at 21:45):
Maybe in each of those files, incidentally the fvarId is always preserved across all tactics?
Damiano Testa (Mar 26 2024 at 22:01):
I doubt it, since I'm pretty sure that there were rw
s.
Damiano Testa (Mar 26 2024 at 22:03):
Indeed, here is a rw
in the determinant file.
And a rw at
here.
Kyle Miller (Mar 27 2024 at 16:39):
docs#Lean.Elab.Tactic.rewriteLocalDecl uses docs#Lean.MVarId.replaceLocalDecl, which creates a docs#Lean.Meta.AssertAfterResult that contains the fvarsubst, but that's never registered as alias info, and, curiously, that never seems to lead to an accidental "unused variable" linter error.
Kyle Miller (Mar 27 2024 at 16:41):
It does keep "go to definition" from working on the variable afterwards.
But... maybe it's not the "same" variable after a rewrite, so perhaps it makes no sense to register an alias.
Damiano Testa (Mar 27 2024 at 19:12):
Ok, thank you for investigating! For my application, I definitely want to consider the "new" local fvar after a rw at
or simp at
as "the same" as the one before the tactic. Indeed, the idea is precisely to catch uses of a tactic like rw
after a tactic like simp
, but only when acting on "the same" hypothesis. Thus, I want to flag
simp at h
rw [] at h
but not
simp at h
rw [] at h'
(assuming that the arguments to rw
do not involve h
and that h
and h'
are really different!)
Damiano Testa (Mar 27 2024 at 19:16):
Maybe I can simply record the FVarId
s after tactics like simp
and match them to the FVarId
s before tactics like rw
and forget about actually evolving/tracking them. However, I worry that, when the "context MVar
" changes, these FVarId
s are not preserved.
Last updated: May 02 2025 at 03:31 UTC