Skip to content

Releases: rbx-loom/loom

v2.0.2

Choose a tag to compare

@github-actions github-actions released this 02 Sep 13:15
ef525ce

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.loom declaration files are now importable modules in their own right. An export declare names an
    ordinary export; a bare declare stays ambient (visible everywhere in the root, not importable) — the
    way it always has been for a global.
  • A declaration file's hand-written .luau sibling (e.g. jecs.d.loom next to jecs.luau) is copied into
    the output tree in the declaration file's place, so a require of it resolves to real Luau at runtime.
  • Folders now fold into a main.loom index file, alongside the existing Rojo-native init.loom convention
    — the index.js/__init__.py style, for a package authored without Rojo's own folding in mind.
    init.loom wins 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 .loom ones — so a third-party package wrapping a hand-written
    .luau library round-trips its runtime sibling through loom publish/loom add intact.

Full Changelog: v2.0.1...v2.0.2

2.0.0

Choose a tag to compare

@github-actions github-actions released this 01 Sep 15:35
5c107fe

[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 .loom files.
  • 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 add and loom publish (with --allow-dirty for a publisher who knows something the working tree
    doesn't), plus loom login for 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 fn puts 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 Yields is generated as async fn automatically.
  • [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 static blocks, 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 a for loop itself.
  • Realms — [realms] assigns each project directory to client/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 is operator, anonymous functions, negation patterns, and qualified enum
    members as match patterns.
  • every statements, decorators (function-wrapping and zero-cost compile-time metadata, queried with
    get_metadata/has_attribute, restricted with attribute_usage), and default trait method bodies shared
    as one Luau function across every non-overriding implement block.
  • Built-in Display, Eq, and Hash traits — recursive to_string(), structural equals(), and a
    consistent hash() for free on any interface.
  • The with operator (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 and f(..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 the internal modifier, one notch narrower than export.
  • Doc comments (###), with @param/@returns surfaced through hover and signature help.

Serialization

  • [serializable] interfaces get generated buffer-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 old number_type/length_type config.
  • 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 new project scaffolding, a rewritten CLI parser, colored output that degrades on redirected or
    NO_COLOR terminals, and Native AOT–published, ReadyToRun-precompiled release binaries installable via
    rokit.
  • Incremental compilation: a module graph cache, and a no-emit compile 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

Read more

1.0.0

Choose a tag to compare

@R-unic R-unic released this 30 Jul 07:27
Immutable release. Only release title and notes can be modified.
79ad559

[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
    specific Instance subclass).
  • Object pattern fields respect luau_name renaming.

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 ??= 69 narrows n off 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's string library 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 of pcall.
  • Instance query macros - get_children, get_descendants, is_a, find_first_child_of_class, and
    related queries, generic over the Roblox class name.