Zulip Chat Archive
Stream: lean4
Topic: incorrect hover for match in do-block
Jovan Gerbscheid (Jan 28 2025 at 17:41):
In this code:
def foo (y : Option Nat) : Option String := do
let _ ← match y with
| some n => some n
| none => none
return s! "oops"
If I hover over match
, with
or either of the |
, there is a subtle highlight on the match block (which has type Option Nat), but the hover information tells me that the type is Option String
(which is the type of the whole do-block). So there is a mismatch between what expression it seems like I'm hovering over, and what expression I'm getting the type of.
Replacing the match
with an if
-let
fixes the problem (in the less preferred way), because there the hover highlight encompasses the whole do-block.
Aaron Liu (Jan 28 2025 at 18:11):
If you #print foo
, you'll see that the match
block got cps'd, and the corresponding match in the definition does have type Option String
. This is probably why the hover also thinks the match
block has type Option String
. If you hover over the identifier being bound, the hover correctly displays Nat
as the type.
I don't know how to fix this.
Kyle Miller (Jan 28 2025 at 18:16):
@Aaron Liu Hovers are generated during the elaboration process (surface syntax is associated to TermInfo data). The hover for match
should be generated before any of the further transforms before the do
notation.
Kyle Miller (Jan 28 2025 at 18:17):
There's some conceptual connection between them, but there does not have to be a direct correspondence between expressions you see in hovers and what appears in #print
.
Kyle Miller (Jan 28 2025 at 18:34):
Reading docs#Lean.Elab.Term.Do.ToCodeBlock.doLetArrowToCode, it looks like the return type of the match
really is Option String
because match
is a valid do element, and the code is transformed (I think) to something like
def foo (y : Option Nat) : Option String := do
match y with
| some n =>
let _ ← some n
return s! "oops"
| none =>
let _ ← none
return s! "oops"
So the cps-like transformation happens sort of at macro expansion time for do
notation.
If you wrap the match
in parentheses, like
def foo (y : Option Nat) : Option String := do
let _ ← (match y with
| some n => some n
| none => none)
return s! "oops"
that prevents the match
from being recognized as a do element, and so it elaborates as a plain term. That causes it to have an Option Nat
hover.
Kyle Miller (Jan 28 2025 at 18:51):
One fix could be to have doLetArowToCode mark the match
as being synthetic syntax, which would prevent incorrect hover.
Last updated: May 02 2025 at 03:31 UTC