Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: locating tactics and corresponding elaboration
Chris Henson (Jun 28 2025 at 16:49):
I have two questions:
1) What is the recommended method of locating a tactic?
2) What is the recommended method of then locating the elaborator for that tactic?
For the first, I will somtimes do something like
#check `(by decide)
which for example would point me to docs#Lean.Parser.Tactic.decide.
Continuing with the example, how would I then in turn find docs#Lean.Elab.Tactic.evalDecide, which is in a different file? Ideally the solution would be generally applicable, but maybe this is an unusal example because it is a builtin tactic?
Robin Arnez (Jun 28 2025 at 17:49):
import Lean
example := by decide
and then ctrl+click on decide
Chris Henson (Jun 28 2025 at 18:50):
I am not getting a go to definition link to click on decide (and am also interested in what this looks like programmatically)
Kevin Buzzard (Jun 28 2025 at 19:08):
So just to clarify, if you copy the code Robin posted into VS Code, ignore the error, and ctrl+click on the word decide (or cmd+click on a mac) you don't jump to the definition of Lean.Elab.Tactic.evalDecide in core Lean?
Chris Henson (Jun 28 2025 at 19:25):
To clarify: if I include import Lean it does work, but not otherwise. Is this the expected behavior?
Kyle Miller (Jun 28 2025 at 19:26):
Yes, that's expected.
Kyle Miller (Jun 28 2025 at 19:27):
(Not ideal, but it's expected)
Kyle Miller (Jun 28 2025 at 19:28):
Both "go to definition" and "go to declaration" are useful for seeing the elaborator and the syntax definition.
Kyle Miller (Jun 28 2025 at 19:30):
I don't believe there's any resource for the programmatic solution except to read through source code for the LSP server. I think docs#Lean.Server.FileWorker.locationLinksOfInfo is the entry point for all the go-to-* logic.
Chris Henson (Jun 28 2025 at 19:34):
Thanks, that link is what I was about to ask for next! Is the reason that this doesn't work for decide until we import Lean because these definitions are in Init?
Kyle Miller (Jun 28 2025 at 19:37):
I think it's specifically because source position information hasn't been loaded in, and the source position is not a "builtin" (data that is in the Lean executable itself), instead it's just in the olean files and needs to be loaded. I'm not completely sure, I'd have to read through the source code.
Most projects will have enough of Lean imported for this data to be loaded.
Kyle Miller (Jun 28 2025 at 19:42):
Oh, it does work for decide. If you do "go to declaration" it goes to the syntax definition.
Kyle Miller (Jun 28 2025 at 19:43):
The issue you ran into is that "go to definition" goes to the elaborator that was invoked on the given syntax, but none of the Lean elaborator is in Init, so it hasn't been loaded, so there's no source position available for Lean.Elab.Tactic.evalDecide.
Kyle Miller (Jun 28 2025 at 19:46):
"The elaborator that was invoked" is important here: there's no direct mapping from syntax to an elaborator, and it's only resolved during tactic execution. There can be macros and multiple elaborators defined for a syntax, so you can't really know ahead of time what it will be. At least you can get the list of elaborators that it will try (maybe take a look at docs#Lean.Elab.Tactic.evalTactic to see how tactic evaluation works; there's some complexity in there you'll want to skip that's for incremental elaboration).
The reason "go to definition" works is that the LSP looks at data registered by withTacticInfoContext to determine which elaborator was executed for a given source syntax.
Last updated: Dec 20 2025 at 21:32 UTC