Quality sprint: remove LLVM backend, fix generics crashes, align docs, wire LSP#10
Merged
Conversation
Cranelift is now the single code-generation backend. The LLVM path was a partial second implementation (~half the builtins, no push/str_*/math/http), did not build cleanly from the documented steps (zstd link error), and offered no measured speedup over Cranelift — which already edges out cc -O2 on the fib benchmark. Removing it eliminates ~6.8K LOC of duplicated codegen and the cost of keeping two backends at parity. - delete turbo-codegen-llvm crate; drop it from the workspace + turbo-cli deps - remove the `--llvm` cargo feature - drop the LLVM jobs/steps from CI, nightly, and release workflows - update RELEASE.md / CLAUDE.md test commands (no more --exclude turbo-codegen-llvm) A future optimizing backend, if pursued, should lower through a shared mid-level IR rather than re-walking the AST a second time.
Two correctness holes in generic functions:
1. Generic function bodies were never type-checked — check_function returned
early for any function with type params, so concrete errors inside them
(let y: i64 = "str"; undefined names) were silently accepted. Now the body
is checked with each type parameter erased to the Error poison type, so
genuine bugs fire while operations over a type param (x + 1) don't
false-positive.
2. Indexing a generic array param ([T]) segfaulted: turbo_ty_from_type_expr
dropped type_params when recursing into Array/Optional/Result/Fn, so [T]'s
element resolved to Struct("T"); indexing then returned an integer typed
as a struct pointer and the refcount path dereferenced it. The call site
now also recovers the concrete element type so a [str] arg prints correctly.
Also: undefined-function errors now suggest a close match ("did you mean
`print`?"), backed by a single-source BUILTIN_FNS list.
Adds regression tests generic_body_checked and generic_array_index.
- parser: range upper bound now parses a full binary expression, so `0..len + 1` and `1..n - 1` work (previously only a unary was parsed) - lexer/cli: an integer literal too large for i64 now reports "integer literal ... is too large for i64" instead of "unexpected character" - cli: `explain` accepts lowercase codes (`explain e0100`) - cli: drop the now-dead `--llvm` build flag - formatter: refuse to reformat files that don't lex/parse (no more silently reindenting broken code) - lsp: diagnostics now carry the E0NNN error code Adds regression test range_arith_bound.
- delete unused resolve_cl_type_with_data (was kept alive by #[allow(dead_code)]) - clippy: use std::ptr::eq for raw-pointer comparison; const thread-local Cell; collapse a nested if; use RangeInclusive::contains - rustfmt reflow cargo clippy --workspace is now warning-clean.
The extension shipped syntax highlighting only — the 2,140-LOC language server (turbolang lsp) was never reachable from VS Code. Add: - extension.js: a vscode-languageclient that launches `turbolang lsp` over stdio, enabling diagnostics, hover, go-to-definition, completions, references, rename, and document symbols in the editor - package.json: main/activationEvents/deps, plus turbo.lsp.path and turbo.lsp.enable settings - snippets/turbo.json: 25 idiomatic snippets (fn, struct, type, match, for, test, server, …) - README with build/install instructions
- README: drop the v0.8.x label, fix binary size 55KB -> 93KB (measured), builtins 64+ -> 100+, fix the VS Code extension line (publisher zvn-dev, 25 snippets), show the working arrow-closure form in map/filter/reduce, remove the LLVM perf row and backend section - COMPATIBILITY: update the version series to 0.9.x; drop the LLVM backend from the experimental list - CHANGELOG: note the LLVM backend removal under [Unreleased] - SYNTAX.md: add a banner clarifying it's the design vision (not the changelog), correct the derive list to Eq/Clone/Display, and retag map/object literals as planned rather than implemented
Untrack 8 internal sprint/audit docs (AUDIT-REPORT, FINDINGS-REPORT, the three SPRINT-PLAN files, STDLIB-ROADMAP, TODO, turbo/PHASE1-POLISH-SPRINT) and a stray benchmark screenshot from the public repo root — they leak internal planning and contradict the current state. The .gitignore already had a section titled "Internal planning docs (should never be committed)"; these had slipped past it. Files remain on disk locally; they're now gitignored, along with the stray mock_agent/simple_agent build artifacts.
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.
Deep quality audit + fix sprint on the Turbo compiler. Five parallel review agents (codegen, frontend pipeline, DX/tooling, claim verification, product/language design) produced a severity-ranked report; this branch executes the fixes. Every finding was verified before fixing, and the full suite is green after every change.
Validation
cargo clippy --workspace0 warnings ·cargo fmt --checkcleanHighlights
Architectural: removed the experimental LLVM backend
It was a partial second implementation (~half the builtins), didn't build from the documented steps (zstd link error), and offered no measured speedup over Cranelift — which already beats
cc -O2on fib. Removing it kills ~6.8K LOC of duplicated codegen, an unbuildable advertised feature, and an unreproducible perf claim. Cranelift is now the single, honest backend.Two CRITICAL bugs fixed (both verified)
returnmeantlet y: i64 = "str"and undefined names inside any generic were accepted. Now checked with type-params erased to theErrorpoison so real bugs fire without false-positiving onx + 1overT.[T]indexing segfaulted —turbo_ty_from_type_exprdroppedtype_paramsrecursing intoArray/Optional/Result/Fn, so[T]'s element becameStruct("T")and the refcount path dereferenced an integer. Fixed + call-site element-type recovery.DX
prnt→ "did you meanprint?";1..n+1parses; huge ints say "too large for i64";explainis case-insensitive; LSP diagnostics carryE0NNN; formatter refuses unparseable filesHonesty + hygiene
SYNTAX.mdhonesty banner + corrected derive/map-literal tagsKnown pre-existing bugs (NOT regressions — confirmed by rebuilding the original compiler; left for follow-up)
examples/todo-cli/main.tbintermittentlySIGTRAPs on teardown (string-arena/memory)remove_constant_phispanic on int-hashmap multi-function modulesDeferred (flagged, not half-built)
Optional auto-wrap (
let x: str? = "hi"),ascasts, trait bounds over primitives, generic arity checking, parser in-body error recovery, method-vs-function error wording, AST-based formatter for operator spacing. Each is a design-weight change.The wedge (product takeaway)
Today Turbo is honestly "a small, fast, Go-simple compiled language with a TS-flavored surface" — not yet full "TypeScript's ease" (object literals,
??/?.on real optionals, typed maps, casts are the gaps). Sharpest defensible wedge right now: the fastest way to write a single-file native CLI/script that starts instantly and ships as a tiny binary.🤖 Generated with Claude Code