lean4-htt/tests/lean/interactive/hover.lean.expected.out
Marc Huisinga 8b8561a699
feat: improved go to definition (#9040)
This PR improves the 'Go to Definition' UX, specifically:
- Using 'Go to Definition' on a type class projection will now extract
the specific instances that were involved and provide them as locations
to jump to. For example, using 'Go to Definition' on the `toString` of
`toString 0` will yield results for `ToString.toString` and `ToString
Nat`.
- Using 'Go to Definition' on a macro that produces syntax with type
class projections will now also extract the specific instances that were
involved and provide them as locations to jump to. For example, using
'Go to Definition' on the `+` of `1 + 1` will yield results for
`HAdd.hAdd`, `HAdd α α α` and `Add Nat`.
- Using 'Go to Declaration' will now provide all the results of 'Go to
Definition' in addition to the elaborator and the parser that were
involved. For example, using 'Go to Declaration' on the `+` of `1 + 1`
will yield results for `HAdd.hAdd`, `HAdd α α α`, `Add Nat`,
``macro_rules | `($x + $y) => ...`` and `infixl:65 " + " => HAdd.hAdd`.
- Using 'Go to Type Definition' on a value with a type that contains
multiple constants will now provide 'Go to Definition' results for each
constant. For example, using 'Go to Type Definition' on `x` for `x :
Array Nat` will yield results for `Array` and `Nat`.

### Details
'Go to Definition' for type class projections was first implemented by
#1767, but there were still a couple of shortcomings with the
implementation. E.g. in order to jump to the instance in `toString 0`,
one had to add another space within the application and then use 'Go to
Definition' on that, or macros would block instances from being
displayed. Then, when the .ilean format was added, most 'Go to
Definition' requests were already handled using the .ileans in the
watchdog process, and so the file worker never received them to handle
them with the semantic information that it has available.

This PR resolves most of the issues with the previous implementation and
refactors the 'Go to Definition' control flow so that 'Go to Definition'
requests are always handled by the file worker, with the watchdog merely
using its .ilean position information to update the positions in the
response to a more up-to-date state. This is necessary because the file
worker obtains its position information from the .oleans, which need to
be rebuilt in order to be up-to-date, while the watchdog always receives
.ilean update notifications from each active file worker with the
current position information in the editor.

Finally, all of the 'Go to Definition' code is refactored to be easier
to maintain.

### Breaking changes
`InfoTree.hoverableInfoAt?` has been generalized to
`InfoTree.hoverableInfoAtM?` and now takes a general `filter` argument
instead of several boolean flags, as was the case before.
2025-07-21 15:47:44 +00:00

653 lines
37 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 3, "character": 8}}
{"range":
{"start": {"line": 3, "character": 8}, "end": {"line": 3, "character": 18}},
"contents":
{"value":
"```lean\nTrue.intro : True\n```\n***\n`True` is true, and `True.intro` (or more commonly, `trivial`)\nis the proof. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 7, "character": 8}}
{"range":
{"start": {"line": 7, "character": 8}, "end": {"line": 7, "character": 18}},
"contents":
{"value":
"```lean\nTrue.intro : True\n```\n***\n`True` is true, and `True.intro` (or more commonly, `trivial`)\nis the proof. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 12, "character": 4}}
{"range":
{"start": {"line": 12, "character": 4}, "end": {"line": 12, "character": 12}},
"contents":
{"value":
"```lean\nNat.zero : Nat\n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 21, "character": 2}}
{"range":
{"start": {"line": 21, "character": 2}, "end": {"line": 21, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 21, "character": 8}}
{"range":
{"start": {"line": 21, "character": 2}, "end": {"line": 21, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 21, "character": 13}}
{"range":
{"start": {"line": 21, "character": 13}, "end": {"line": 21, "character": 23}},
"contents":
{"value":
"```lean\nTrue.intro : True\n```\n***\n`True` is true, and `True.intro` (or more commonly, `trivial`)\nis the proof. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 28, "character": 6}}
{"range":
{"start": {"line": 28, "character": 6}, "end": {"line": 28, "character": 12}},
"contents":
{"value":
"```lean\nLean.Parser.Category.tactic : Lean.Parser.Category\n```\n***\n`tactic` is the builtin syntax category for tactics. These appear after\n`by` in proofs, and they are programs that take in the proof context\n(the hypotheses in scope plus the type of the term to synthesize) and construct\na term of the expected type. For example, `simp` is a tactic, used in:\n```\nexample : 2 + 2 = 4 := by simp\n```\n\n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 28, "character": 32}}
{"range":
{"start": {"line": 28, "character": 32}, "end": {"line": 28, "character": 36}},
"contents":
{"value":
"```lean\nLean.Parser.Category.term : Lean.Parser.Category\n```\n***\n`term` is the builtin syntax category for terms. A term denotes an expression\nin lean's type theory, for example `2 + 2` is a term. The difference between\n`Term` and `Expr` is that the former is a kind of syntax, while the latter is\nthe result of elaboration. For example `by simp` is also a `Term`, but it elaborates\nto different `Expr`s depending on the context. \n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 31, "character": 6}}
{"range":
{"start": {"line": 31, "character": 6}, "end": {"line": 31, "character": 12}},
"contents":
{"value":
"```lean\nLean.Parser.Category.tactic : Lean.Parser.Category\n```\n***\n`tactic` is the builtin syntax category for tactics. These appear after\n`by` in proofs, and they are programs that take in the proof context\n(the hypotheses in scope plus the type of the term to synthesize) and construct\na term of the expected type. For example, `simp` is a tactic, used in:\n```\nexample : 2 + 2 = 4 := by simp\n```\n\n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 31, "character": 24}}
{"range":
{"start": {"line": 31, "character": 23}, "end": {"line": 31, "character": 27}},
"contents":
{"value":
"```lean\nLean.Parser.Category.term : Lean.Parser.Category\n```\n***\n`term` is the builtin syntax category for terms. A term denotes an expression\nin lean's type theory, for example `2 + 2` is a term. The difference between\n`Term` and `Expr` is that the former is a kind of syntax, while the latter is\nthe result of elaboration. For example `by simp` is also a `Term`, but it elaborates\nto different `Expr`s depending on the context. \n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 36, "character": 2}}
{"range":
{"start": {"line": 36, "character": 2}, "end": {"line": 36, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 44, "character": 2}}
{"range":
{"start": {"line": 44, "character": 2}, "end": {"line": 44, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 49, "character": 16}}
{"range":
{"start": {"line": 49, "character": 15}, "end": {"line": 49, "character": 21}},
"contents":
{"value": "```lean\nmyNota : Lean.ParserDescr\n```\n***\nMy notation ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 52, "character": 7}}
{"range":
{"start": {"line": 52, "character": 7}, "end": {"line": 52, "character": 15}},
"contents":
{"value": "```lean\n1 : Nat\n```\n***\nMy notation ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 59, "character": 7}}
{"range":
{"start": {"line": 59, "character": 7}, "end": {"line": 59, "character": 15}},
"contents":
{"value": "```lean\nNat\n```\n***\nMy notation ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 69, "character": 7}}
{"range":
{"start": {"line": 69, "character": 7}, "end": {"line": 69, "character": 16}},
"contents":
{"value": "```lean\nNat\n```\n***\nMy ultimate notation ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 73, "character": 21}}
{"range":
{"start": {"line": 73, "character": 18}, "end": {"line": 73, "character": 25}},
"contents":
{"value": "```lean\nmyInfix : Lean.TrailingParserDescr\n```",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 73, "character": 39}}
{"range":
{"start": {"line": 73, "character": 38}, "end": {"line": 73, "character": 45}},
"contents":
{"value":
"```lean\nNat.add : Nat → Nat → Nat\n```\n***\nAddition of natural numbers, typically used via the `+` operator.\n\nThis function is overridden in both the kernel and the compiler to efficiently evaluate using the\narbitrary-precision arithmetic library. The definition provided here is the logical model.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 77, "character": 10}}
{"range":
{"start": {"line": 77, "character": 7}, "end": {"line": 77, "character": 14}},
"contents":
{"value":
"```lean\nNat\n```\n***\nAddition of natural numbers, typically used via the `+` operator.\n\nThis function is overridden in both the kernel and the compiler to efficiently evaluate using the\narbitrary-precision arithmetic library. The definition provided here is the logical model.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 82, "character": 7}}
{"range":
{"start": {"line": 82, "character": 7}, "end": {"line": 82, "character": 8}},
"contents":
{"value":
"```lean\nNat : Type\n```\n***\nThe natural numbers, starting at zero.\n\nThis type is special-cased by both the kernel and the compiler, and overridden with an efficient\nimplementation. Both use a fast arbitrary-precision arithmetic library (usually\n[GMP](https://gmplib.org/)); at runtime, `Nat` values that are sufficiently small are unboxed.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 87, "character": 14}}
{"range":
{"start": {"line": 87, "character": 14}, "end": {"line": 87, "character": 36}},
"contents":
{"value":
"```lean\nLean.Parser.Term.doSeq : Lean.Parser.Parser\n```\n***\nA `doSeq` is a sequence of `doElem`, the main argument after the `do` keyword and other\ndo elements that take blocks. It can either have the form `\"{\" (doElem \";\"?)* \"}\"` or\n`many1Indent (doElem \";\"?)`, where `many1Indent` ensures that all the items are at\nthe same or higher indentation level as the first line. \n***\n*import Lean.Parser.Do*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 89, "character": 30}}
{"range":
{"start": {"line": 89, "character": 29}, "end": {"line": 89, "character": 34}},
"contents":
{"value":
"```lean\nLean.Parser.Term.doSeq : Lean.Parser.Parser\n```\n***\nA `doSeq` is a sequence of `doElem`, the main argument after the `do` keyword and other\ndo elements that take blocks. It can either have the form `\"{\" (doElem \";\"?)* \"}\"` or\n`many1Indent (doElem \";\"?)`, where `many1Indent` ensures that all the items are at\nthe same or higher indentation level as the first line. \n***\n*import Lean.Parser.Do*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 92, "character": 2}}
{"range":
{"start": {"line": 92, "character": 0}, "end": {"line": 92, "character": 7}},
"contents": {"value": "My command ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 99, "character": 2}}
{"range":
{"start": {"line": 99, "character": 0}, "end": {"line": 99, "character": 7}},
"contents": {"value": "My command ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 102, "character": 16}}
{"range":
{"start": {"line": 102, "character": 16},
"end": {"line": 102, "character": 23}},
"contents":
{"value":
"```lean\nLean.Parser.ppSpace : Lean.Parser.Parser\n```\n***\nNo-op parser that advises the pretty printer to emit a space/soft line break. \n***\n*import Lean.Parser.Extra*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 102, "character": 24}}
{"range":
{"start": {"line": 102, "character": 24},
"end": {"line": 102, "character": 31}},
"contents":
{"value":
"```lean\nLean.ParserDescr.sepBy1 (p : Lean.ParserDescr) (sep : String) (psep : Lean.ParserDescr)\n (allowTrailingSep : Bool := false) : Lean.ParserDescr\n```\n***\n`sepBy1` is just like `sepBy`, except it takes 1 or more instead of\n0 or more occurrences of `p`. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 102, "character": 31}}
{"range":
{"start": {"line": 102, "character": 31},
"end": {"line": 102, "character": 35}},
"contents":
{"value":
"```lean\nLean.Parser.Category.term : Lean.Parser.Category\n```\n***\n`term` is the builtin syntax category for terms. A term denotes an expression\nin lean's type theory, for example `2 + 2` is a term. The difference between\n`Term` and `Expr` is that the former is a kind of syntax, while the latter is\nthe result of elaboration. For example `by simp` is also a `Term`, but it elaborates\nto different `Expr`s depending on the context. \n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 111, "character": 2}}
{"range":
{"start": {"line": 111, "character": 0}, "end": {"line": 111, "character": 8}},
"contents": {"value": "My ultimate command ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 115, "character": 10}}
{"range":
{"start": {"line": 115, "character": 8},
"end": {"line": 115, "character": 14}},
"contents":
{"value":
"Structure instance. `{ x := e, ... }` assigns `e` to field `x`, which may be\ninherited. If `e` is itself a variable called `x`, it can be elided:\n`fun y => { x := 1, y }`.\nA *structure update* of an existing value can be given via `with`:\n`{ point with x := 1 }`.\nThe structure type can be specified if not inferable:\n`{ x := 1, y := 2 : Point }`.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 119, "character": 8}}
{"range":
{"start": {"line": 119, "character": 8},
"end": {"line": 119, "character": 10}},
"contents":
{"value":
"```lean\nid.{u} {α : Sort u} (a : α) : α\n```\n***\nThe identity function. `id` takes an implicit argument `α : Sort u`\n(a type in any universe), and an argument `a : α`, and returns `a`.\n\nAlthough this may look like a useless function, one application of the identity\nfunction is to explicitly put a type on an expression. If `e` has type `T`,\nand `T'` is definitionally equal to `T`, then `@id T' e` typechecks, and Lean\nknows that this expression has type `T'` rather than `T`. This can make a\ndifference for typeclass inference, since `T` and `T'` may have different\ntypeclass instances on them. `show T' from e` is sugar for an `@id T' e`\nexpression.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 119, "character": 10}}
{"range":
{"start": {"line": 119, "character": 8},
"end": {"line": 119, "character": 21}},
"contents": {"value": "```lean\nTrue\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 126, "character": 2}}
{"range":
{"start": {"line": 126, "character": 2}, "end": {"line": 126, "character": 3}},
"contents": {"value": "```lean\nn : Id \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 133, "character": 9}}
{"range":
{"start": {"line": 133, "character": 7},
"end": {"line": 133, "character": 17}},
"contents": {"value": "```lean\nfoo : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 138, "character": 7}}
{"range":
{"start": {"line": 138, "character": 7},
"end": {"line": 138, "character": 10}},
"contents": {"value": "```lean\nBar.foo : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 141, "character": 9}}
{"range":
{"start": {"line": 141, "character": 7},
"end": {"line": 141, "character": 17}},
"contents": {"value": "```lean\n_root_.foo : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 144, "character": 4}}
{"range":
{"start": {"line": 144, "character": 4}, "end": {"line": 144, "character": 7}},
"contents": {"value": "```lean\nBar.bar : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 147, "character": 10}}
{"range":
{"start": {"line": 147, "character": 10},
"end": {"line": 147, "character": 13}},
"contents": {"value": "```lean\nBar.Foo : Type\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 147, "character": 17}}
{"range":
{"start": {"line": 147, "character": 17},
"end": {"line": 147, "character": 19}},
"contents":
{"value": "```lean\nBar.Foo.mk (hi : ) : Foo\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 150, "character": 2}}
{"range":
{"start": {"line": 150, "character": 2}, "end": {"line": 150, "character": 4}},
"contents":
{"value": "```lean\nBar.Foo.hi (self : Foo) : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 153, "character": 10}}
{"range":
{"start": {"line": 153, "character": 10},
"end": {"line": 153, "character": 13}},
"contents": {"value": "```lean\nBar.Bar : Type\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 155, "character": 4}}
{"range":
{"start": {"line": 155, "character": 4}, "end": {"line": 155, "character": 6}},
"contents": {"value": "```lean\nBar.Bar.mk : Bar\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 158, "character": 2}}
{"range":
{"start": {"line": 158, "character": 0}, "end": {"line": 158, "character": 8}},
"contents":
{"value":
"```lean\nBar.«instToStringNat_external:file:///hover.lean» : ToString \n```",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 160, "character": 9}}
{"range":
{"start": {"line": 160, "character": 9},
"end": {"line": 160, "character": 10}},
"contents": {"value": "```lean\nBar.f : ToString \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 163, "character": 10}}
{"range":
{"start": {"line": 163, "character": 10},
"end": {"line": 163, "character": 16}},
"contents":
{"value": "A type universe. `Type ≡ Type 0`, `Type u ≡ Sort (u + 1)`. ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 166, "character": 4}}
{"range":
{"start": {"line": 166, "character": 4},
"end": {"line": 166, "character": 11}},
"contents": {"value": "```lean\nBar.foo.bar : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 166, "character": 8}}
{"range":
{"start": {"line": 166, "character": 4},
"end": {"line": 166, "character": 11}},
"contents": {"value": "```lean\nBar.foo.bar : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 173, "character": 6}}
{"range":
{"start": {"line": 173, "character": 6}, "end": {"line": 173, "character": 7}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 176, "character": 4}}
[{"targetUri": "file:///hover.lean",
"targetSelectionRange":
{"start": {"line": 173, "character": 6},
"end": {"line": 173, "character": 7}},
"targetRange":
{"start": {"line": 173, "character": 6},
"end": {"line": 173, "character": 7}},
"originSelectionRange":
{"start": {"line": 176, "character": 4},
"end": {"line": 176, "character": 5}}}]
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 176, "character": 4}}
{"range":
{"start": {"line": 176, "character": 4}, "end": {"line": 176, "character": 5}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 180, "character": 12}}
{"range":
{"start": {"line": 180, "character": 11},
"end": {"line": 180, "character": 33}},
"contents":
{"value": "Enables or disables all unused variable linter warnings ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 183, "character": 8}}
{"range":
{"start": {"line": 183, "character": 8}, "end": {"line": 183, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 186, "character": 8}}
[{"targetUri": "file:///hover.lean",
"targetSelectionRange":
{"start": {"line": 183, "character": 8},
"end": {"line": 183, "character": 9}},
"targetRange":
{"start": {"line": 183, "character": 8},
"end": {"line": 183, "character": 9}},
"originSelectionRange":
{"start": {"line": 186, "character": 8},
"end": {"line": 186, "character": 9}}}]
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 186, "character": 8}}
{"range":
{"start": {"line": 186, "character": 8}, "end": {"line": 186, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 191, "character": 25}}
{"range":
{"start": {"line": 191, "character": 25},
"end": {"line": 191, "character": 26}},
"contents": {"value": "```lean\nn : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 194, "character": 2}}
{"range":
{"start": {"line": 194, "character": 2}, "end": {"line": 194, "character": 8}},
"contents":
{"value":
"Changes the inlining behavior. This attribute comes in several variants:\n- `@[inline]`: marks the definition to be inlined when it is appropriate.\n- `@[inline_if_reduce]`: marks the definition to be inlined if an application of it after inlining\n and applying reduction isn't a `match` expression. This attribute can be used for inlining\n structurally recursive functions.\n- `@[noinline]`: marks the definition to never be inlined.\n- `@[always_inline]`: marks the definition to always be inlined.\n- `@[macro_inline]`: marks the definition to always be inlined at the beginning of compilation.\n This makes it possible to define functions that evaluate some of their parameters lazily.\n Example:\n ```\n @[macro_inline]\n def test (x y : Nat) : Nat :=\n if x = 42 then x else y\n\n #eval test 42 (2^1000000000000) -- doesn't compute 2^1000000000000\n ```\n Only non-recursive functions may be marked `@[macro_inline]`.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 200, "character": 2}}
{"range":
{"start": {"line": 200, "character": 2},
"end": {"line": 200, "character": 15}},
"contents":
{"value":
"`· tac` focuses on the main goal and tries to solve it using `tac`, or else fails. ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 203, "character": 28}}
{"range":
{"start": {"line": 203, "character": 27},
"end": {"line": 203, "character": 32}},
"contents":
{"value":
"```lean\nId \n```\n***\nParentheses, used for grouping expressions (e.g., `a * (b + c)`).\nCan also be used for creating simple functions when combined with `·`. Here are some examples:\n - `(· + 1)` is shorthand for `fun x => x + 1`\n - `(· + ·)` is shorthand for `fun x y => x + y`\n - `(f · a b)` is shorthand for `fun x => f x a b`\n - `(h (· + 1) ·)` is shorthand for `fun x => h (fun y => y + 1) x`\n - also applies to other parentheses-like notations such as `(·, 1)`\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 206, "character": 8}}
{"range":
{"start": {"line": 206, "character": 8}, "end": {"line": 206, "character": 9}},
"contents": {"value": "```lean\n?m\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 206, "character": 10}}
{"range":
{"start": {"line": 206, "character": 8},
"end": {"line": 206, "character": 13}},
"contents":
{"value":
"```lean\n?m x1✝ x2✝\n```\n***\n`a + b` computes the sum of `a` and `b`.\nThe meaning of this notation is type-dependent. \n\nConventions for notations in identifiers:\n\n * The recommended spelling of `+` in identifiers is `add`.",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 215, "character": 28}}
{"range":
{"start": {"line": 215, "character": 28},
"end": {"line": 215, "character": 29}},
"contents": {"value": "```lean\nx : α\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 217, "character": 28}}
{"range":
{"start": {"line": 217, "character": 28},
"end": {"line": 217, "character": 29}},
"contents": {"value": "```lean\nα\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 219, "character": 31}}
{"range":
{"start": {"line": 219, "character": 31},
"end": {"line": 219, "character": 32}},
"contents": {"value": "```lean\nx : α\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 222, "character": 22}}
{"range":
{"start": {"line": 222, "character": 22},
"end": {"line": 222, "character": 32}},
"contents": {"value": "my_intro tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 222, "character": 31}}
{"range":
{"start": {"line": 222, "character": 31},
"end": {"line": 222, "character": 32}},
"contents": {"value": "```lean\nα\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 229, "character": 22}}
{"range":
{"start": {"line": 229, "character": 22},
"end": {"line": 229, "character": 32}},
"contents": {"value": "my_intro tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 231, "character": 17}}
{"range":
{"start": {"line": 231, "character": 17},
"end": {"line": 231, "character": 25}},
"contents":
{"value": "```lean\nmy_intro : \n```\n***\nmy_intro term ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 235, "character": 8}}
{"range":
{"start": {"line": 235, "character": 8}, "end": {"line": 235, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 238, "character": 4}}
{"range":
{"start": {"line": 238, "character": 2}, "end": {"line": 238, "character": 8}},
"contents":
{"value":
"The left hand side of an induction arm, `| foo a b c` or `| @foo a b c`\nwhere `foo` is a constructor of the inductive type and `a b c` are the arguments\nto the constructor.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 241, "character": 4}}
{"range":
{"start": {"line": 241, "character": 2},
"end": {"line": 241, "character": 10}},
"contents":
{"value":
"The left hand side of an induction arm, `| foo a b c` or `| @foo a b c`\nwhere `foo` is a constructor of the inductive type and `a b c` are the arguments\nto the constructor.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 241, "character": 9}}
{"range":
{"start": {"line": 241, "character": 9},
"end": {"line": 241, "character": 10}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 245, "character": 8}}
{"range":
{"start": {"line": 245, "character": 8}, "end": {"line": 245, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 247, "character": 12}}
{"range":
{"start": {"line": 247, "character": 12},
"end": {"line": 247, "character": 13}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 249, "character": 4}}
{"range":
{"start": {"line": 249, "character": 2}, "end": {"line": 249, "character": 8}},
"contents":
{"value":
"The left hand side of an induction arm, `| foo a b c` or `| @foo a b c`\nwhere `foo` is a constructor of the inductive type and `a b c` are the arguments\nto the constructor.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 252, "character": 9}}
{"range":
{"start": {"line": 252, "character": 9},
"end": {"line": 252, "character": 10}},
"contents":
{"value":
"```lean\n\n```\n***\nA *hole* (or *placeholder term*), which stands for an unknown term that is expected to be inferred based on context.\nFor example, in `@id _ Nat.zero`, the `_` must be the type of `Nat.zero`, which is `Nat`.\n\nThe way this works is that holes create fresh metavariables.\nThe elaborator is allowed to assign terms to metavariables while it is checking definitional equalities.\nThis is often known as *unification*.\n\nNormally, all holes must be solved for. However, there are a few contexts where this is not necessary:\n* In `match` patterns, holes are catch-all patterns.\n* In some tactics, such as `refine'` and `apply`, unsolved-for placeholders become new goals.\n\nRelated concept: implicit parameters are automatically filled in with holes during the elaboration process.\n\nSee also `?m` syntax (synthetic holes).\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 252, "character": 11}}
{"range":
{"start": {"line": 252, "character": 11},
"end": {"line": 252, "character": 13}},
"contents": {"value": "```lean\nih : True\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 257, "character": 6}}
{"range":
{"start": {"line": 257, "character": 4}, "end": {"line": 257, "character": 9}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 257, "character": 15}}
{"range":
{"start": {"line": 257, "character": 13},
"end": {"line": 257, "character": 18}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 260, "character": 6}}
{"range":
{"start": {"line": 260, "character": 4}, "end": {"line": 260, "character": 9}},
"contents":
{"value":
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 260, "character": 17}}
{"range":
{"start": {"line": 260, "character": 15},
"end": {"line": 260, "character": 20}},
"contents":
{"value":
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 263, "character": 27}}
{"range":
{"start": {"line": 263, "character": 27},
"end": {"line": 263, "character": 37}},
"contents":
{"value":
"```lean\nInhabited.mk.{u} {α : Sort u} (default : α) : Inhabited α\n```\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 263, "character": 28}}
{"range":
{"start": {"line": 263, "character": 28},
"end": {"line": 263, "character": 36}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 269, "character": 2}}
{"range":
{"start": {"line": 269, "character": 2}, "end": {"line": 269, "character": 3}},
"contents":
{"value":
"```lean\n\n```\n***\nA *hole* (or *placeholder term*), which stands for an unknown term that is expected to be inferred based on context.\nFor example, in `@id _ Nat.zero`, the `_` must be the type of `Nat.zero`, which is `Nat`.\n\nThe way this works is that holes create fresh metavariables.\nThe elaborator is allowed to assign terms to metavariables while it is checking definitional equalities.\nThis is often known as *unification*.\n\nNormally, all holes must be solved for. However, there are a few contexts where this is not necessary:\n* In `match` patterns, holes are catch-all patterns.\n* In some tactics, such as `refine'` and `apply`, unsolved-for placeholders become new goals.\n\nRelated concept: implicit parameters are automatically filled in with holes during the elaboration process.\n\nSee also `?m` syntax (synthetic holes).\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 272, "character": 4}}
{"range":
{"start": {"line": 272, "character": 4}, "end": {"line": 272, "character": 8}},
"contents":
{"value": "```lean\nauto (o : := by exact 1) : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 277, "character": 22}}
{"range":
{"start": {"line": 277, "character": 22},
"end": {"line": 277, "character": 23}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 277, "character": 13}}
{"range":
{"start": {"line": 277, "character": 13},
"end": {"line": 277, "character": 15}},
"contents": {"value": "```lean\n_e : 1 = x\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 282, "character": 8}}
{"range":
{"start": {"line": 282, "character": 8},
"end": {"line": 282, "character": 10}},
"contents": {"value": "```lean\n_e : 1 = 0\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 285, "character": 9}}
{"range":
{"start": {"line": 285, "character": 9},
"end": {"line": 285, "character": 10}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 290, "character": 13}}
{"range":
{"start": {"line": 290, "character": 13},
"end": {"line": 290, "character": 16}},
"contents":
{"value":
"```lean\nList.nil.{u} {α : Type u} : List α\n```\n***\nThe empty list, usually written `[]`. \n\nConventions for notations in identifiers:\n\n * The recommended spelling of `[]` in identifiers is `nil`.\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 292, "character": 13}}
{"range":
{"start": {"line": 292, "character": 11},
"end": {"line": 292, "character": 15}},
"contents":
{"value":
"```lean\nList.cons.{u} {α : Type u} (head : α) (tail : List α) : List α\n```\n***\nThe list whose first element is `head`, where `tail` is the rest of the list.\nUsually written `head :: tail`.\n\n\nConventions for notations in identifiers:\n\n * The recommended spelling of `::` in identifiers is `cons`.\n\n * The recommended spelling of `[a]` in identifiers is `singleton`.\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 294, "character": 18}}
{"range":
{"start": {"line": 294, "character": 17},
"end": {"line": 294, "character": 20}},
"contents":
{"value":
"```lean\nList.map.{u, v} {α : Type u} {β : Type v} (f : α → β) (l : List α) : List β\n```\n***\nApplies a function to each element of the list, returning the resulting list of values.\n\n`O(|l|)`.\n\nExamples:\n* `[a, b, c].map f = [f a, f b, f c]`\n* `[].map Nat.succ = []`\n* `[\"one\", \"two\", \"three\"].map (·.length) = [3, 3, 5]`\n* `[\"one\", \"two\", \"three\"].map (·.reverse) = [\"eno\", \"owt\", \"eerht\"]`\n\n***\n*import Init.Data.List.Basic*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 297, "character": 26}}
{"range":
{"start": {"line": 297, "character": 25},
"end": {"line": 297, "character": 29}},
"contents":
{"value":
"```lean\nList.zip.{u, v} {α : Type u} {β : Type v} : List α → List β → List (α × β)\n```\n***\nCombines two lists into a list of pairs in which the first and second components are the\ncorresponding elements of each list. The resulting list is the length of the shorter of the input\nlists.\n\n`O(min |xs| |ys|)`.\n\nExamples:\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2, 3] = [(\"Mon\", 1), (\"Tue\", 2), (\"Wed\", 3)]`\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2] = [(\"Mon\", 1), (\"Tue\", 2)]`\n* `[x₁, x₂, x₃].zip [y₁, y₂, y₃, y₄] = [(x₁, y₁), (x₂, y₂), (x₃, y₃)]`\n\n***\n*import Init.Data.List.Basic*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 297, "character": 19}}
{"range":
{"start": {"line": 297, "character": 19},
"end": {"line": 297, "character": 22}},
"contents":
{"value":
"```lean\nList.zip.{u, v} {α : Type u} {β : Type v} : List α → List β → List (α × β)\n```\n***\nCombines two lists into a list of pairs in which the first and second components are the\ncorresponding elements of each list. The resulting list is the length of the shorter of the input\nlists.\n\n`O(min |xs| |ys|)`.\n\nExamples:\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2, 3] = [(\"Mon\", 1), (\"Tue\", 2), (\"Wed\", 3)]`\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2] = [(\"Mon\", 1), (\"Tue\", 2)]`\n* `[x₁, x₂, x₃].zip [y₁, y₂, y₃, y₄] = [(x₁, y₁), (x₂, y₂), (x₃, y₃)]`\n\n***\n*import Init.Data.List.Basic*",
"kind": "markdown"}}