Releases: luau-lang/luau
0.676
We're back on track after the long weekend!
General
clang-format
ed new code. Keep your code tidy!- Disable some Luau tests that are broken currently.
- Enable fragment autocomplete to do tagged union completion for modules typechecked in the old solver.
New Type Solver
- Fix false positives on generic type packs in non-strict mode.
- Update type signature of
setmetatable
to be<T, MT>(T, MT) -> setmetatable<T, MT>
. - Make local type aliases available in type functions. For example:
type Foo = number
type Array<T> = {T}
type function Bar(t)
return types.unionof(Foo, Array(t))
end
VM/Runtime
- Make sure
lua_unref
doesn't accept refs which did not exist in the table.
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: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
Full Changelog: 0.675...676
0.675
General
- Introduce
Frontend::parseModules
for parsing a group of modules at once. - Support chained function types in the CST.
New Type Solver
- Enable write-only table properties (described in this RFC).
- Disable singleton inference for large tables to improve performance.
- Fix a bug that occurs when we try to expand a type alias to itself.
- Catch cancelation during the type-checking phase in addition to during constraint solving.
- Fix stringification of the empty type pack:
()
. - Improve errors for calls being rejected on the primitive
function
type. - Rework generalization: We now generalize types as soon as the last constraint relating to them is finished. We think this will reduce the number of cases where type inference fails to complete and reduce the number of instances where
*blocked*
types appear in the inference result.
VM/Runtime
- Dynamically disable native execution for functions that incur a slowdown (relative to bytecode execution).
- Improve names for
thread
/closure
/proto
in the Luau heap dump.
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: 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.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 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