Skip to content

Commit 18d7eba

Browse files
fix: hovers and docstrings for (co)inductive types
This PR fixes a regression introduced by #10307, where hovering the name of an inductive type or constructor in its own declaration didn't show the docstring. In the process, a bug in docstring handling for coinductive types was discovered and also fixed. Tests are added to prevent the regression from repeating in the future.
1 parent 3931a72 commit 18d7eba

File tree

3 files changed

+145
-3
lines changed

3 files changed

+145
-3
lines changed

src/Lean/Elab/MutualInductive.lean

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,6 @@ Term.withoutSavingRecAppSyntax do
11231123
private def mkInductiveDecl (vars : Array Expr) (elabs : Array InductiveElabStep1) : TermElabM FinalizeContext :=
11241124
withElaboratedHeaders vars elabs fun vars elabs rs scopeLevelNames => do
11251125
let res ← mkInductiveDeclCore addAndFinalizeInductiveDecl vars elabs rs scopeLevelNames
1126-
addTermInfoViews <| elabs.map (·.view)
11271126
return res
11281127

11291128
private def mkAuxConstructions (declNames : Array Name) : TermElabM Unit := do
@@ -1275,9 +1274,11 @@ private def elabInductiveViewsPostprocessing (views : Array InductiveView) (res
12751274
unless (views.any (·.isCoinductive)) do
12761275
Term.applyAttributesAt view.declName view.modifiers.attrs .afterCompilation
12771276

1277+
-- Term info is added here so that docstrings are maximally available in the environment for hovers
1278+
runTermElabM fun _ => Term.withDeclName view0.declName <| withRef ref <| addTermInfoViews views
1279+
12781280
private def elabInductiveViewsPostprocessingCoinductive (views : Array InductiveView)
12791281
: CommandElabM Unit := do
1280-
let views := views.map updateViewRemovingFunctorName
12811282
let view0 := views[0]!
12821283
let ref := view0.ref
12831284

@@ -1299,6 +1300,9 @@ private def elabInductiveViewsPostprocessingCoinductive (views : Array Inductive
12991300
unless (views.any (·.isCoinductive)) do
13001301
Term.applyAttributesAt view.declName view.modifiers.attrs .afterCompilation
13011302

1303+
-- Term info is added here so that docstrings are maximally available in the environment for hovers
1304+
runTermElabM fun _ => Term.withDeclName view0.declName <| withRef ref <| addTermInfoViews views
1305+
13021306
def InductiveViewToCoinductiveElab (e : InductiveElabStep1) : CoinductiveElabData where
13031307
declId := e.view.declId
13041308
declName := e.view.declName
@@ -1321,7 +1325,6 @@ def elabInductives (inductives : Array (Modifiers × Syntax)) : CommandElabM Uni
13211325
elabFlatInductiveViews vars flatElabs
13221326
discard <| flatElabs.mapM fun e => MetaM.run' do mkSumOfProducts e.view.declName
13231327
elabCoinductive (flatElabs.map InductiveViewToCoinductiveElab)
1324-
addTermInfoViews <| elabs.map (·.view)
13251328
elabInductiveViewsPostprocessingCoinductive (elabs.map (·.view))
13261329
else
13271330
let res ← runTermElabM fun vars => do

tests/lean/interactive/hover.lean

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,3 +306,43 @@ since it needs the environment with the generated `_eval.match_1` matcher.
306306
-/
307307
#eval (default : Nat) matches .succ ..
308308
--^ textDocument/hover
309+
310+
/--
311+
These are docs
312+
-/
313+
structure S where
314+
--^ textDocument/hover
315+
/-- So are these -/
316+
mk ::
317+
--^ textDocument/hover
318+
/-- And these -/
319+
x : Nat
320+
--^ textDocument/hover
321+
322+
#check { x := 5 : S }
323+
--^ textDocument/hover
324+
--^ textDocument/hover
325+
326+
/-- Docs -/
327+
inductive S' where
328+
--^ textDocument/hover
329+
/-- More docs -/
330+
| mk (x : Nat)
331+
--^ textDocument/hover
332+
333+
#check (.mk 5 : S')
334+
--^ textDocument/hover
335+
--^ textDocument/hover
336+
337+
/-- An infinite sequence -/
338+
coinductive InfSeq (r : α → α → Prop) : α → Prop where
339+
--^ textDocument/hover
340+
/-- Take a step -/
341+
| step : r a b → InfSeq r b → InfSeq r a
342+
--^ textDocument/hover
343+
344+
#check InfSeq
345+
--^ textDocument/hover
346+
347+
#check InfSeq.step
348+
--^ textDocument/hover

tests/lean/interactive/hover.lean.expected.out

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,3 +657,102 @@
657657
{"start": {"line": 306, "character": 6},
658658
"end": {"line": 306, "character": 38}},
659659
"contents": {"value": "```lean\nBool\n```", "kind": "markdown"}}
660+
{"textDocument": {"uri": "file:///hover.lean"},
661+
"position": {"line": 312, "character": 10}}
662+
{"range":
663+
{"start": {"line": 312, "character": 10},
664+
"end": {"line": 312, "character": 11}},
665+
"contents":
666+
{"value": "```lean\nS : Type\n```\n***\nThese are docs\n", "kind": "markdown"}}
667+
{"textDocument": {"uri": "file:///hover.lean"},
668+
"position": {"line": 315, "character": 2}}
669+
{"range":
670+
{"start": {"line": 315, "character": 2}, "end": {"line": 315, "character": 4}},
671+
"contents":
672+
{"value": "```lean\nS.mk (x : ℕ) : S\n```\n***\nSo are these ",
673+
"kind": "markdown"}}
674+
{"textDocument": {"uri": "file:///hover.lean"},
675+
"position": {"line": 318, "character": 2}}
676+
{"range":
677+
{"start": {"line": 318, "character": 2}, "end": {"line": 318, "character": 3}},
678+
"contents":
679+
{"value": "```lean\nS.x (self : S) : ℕ\n```\n***\nAnd these ",
680+
"kind": "markdown"}}
681+
{"textDocument": {"uri": "file:///hover.lean"},
682+
"position": {"line": 321, "character": 9}}
683+
{"range":
684+
{"start": {"line": 321, "character": 9},
685+
"end": {"line": 321, "character": 10}},
686+
"contents":
687+
{"value": "```lean\nx : ℕ\n```\n***\nAnd these ", "kind": "markdown"}}
688+
{"textDocument": {"uri": "file:///hover.lean"},
689+
"position": {"line": 321, "character": 18}}
690+
{"range":
691+
{"start": {"line": 321, "character": 18},
692+
"end": {"line": 321, "character": 19}},
693+
"contents":
694+
{"value": "```lean\nS : Type\n```\n***\nThese are docs\n", "kind": "markdown"}}
695+
{"textDocument": {"uri": "file:///hover.lean"},
696+
"position": {"line": 326, "character": 10}}
697+
{"range":
698+
{"start": {"line": 326, "character": 10},
699+
"end": {"line": 326, "character": 12}},
700+
"contents":
701+
{"value": "```lean\nS' : Type\n```\n***\nDocs ", "kind": "markdown"}}
702+
{"textDocument": {"uri": "file:///hover.lean"},
703+
"position": {"line": 329, "character": 4}}
704+
{"range":
705+
{"start": {"line": 329, "character": 4}, "end": {"line": 329, "character": 6}},
706+
"contents":
707+
{"value": "```lean\nS'.mk (x : ℕ) : S'\n```\n***\nMore docs ",
708+
"kind": "markdown"}}
709+
{"textDocument": {"uri": "file:///hover.lean"},
710+
"position": {"line": 332, "character": 9}}
711+
{"range":
712+
{"start": {"line": 332, "character": 8},
713+
"end": {"line": 332, "character": 11}},
714+
"contents":
715+
{"value": "```lean\nS'.mk (x : ℕ) : S'\n```\n***\nMore docs ",
716+
"kind": "markdown"}}
717+
{"textDocument": {"uri": "file:///hover.lean"},
718+
"position": {"line": 332, "character": 16}}
719+
{"range":
720+
{"start": {"line": 332, "character": 16},
721+
"end": {"line": 332, "character": 18}},
722+
"contents":
723+
{"value": "```lean\nS' : Type\n```\n***\nDocs ", "kind": "markdown"}}
724+
{"textDocument": {"uri": "file:///hover.lean"},
725+
"position": {"line": 337, "character": 12}}
726+
{"range":
727+
{"start": {"line": 337, "character": 12},
728+
"end": {"line": 337, "character": 18}},
729+
"contents":
730+
{"value":
731+
"```lean\nInfSeq.{u_1} {α : Sort u_1} (r : α → α → Prop) : α → Prop\n```\n***\nAn infinite sequence ",
732+
"kind": "markdown"}}
733+
{"textDocument": {"uri": "file:///hover.lean"},
734+
"position": {"line": 340, "character": 7}}
735+
{"range":
736+
{"start": {"line": 340, "character": 4}, "end": {"line": 340, "character": 8}},
737+
"contents":
738+
{"value":
739+
"```lean\nInfSeq.step.{u_1} {α : Sort u_1} (r : α → α → Prop) {a b : α} : r a b → InfSeq r b → InfSeq r a\n```\n***\nTake a step ",
740+
"kind": "markdown"}}
741+
{"textDocument": {"uri": "file:///hover.lean"},
742+
"position": {"line": 343, "character": 7}}
743+
{"range":
744+
{"start": {"line": 343, "character": 7},
745+
"end": {"line": 343, "character": 13}},
746+
"contents":
747+
{"value":
748+
"```lean\nInfSeq.{u_1} {α : Sort u_1} (r : α → α → Prop) : α → Prop\n```\n***\nAn infinite sequence ",
749+
"kind": "markdown"}}
750+
{"textDocument": {"uri": "file:///hover.lean"},
751+
"position": {"line": 346, "character": 7}}
752+
{"range":
753+
{"start": {"line": 346, "character": 7},
754+
"end": {"line": 346, "character": 18}},
755+
"contents":
756+
{"value":
757+
"```lean\nInfSeq.step.{u_1} {α : Sort u_1} (r : α → α → Prop) {a b : α} : r a b → InfSeq r b → InfSeq r a\n```\n***\nTake a step ",
758+
"kind": "markdown"}}

0 commit comments

Comments
 (0)