Releases: luau-lang/luau
0.674
General
- Expose an optional
get_alias
API as an alternative toget_config
in Luau.Require and Luau.RequireNavigator. - Improve the Luau CLI's virtual filesystem implementation to fix bugs related to
init.luau
. Fixes #1816
New Type Solver
- Avoid double reporting errors when erroneous arguments are provided to type functions.
- Fix some instances of unresovable cyclic type functions in loops by only considering the first loop cycles. This results in some type inference inaccuracies when the type of a variable in loop through multiple iterations. Fixes #1413.
- Better generalize free types that have meaningful lower and upper bounds, especially for table indexers.
- Report more specific errors when assigning or returning table literal types, instead of citing the entire table type.
- Inference for functions with generic type packs is greatly improved.
- Fix some internal compiler exceptions when using type-stating functions like
table.freeze
inif _ then _ else _
expressions and short circuiting binary operations. - More consistently simplify unions of primitive types, especially in array-like and dictionary-like tables.
- Fix a crash when type checking an erroneous type alias containing
typeof
with a type assertion expression, as in:type MyTable = {} -- This will error at type checking time as it's a duplicate type MyTable = typeof(setmetatable(SomeTable :: {}, SomeMetaTable));
- Fix a crash when inferring the type of an index expression where the indexee is invalid (e.g.
nil
).
Runtime
- Avoid throwing an exception from
luau_load
if we run out of memory. - Type functions are no longer compiled and included in bytecode. Fixes #1817.
- Fix some instances of Luau C API functions reading invalid debug information (generally when the first or last instruction of a block was being inspected). Fixes #1369.
- Avoid potential signed integer overflow when doing bounds checks on tables.
- Support 16 byte aligned userdata objects when system allocation alignment is also 16 bytes.
- Fix memory leaks in
Luau.Require
when using VM build with no exceptions. Fixes #1827.
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: James McNellis jmcnellis@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
0.673
General Changes
- Remove a
static_assert
that prevented Luau from building on 32-bit targets. - Fix
proxyrequire
(see #1804) - Replace contents API with new
loadname
API in Luau.Require - Store the positions of
:
symbols in the CST. - Fix a minor bug in the new incremental autocomplete engine: Properly suggest
else
andelseif
if the cursor is currently within anif
block.
New Type Solver
- Allow generics to be substituted for negation types when performing subtype tests
- Crash fixes
- Surface subtyping errors more consistently.
- Avoid creating double-negation types (like
~~(false?)
) when generating constraints.
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Aviral Goel agoel@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
Full Changelog: 0.672...0.673
0.672
What's Changed?
Hi there, folks! It's been another busy week in the type mines, trying to bring you all the very best type inference system we can. We've got a bunch of updates to large pain points across the new type solver, and our next big update (currently under a debug flag) improving type generalization is finally nearing completion (and should hopefully eliminate quite a lot of "type solver failed to complete" errors). We've also continued polishing both the CST Parser and the Luau.Require
library we introduced a few releases ago based on user feedback and bug reports, and we're really happy with how they're turning out.
Parser
- Fixes a bug in the CST tooling where the spacing on return type annotations for functions was not being printed correctly.
- Resolves some issues with the JSON encoding of
AstGenericType
andAstGenericTypePack
Runtime
- Implements support for yielding requires in
Luau.Require
library. - Improves the error messages for require-by-string to include the chunk name that was problematic where possible and the overall require path that failed to be required.
- Fixes a bug that prevented the use of
require
within C functions andpcall
. - Adds an API to support selectively removing chunks from the require cache in
Luau.Require
- Adds an API to support clearing the entire require cache in
Luau.Require
New Type Solver
- Fixes a crash in the new non-strict mode when visiting function return types in incomplete ASTs (e.g. during editing).
- Improves type simplification to support intersections of tables with extern types, resolving one of the causes of frequent refinements unexpectedly leading to
never
. - Improves type inference to better understand diverging branches in functions, reducing false negatives where the type system fails to learn that a binding must now always be initialized.
- Fixes a typo in the type definitions for user-defined function types where the
intersection
tag was misspelled. - Improves the overall accuracy of free type tracking during constraint solving, leading to better inference results overall.
- Implements
types.optional
as a new library function for user-defined type functions to make it easier to union a type withnil
. - Resolves a number of bugs caused by local type inference expanding the domain of upvalues
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Full Changelog: 0.671...0.672
0.671
What's Changed
- Internally rename
ClassType
toExternType
. In definition files, the syntax to define these types has changed todeclare extern type Foo with prop: type end
- Add
luarequire_registermodule
to Luau.Require - Support yieldable Luau C functions calling other functions
- Store return types as
AstTypePack*
on Ast nodes
New Solver
- Improve the logic that determines constraint dispatch ordering
- Fix a crash in the type solver that arose when using multi-return functions with
string.format
- Fix #1736
- Initial steps toward rethinking function generalization:
- Instead of generalizing every type in a function all at once, we will instead generalize individual type variables once their bounds have been fully resolved. This will make it possible to properly interleave type function reduction and generalization.
- Magic functions are no longer considered magical in cases where they are not explicitly called by the code.
- The most prominent example of this is in
for..in
loops where the function call is part of the desugaring process. - Almost all magic functions work by directly inspecting the AST, so they can't work without an AST fragment anyway.
- Further, none of the magic functions we have are usefully used in this way.
- The most prominent example of this is in
Full Changelog: 0.670...0.671
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
0.670
What's Changed
This week has been focused primarily on bugfixes, with a ton of usability improvements to the new solver, fragment autocomplete, and the concrete syntax tree project.
Community Contributions
- Update Arch Linux installation instructions by @MaidenlessUsr in #1774
Runtime
- Fix an assertion caused by failing to allocate native code pages.
- Expose a
lua_pushrequire
function, which performs the same initialization steps asluaopen_require
but does not register require globally. This lets users create specialized, customrequires
.
New Solver
- Fix a bug in simplification of types caused by combinatorial explosion of intersection and union types.
- Fix a memory leak in fragment autocomplete
- Improve the isolation of modules in fragment autocomplete
- Throw errors when users define a type function with the name
typeof
- Continue to narrow intersection types which might be
never
. - Major rework of generalization continues - we are blazing a new path with eager + non-reentrant generalization and actively working to make these more performant and less error prone.
- Improve the ability of
and/or
type functions to reduce, even when their arguments are generic. - Report arity mismatches for undersaturated calls with unknown parameters
New Non-Strict
- Extends the new non-strict mode to report unknown symbols in types
Old Solver
- Fix a crash caused by excessive stack usage during typechecking
Misc
- Improvements to Concrete Syntax Tree location tracking for string table props.
- Do not store file extensions in module chunknames [Luau CLI] by @vrn-sn in #1772
Full Changelog: 0.669...0.670
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Aviral Goel agoel@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
0.669
What's Changed
General
- We updated Luau's license year to 2025!
- We fixed a bug where large amounts of errors were being printed when deep intersections of unions error.
Require-by-String
This release introduces the Luau.Require
library, which exposes the runtime semantics of require-by-string, including support for the new @self
alias described in this RFC.
The library operates on a virtualized filesystem, allowing consumers to specify navigation rules without assuming a filesystem context. Documentation in Require.h
explains how to enable the library, and the setupState
function in Repl.cpp demonstrates how we've integrated it into the luau CLI tool. Note that the interface in Require.h
is written in C, which enables any application written in a language with a C foreign-function interface to link against this library and enable require-by-string. This makes it straightforward for any application embedding Luau to support require-by-string, provided that it defines or operates within an environment resembling a virtual filesystem.
The core navigation semantics of require-by-string have additionally been pulled into the Luau.RequireNavigator
library. While Luau.Require
internally depends on Luau.RequireNavigator
, the latter does not depend on the Luau VM. This library provides an interface for inspecting require-by-string's navigation behavior and therefore serves as a useful dependency for static tooling. Documentation for Luau.RequireNavigator
is available in RequireNavigator.h
.
Autocomplete
- We fixed a memory leak in fragment autocomplete!
New Solver And Old Solver
- We've found a infinite iteration error over a type pack. We added a way to detect this error and throw an
InternalCompileError
instead. - We fix
table.freeze
not accounting for the first argument not getting type stated. We fall back to regular inference instead. - We fix a crash in the old solver with
length_error
. - We fix a crash in the new solver stemming from generalization reentrancy. Now we correctly generalize interior free types that do not appear in a function signature.
- We fix a nil refinement. (Fixes #1687 and #1451)
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
Full Changelog: 0.668...0.669
0.668
New Type Solver
- Update resolved types for singleton unions and intersections to avoid crashing when type checking type assertions.
- Generalize free return type pack of a function type inferred at call site to ensure that the free type does not leak to another module.
- Fix crash from cyclic indexers by reducing if possible or producing an error otherwise.
- Fix handling of irreducible type functions to prevent type inference from failing.
- Fix handling of recursive metatables to avoid infinite recursion.
New and Old Type Solver
Fix accidental capture of all exceptions in multi-threaded typechecking by converting all typechecking exceptions to InternalCompilerError
and only capturing those.
Fragment Autocomplete
- Add a block based diff algorithm based on class index and span for re-typechecking. This reduces the granularity of fragment autocomplete to avoid flakiness when the fragment does not have enough type information.
- Fix bugs arising from incorrect scope selection for autocompletion.
Roundtrippable AST
Store type alias location in TypeFun
class to ensure it is accessible for exported types as part of the public interface.
Build System
- Bump minimum supported CMake version to 3.10 since GitHub is phasing out the currently supported minimum version 3.0, released 11 years ago.
- Fix compilation when
HARDSTACKTESTS
is enabled.
Miscellaneous
Flag removals and cleanup of unused code.
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
External Contributors
Thanks to @grh-official for PR #1759
Full Changelog: 0.667...0.668
0.667
After a very auspicious release last week, we have a new bevy of changes for you!
What's Changed
Deprecated Attribute
This release includes an implementation of the @deprecated
attribute proposed in this RFC. It relies on the new type solver to propagate deprecation information from function and method AST nodes to the corresponding type objects. These objects are queried by a linter pass when it encounters local, global, or indexed variables, to issue deprecation warnings. Uses of deprecated functions and methods in recursion are ignored. To support deprecation of class methods, the parser has been extended to allow attribute declarations on class methods. The implementation does not support parameters, so it is not currently possible for users to customize deprecation messages.
General
- Add a limit for normalization 8000 of function types.
New Type Solver
- Fix type checker to accept numbers as concat operands (Fixes #1671).
- Fix user-defined type functions failing when used inside type aliases/nested calls (Fixes #1738, Fixes #1679).
- Improve constraint generation for overloaded functions (in part thanks to @vvatheus in #1694).
- Improve type inference for indexers on table literals, especially when passing table literals directly as a function call argument.
- Equate regular error type and intersection with a negation of an error type.
- Avoid swapping types in 2-part union when RHS is optional.
- Use simplification when doing
~nil
refinements. len<>
now works on metatables without__len
function.
AST
- Retain source information for
AstTypeUnion
andAstTypeIntersection
.
Transpiler
- Print attributes on functions.
Parser
- Allow types in indexers to begin with string literals by @jackdotink in #1750.
Autocomplete
- Evaluate user-defined type functions in ill-formed source code to provide autocomplete.
- Fix the start location of functions that have attributes.
- Implement better fragment selection.
New Contributors
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Aviral Goel agoel@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
Full Changelog: 0.666...0.667
0.666
Another week, another release. Happy spring! π·
What's Changed
New Type Solver
- Add typechecking and autocomplete support for user-defined type
functions! - Improve the display of type paths, making type mismatch errors far
more human-readable. - Enhance various aspects of the
index
type function: support function
type metamethods, fix crashes involving cyclic metatables, and forward
any
types through the type function. - Fix incorrect subtyping results involving the
buffer
type. - Fix crashes related to typechecking anonymous functions in nonstrict
mode.
AST
- Retain source information for type packs, functions, and type
functions. - Introduce
AstTypeOptional
to differentiateT?
fromT | nil
in
the AST. - Prevent the transpiler from advancing before tokens when the AST has
errors.
Autocomplete
- Introduce demand-based cloning and better module isolation for
fragment autocomplete, leading to a substantial speedup in performance. - Guard against recursive unions in
autocompleteProps
.
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss aaronweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
Full Changelog: 0.665...0.666
0.665
Hello all! Another week, another Luau release!
Change to lua_setuserdatametatable
This release fixes #1710: lua_setuserdatametatable
is being changed so that it only operates on the top of the stack: the idx
parameter is being removed. Prior to this, lua_setuserdatametable
would set the metatable of the value in the stack at idx
, but always pop the top of the stack. The old behavior is available in this release as lua_setuserdatametatable_DEPRECATED
.
What's changed?
This release exposes a generalized implementation of require-by-string's autocomplete logic. FileResolver
can now be optionally constructed with a RequireSuggester
, which provides an interface for converting a given module to a RequireNode
. Consumers of this new API implement a RequireNode
to define how modules are represented in their embedded context, and the new API manages the logic specific to require-by-string, including providing suggestions for require aliases. This enhancement moves toward integrating require-by-string's semantics into the language itself, rather than merely providing a specification for community members to implement themselves.
New Type Solver
- Fixed a source of potential
Luau::follow detected a Type cycle
internal compiler exceptions when assigning a global to itself. - Fixed an issue whereby
*no-refine*
(a type which should not be visible at the end of type checking) was not being properly elided, causing inference of class-like tables to become unreadable / induce crashes in autocomplete. - Fixed a case of incomplete constraint solving when performing basic math in a loop
Fragment Autocomplete
- Fixed several crashes related to not properly filling in scope information for the fragments
- Fixed a source of memory corruption by isolating the return type of a fragment when it is type checked.
- Improved performance by opting not to clone persistent types for the fragment (e.g.: built in types)
Full Changelog: 0.664...0.665
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Talha Pathan tpathan@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com