Zulip Chat Archive
Stream: lean4
Topic: Goto definition + have with pattern
Julian Berman (Feb 24 2024 at 20:29):
Is it a known issue that if you use goto definition on Nat
in:
example : 2 = 2 := by
have x : ∃ n : Nat, 1 = 1 := by sorry
rfl
you get to Nat
, but if you use it in the presence of a pattern:
example : 2 = 2 := by
have ⟨x, y⟩ : ∃ n : Nat, 1 = 1 := by sorry
rfl
you go to haveDecl
?
Kyle Miller (Feb 24 2024 at 21:07):
This is an issue with the let
tactic too, and it seems to be rooted in an issue with the let
term. If you hover over any part of the type after the :
it highlights the whole letDecl
example : 2 = 2 :=
let ⟨x, y⟩ : ∃ n : Nat, 1 = 1 := (by sorry)
rfl
Kyle Miller (Feb 24 2024 at 21:09):
That issue seems to be rooted in turn in how match
handles type ascriptions. Hovering over the type highlights the whole type ascription.
example : 2 = 2 :=
match ((by sorry) : ∃ n : Nat, 1 = 1) with
| ⟨x, y⟩ => rfl
Kyle Miller (Feb 24 2024 at 21:38):
And it looks like it comes down to how type ascriptions themselves elaborate when the value is a tactic. Hovering over Nat
gives information about the type ascription.
#check (by sorry : Nat)
Kyle Miller (Feb 24 2024 at 21:48):
Going back up to the original have
notation, avoiding a tactic makes hovering over Nat
highlight just Nat
.
example : 2 = 2 := by
have ⟨x, y⟩ : ∃ n : Nat, 1 = 1 := sorry
rfl
Julian Berman (Feb 24 2024 at 22:13):
Thanks for the digging! You'd agree these are bugs I assume?
Julian Berman (Feb 24 2024 at 22:14):
It seems strange to me to even ever jump to / hover a tactic definition unless you specifically hover on the tactic name, but I'm not sure whether that's relevant / a good mental model in general for any possible tactic.
Kyle Miller (Feb 24 2024 at 22:17):
Somehow the type in (by sorry : ∃ n : Nat, 1 = 1)
is losing some TermInfo, and as a fallback it's looking outward to anything that annotates how the term was elaborated. Here, it's the type ascription, and in your have
tactic, it's the haveDecl
syntax, which itself looks out to the have
when doing "go to definition".
Kyle Miller (Feb 24 2024 at 22:19):
There's a whole tree of nested info, and it walks up the tree as a fallback. The whole tactic range itself is annotated with the tactic itself. (For example, if you "go to definition" on the =>
in a tactic, it's associated to the tactic itself. That's a counterexample to "only the tactic name itself refers to the tactic.")
Julian Berman (Feb 24 2024 at 22:20):
Yeah I figured something like that was going on (and I realize I'm just randomly talking) but to me it's odd even if pieces of syntax within a tactic end up jumping to the tactic
Kyle Miller (Feb 24 2024 at 22:21):
At least it unifies things, because there are also tactics like <;>
that have no head keyword
Julian Berman (Feb 24 2024 at 22:22):
True.
Kyle Miller (Feb 24 2024 at 22:39):
Weird, I don't see anything about the ascription in the info tree when there's a tactic. When it's just (1 : Nat)
, there's elabTypeAscription
.
set_option trace.Elab.info true
example := ((by exact 1) : Nat)
/-
• command @ ⟨55, 0⟩-⟨55, 31⟩ @ Lean.Elab.Command.elabDeclaration
• ℕ : Type @ ⟨55, 8⟩†-⟨55, 31⟩† @ Lean.Elab.Term.elabHole
• _example (isBinder := true) : ℕ @ ⟨55, 0⟩†-⟨55, 31⟩†
• Tactic @ ⟨55, 13⟩-⟨55, 23⟩
(Term.byTactic "by" (Tactic.tacticSeq (Tactic.tacticSeq1Indented [(Tactic.exact "exact" (num "1"))])))
before
⊢ ℕ
after no goals
• Tactic @ ⟨55, 13⟩-⟨55, 15⟩
"by"
before
⊢ ℕ
after no goals
• Tactic @ ⟨55, 16⟩-⟨55, 23⟩ @ Lean.Elab.Tactic.evalTacticSeq
(Tactic.tacticSeq (Tactic.tacticSeq1Indented [(Tactic.exact "exact" (num "1"))]))
before
⊢ ℕ
after no goals
• Tactic @ ⟨55, 16⟩-⟨55, 23⟩ @ Lean.Elab.Tactic.evalTacticSeq1Indented
(Tactic.tacticSeq1Indented [(Tactic.exact "exact" (num "1"))])
before
⊢ ℕ
after no goals
• Tactic @ ⟨55, 16⟩-⟨55, 23⟩ @ Lean.Elab.Tactic.evalExact
(Tactic.exact "exact" (num "1"))
before
⊢ ℕ
after no goals
• 1 : ℕ @ ⟨55, 22⟩-⟨55, 23⟩ @ Lean.Elab.Term.elabNumLit
• _example (isBinder := true) : ℕ @ ⟨55, 0⟩-⟨55, 7⟩
-/
example := (1 : Nat)
/-
• command @ ⟨88, 0⟩-⟨88, 31⟩ @ Lean.Elab.Command.elabDeclaration
• ℕ : Type @ ⟨88, 8⟩†-⟨88, 31⟩† @ Lean.Elab.Term.elabHole
• _example (isBinder := true) : ℕ @ ⟨88, 0⟩†-⟨88, 31⟩†
• 1 : ℕ @ ⟨88, 11⟩-⟨88, 31⟩ @ Lean.Elab.Term.elabTypeAscription
• ℕ : Type @ ⟨88, 27⟩-⟨88, 30⟩ @ Lean.Elab.Term.elabIdent
• [.] Nat : some Sort.{?_uniq.17909} @ ⟨88, 27⟩-⟨88, 30⟩
• ℕ : Type @ ⟨88, 27⟩-⟨88, 30⟩
• 1 : ℕ @ ⟨88, 12⟩-⟨88, 13⟩ @ Lean.Elab.Term.elabNumLit
• _example (isBinder := true) : ℕ @ ⟨88, 0⟩-⟨88, 7⟩
-/
Julian Berman (Feb 24 2024 at 22:58):
(I am modifying my dreamed up rule to be "hover and go to definition should work only on the first contiguous set of characters part of a tactic" :P) -- or even better, use textDocument/implementation
for jumping to tactic definitions themselves, though probably it bears checking how other language servers use textDocument/definition vs textDocument/implementation vs textDocument/declaration.
Julian Berman (Feb 24 2024 at 23:00):
Less idly I'm trying to understand what those mean. I assume you basically knew that that output somehow corresponds to how Lean is calculating what range to return for the hover?
Julian Berman (Feb 24 2024 at 23:01):
Oh OK I see, that's literally embedding those ranges in the text there, got it.
Last updated: May 02 2025 at 03:31 UTC