lsp: document every built-in member, complexity included - #43
Merged
Conversation
Big-O was written down in DESIGN prose and in comments beside the schemes, which is nowhere a user can see it. Hover showed a built-in member's type and effect and no prose at all, since doc comments only ever came from a user's own declarations, and completion items carried a label and nothing else — not even the signature. `types::MEMBER_DOCS` gives all 151 built-in members a one-line description, keyed by the name a user writes. The language server appends it to hover below the type, exactly where a `##` doc already goes, and attaches it to completion items along with the rendered signature as `detail`. A user's own declaration wins over a built-in of the same name. Complexity is stated wherever it is not obvious or not what a reader would assume, which is the point: a `List` backed by a Python list makes cost easy to misjudge. `List.contains` is a linear scan where `Set.contains` is O(1); `updateAt`, `insertAt` and `removeAt` copy; `distinct` hashes; `Map.add` copies, though a fold that builds a map lowers to an in-place loop. Signatures render once on first use, by seeding a fresh environment and showing each scheme, so they cannot drift from the schemes themselves. Constraints are not spelled in the signature; where `comparison` or `num` matters the member's doc line says so. Three tests pin the table to the prelude constants: every member is documented, every entry names a real member, and every member has a signature. So the four remaining sweep PRs cannot add an undocumented member — the enforcement lands before the members do.
This was referenced Jul 31, 2026
Merged
simontreanor
added a commit
that referenced
this pull request
Jul 31, 2026
Two dogfooding reports from real programs, and the standard-library sweep they triggered. Language: * a `type` declaration can name an imported type, bare or module-qualified (#36) — the one gap that changed a program's architecture rather than its phrasing, forcing two modules into one file * field access resolves from the base's type when it is known, so two records may share a field name without prefixes (#37) * parameters destructure: tuples (#38), records (#40), and `_` * a direct self tail call lowers to a loop, so an interactive turn loop no longer walks the stack (#39, #41) Standard library — about 115 new members, taking every module to the F# core set: List (#42), Seq (#44), Set and Map (#46), String (#47), Option and Result (#48), then a member-by-member FSharp.Core audit (#51). Every built-in member now carries a one-line description and its complexity in hover and completion (#43, #49), enforced by tests. Fixes: * `pyfun run` on a single file gives the program its own stdin, so an interactive program is runnable by the command whose job is running programs (#35) * a partially applied lambda closes over its argument instead of being wrapped, so `List.map ((+) 2)` emits `lambda b: 2 + b` (#52) * every multi-argument callback's scheme put the effect variable on the wrong arrows, so `List.fold` could never accept an effectful folder (#51) * `Seq.empty` lowered to a bare `iter()`, a TypeError (#51) One source-incompatible change, which is why this is 0.4.0 and not 0.3.1: a dotted `extern` target whose module prefix cannot be decided from the text is now a compile error naming the `extern import` to add (#50). `sys.stdout.flush` used to emit `import sys.stdout` and fail at runtime; declaring `extern import sys` fixes it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #42, and groundwork for the four remaining sweep PRs.
Big-O was written down in DESIGN prose and in comments beside the schemes, which is nowhere a user can see it. Hover on a built-in showed its type and effect and no prose at all, since doc comments only ever came from a user's own declarations. Completion items carried a label and nothing else — not even the signature.
types::MEMBER_DOCSnow gives all 151 built-in members a one-line description, keyed by the name a user writes. The server appends it to hover below the type, exactly where a##doc already goes, and attaches it to completion items along with the rendered signature asdetail.Complexity is stated wherever it is not obvious or not what a reader would assume, which is the whole point: a
Listbacked by a Python list makes cost easy to misjudge.containsis a linear scan whereSet.containsis O(1);updateAt/insertAt/removeAtcopy;distincthashes;Map.addcopies, though a fold that builds a map lowers to an in-place loop.A user's own declaration wins over a built-in of the same name — there is a test where a user function called
maxdoes not inherit the prelude's documentation.Signatures cannot drift: they are rendered once on first use by seeding a fresh environment and showing each scheme, rather than being written out by hand a second time. Constraints are not spelled in the signature; where
comparisonornummatters, the member's doc line says so.Three tests pin the table to the prelude constants — every member is documented, every entry names a real member, every member has a signature. That is the part that pays off later: the four remaining sweep PRs (
Seq,Map/Set,String,Option/Result, ~60 members) cannot add an undocumented member, so the enforcement is in place before the members arrive rather than leaving them to backfill.Plus four LSP tests: hover on a qualified member, hover on a global, a user declaration shadowing a built-in name, and a completion item carrying both signature and documentation.