Repository navigation
Releases: rbx-loom/loom
Releases · rbx-loom/loom
Release list
v2.0.2
2.0.2 - 2026-09-02
A small follow-up to 2.0.1, focused on module resolution: declaration files pairing with hand-written Luau
now actually resolve, folders gain a second index-file convention, and the package manager pipeline is
verified end-to-end for third-party (non-Loom) Luau libraries.
Module resolution
.d.loomdeclaration files are now importable modules in their own right. Anexport declarenames an
ordinary export; a baredeclarestays ambient (visible everywhere in the root, not importable) — the
way it always has been for a global.- A declaration file's hand-written
.luausibling (e.g.jecs.d.loomnext tojecs.luau) is copied into
the output tree in the declaration file's place, so arequireof it resolves to real Luau at runtime. - Folders now fold into a
main.loomindex file, alongside the existing Rojo-nativeinit.loomconvention
— theindex.js/__init__.pystyle, for a package authored without Rojo's own folding in mind.
init.loomwins where a folder somehow has both. - Fixed a require emitted for a
main.loom-folded import falling back to a path Luau's own
require-by-string resolver can't fold on its own; it now names the file outright when no Rojo project
maps the output.
Package manager
- Verified (and covered with a regression test) that publishing and installing a package carries every file
under its source directory — not just.loomones — so a third-party package wrapping a hand-written
.luaulibrary round-trips its runtime sibling throughloom publish/loom addintact.
Full Changelog: v2.0.1...v2.0.2
2.0.0
[2.0.0 (2.0.1)] - 2026-09-01
The second release of Loom. Where 1.0.0 proved out the language, 2.0.0 turns it into a toolchain: a full
language server, a package manager with a real registry, and a broad expansion of both the type system and
the standard library, alongside binary/delta serialization generated straight from your types.
Language server
- Diagnostics, hover, go-to-definition, go-to-type-definition, and go-to-implementation over
.loomfiles. - Context-aware completion — members, attributes, module specifiers, and type-vs-value position — with
auto-import and signature help. - Inlay hints, find-references, rename (including updating imports), document highlight, outline,
folding ranges, call/type hierarchy, semantic tokens, workspace symbol search, code lens, and quick fixes. - Incremental, debounced recompilation per document store, with a project's whole unit re-diagnosed
together rather than file-by-file; watches files changed outside the editor and reacts to lockfile
changes. - https://github.com/rbx-loom/vscode-loom/releases/tag/v0.3.2
Package manager & registry
loom addandloom publish(with--allow-dirtyfor a publisher who knows something the working tree
doesn't), plusloom loginfor storing a registry token outside any project.- Resolving, installing, and publishing packages over an HTTP registry, with a local index usable for
vendoring or fixtures. - A real lock file (
loom-lock.toml): version requirement parsing and intersection, yanked-version
handling, checksum verification against what the index states, and a failure channel so an unreachable
registry is reported rather than read as "package doesn't exist." [dependencies]/bare module specifiers resolve to package roots, with an install-location contract that
keeps a dependency's compiled output scoped to the consuming project.- Huge thanks to @AlternativeLua for this entire section!
async/await
async fnputs Luau's invisible yields in the function signature; calling one starts it and hands back a
Future<T>, so two yielding calls can run concurrently instead of blocking each other.- Every Roblox API method the dump tags
Yieldsis generated asasync fnautomatically. [no_yield]marks a function that may not await, and a chain of awaited calls collapses into one
traceback-preserving wait rather than one per link.
Type system
- Static interface members and
staticblocks, plus the::operator for reaching them (also now required
for enum member access). - Conditional types (
T is U ? A : B/match T { ... }) and mapped types ([K from keyof(T)]: T[K]),
resolved lazily against an instantiation rather than at declaration. - Operator overloading — a trait carrying
[luau_metamethod]methods makes+,==,<, and friends work
on your own types, resolved through interface/trait metamethod info at the type-checking level. - Type indexing (
Foo["bar"], enum member types, indexing through a generic parameter) resolved at compile
time. - Iterators — a type implementing
Iterator<T>can drive aforloop itself. - Realms —
[realms]assigns each project directory toclient/server/shared, and an import that
crosses that boundary is a compile error instead of a runtime surprise;[server]/[client]narrow a
single declaration inside a shared module. - A large pass of correctness fixes to generic instantiation, overload resolution, union pattern narrowing,
and structural assignability — including canonicalizing generic instantiations, keeping a stored generic's
written name through substitution, and unifying assignability's mutability rule across properties,
indexers, and arrays.
Language features
- Pattern matching gained an
isoperator, anonymous functions, negation patterns, and qualified enum
members as match patterns. everystatements, decorators (function-wrapping and zero-cost compile-time metadata, queried with
get_metadata/has_attribute, restricted withattribute_usage), and default trait method bodies shared
as one Luau function across every non-overridingimplementblock.- Built-in
Display,Eq, andHashtraits — recursiveto_string(), structuralequals(), and a
consistenthash()for free on any interface. - The
withoperator (value with { field: newValue }) for building a new instance from an existing one. - Named arguments, nested destructuring patterns, and destructuring defaults.
- Spread elements —
[69, ..rest]in array literals andf(..rest)into a rest parameter. - Optional chaining (
?.) and the null-forgiving expression (!). - The
^=once event operator, connecting a handler that disconnects itself after firing once. export */export type *and theinternalmodifier, one notch narrower thanexport.- Doc comments (
###), with@param/@returnssurfaced through hover and signature help.
Serialization
[serializable]interfaces get generatedbuffer-backed binary codecs — no runtime schema walked.[packed]bit-packing, variable-width and fixed-width array elements, string/optional/union fields, map
encoding for indexer types, and nested collections including unions inside them.- Delta encoding (
diff_binary/apply_diff_binary) sends only what changed, with generic structural
equality emitted into the runtime library to detect it. - Sized number types (
u8/u16/u32/i8/i16/i32/f32/f64) and type-level sizing syntax for
Vector3/Vector2/CFrame/array length, replacing the oldnumber_type/length_typeconfig. - Round-trip tested by actually executing the emitted serializers on an embedded Luau, not just snapshotted.
Standard library
Set<T>/MutSet<T>— set algebra lowered to a plain table with no runtime wrapper, plus
Array.to_set().- Array —
select,where,aggregate,select_many,flatten,any,all,count, fused into a
single pass over the array at codegen time rather than one per stage. - Result — additional combinators, including error-side combinators, and
?error propagation. - Roblox API methods that can fail now return
Result<T, RobloxError>instead of throwing, with
[fallible]marking a panicking escape hatch and[deprecated]warning at the use site.
Tooling & performance
loom newproject scaffolding, a rewritten CLI parser, colored output that degrades on redirected or
NO_COLORterminals, and Native AOT–published, ReadyToRun-precompiled release binaries installable via
rokit.- Incremental compilation: a module graph cache, and a no-
emitcompile skips generating Luau it will never
write. - A long pass of codegen performance work — array-combinator fusion, single-pass measuring/writing in the
serializer, presized allocations, cached repeated accesses — alongside correctness fixes across the parser,
resolver, flow analyzer, macros, and diagnostics surfaced throughout the release.
What's Changed
- fix/feat: events working across modules by @AlternativeLua in #140
- feat: config model by @AlternativeLua in #162
- feat: intrinsic binary serialization API (#139) by @R-unic in #158
- feat/operator-overloading by @R-unic in #166
- feat: compliation spans multiple roots by @AlternativeLua in #170
- Package manager prerequisites: resolution, scoping, install location, reporting by @AlternativeLua in #173
- fix/duplicate-interface-types by @R-unic in #181
- ref/serialization-emit-readability by @R-unic in #182
- fix/175-invalid-lsp-payloads by @R-unic in #184
- design/180-roblox-api-error-handling by @R-unic in #188
- perf/codegen-presize-and-step by @R-unic in #189
- Fix for #177 by @AlternativeLua in #190
- feat/array-combinators by @R-unic in #191
- feat: export all by @AlternativeLua in #192
- LSP expansion by @R-unic in #193
- feat: Installer via rokit by @AlternativeLua in #196
- feat: set intrinsic declarations by @R-unic in #195
- chore: clear qodana's high-severity inspections by @R-unic in #197
- docs: change ada's identity to poppy the viral singer by @aspennoo in #199
- feat: async/await and Future by @R-unic in #200
- fix/198-generic-identity-lost-on-substitute by @R-unic in #201
- chore/architecture-audit by @R-unic in #203
- perf: serialization & chained array combinator emit optimization by @R-unic in #204
- feat: server/client/shared realms, generalized iterators, and [no_yield] guard by @R-unic in #205
- feat: array spread elements by @R-unic in #207
- fix: keyof, generic-dependent constraints, and intersection members by @R-unic in #208
- feat: type system expansion by @R-unic in #209
- feat: package resolution, lock file, and version requirements by @AlternativeLua in #225
- Stdlib parity by @R-unic in #228
- ...
1.0.0
[1.0.0] - 2026-07-30
The first release of Loom, a domain-specific language for Roblox that transpiles to Luau.
Pattern matching
- Full Luau generation for every pattern kind: array, object, tuple, range, typed, or, and, rest, and
wildcard patterns, including guard clauses (when). - Match exhaustiveness checking, including discriminated unions narrowed by a common property.
- Structural checking via patterns, and patterns matching Roblox instance types (e.g. matching on a
specificInstancesubclass). - Object pattern fields respect
luau_namerenaming.
Type system
- Bidirectional/contextual typing threaded through the whole checker for better inference with fewer
annotations. - Detailed, actionable type error messages with hints (e.g. suggesting the operator you probably meant).
- Flow-sensitive narrowing, including after assignment (
n ??= 69narrowsnoff its declared optional
type for the rest of that flow).
Standard library
math- typings for Luau's built-in math library (trig, rounding,clamp,random, etc.).string- methods and properties (.length,.split(),.trim(),.replace(),.starts_with(),
and more), mapped directly to Luau'sstringlibrary where possible.Array-.join(),.push()/.pop(),.insert()/.remove(),.index_of(),.has().Range-.length,.clamp().- Result pattern for error handling (
Result.ok/Result.err) in place ofpcall. - Instance query macros -
get_children,get_descendants,is_a,find_first_child_of_class, and
related queries, generic over the Roblox class name.