Releases: luau-lang/luau
0.706
Hey everyone! We've been hard at work fixing bugs and improving native codegen. Enjoy!
Analysis
-
Rename the class tag to extern in type functions
-
Fix #2204
-
Rework type unification in terms of subtyping.
This uses the new solver's understanding of subtyping to drive unification for
some internal callsites. This is a broad change that should result in more
consistent inference. For example:local function sum<T>(x: T, y: T, z: (T, T) -> T) return z(x, y) end local function sumrec(f: typeof(sum)) return sum(2, 3, function<X>(g: X, h: X): add<X, X> return g + h end) end -- Prior we would claim that `b` is of type `add<X, X> | number`: not good! -- We now correctly claim that it is of type `number` thanks to bug fixes -- made to subtyping that did not make their way to the unifier. local b = sumrec(sum)
Native Codegen
- Improve vector handling in binary operations
- Fix missed optimization causing an assertion failure
- Propagate loads of STORE_VECTOR components produced by UINT_TO_FLOAT
- Constant-fold new operand of CHECK_BUFFER_LEN
- For register load-store propagation, use the second operand only for LOAD_FLOAT
- TValue store cannot be removed when it's partially over-written
- Rework equality and ordering comparisons to fix issues and be more type aware
- Migrate Luau NCG IrInst operands representation to SmallVector
Runtime
- Fix 64-bit countrz to build on 32 bit Windows.
- Remap Luau local debug and type information after performing jump expansion
- Add support for building Luau as a shared library
- Luau should be able to make fastcalls even if library name is obscured by a local polyfill
OSS Contributions
- Track type spans in
ToStringResultto support decomposition #2163 - Expose
luaL_tracebackfrom Lua C API #2167
Internal Contributors
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Ilya Rezvov irezvov@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.705...0.706
0.705
Hello Luaunauts, we're continuing into the second release of the year at a brisk pace! We've got a number of improvements for both native code generation and the new type solver, as well as some other assorted changes, that keep us moving towards the goal of making the best possible scripting language!
Analysis
- Refinements against a union of tables would sometimes erroneously refine to a narrower type than intended. The root cause here was a bug in the logic that determines how to "simplify" types (for example knowing that
true | falseis the same asboolean).export type States = "Closed" | "Closing" | "Opening" | "Open" export type MyType<A = any> = { State: States, IsOpen: boolean, Open: (self: MyType<A>) -> (), } local value = {} :: MyType function value:Open() if self.IsOpen == true then elseif self.State == "Closing" or self.State == "Opening" then -- Prior, this line errored as we were erroneously refining -- `self` with `{ State: "Closing" | "Opening" }` rather -- than `{ read State: "Closing" | "Opening" } self:Open() end end
- Adds an option in
ToString.cppto disable the use of synthetic names, which can be used to improve the quality of hover type. - Fixes a bug where
table.freezewould incorrectly error on arguments ofanytype (fixes #2181) - Subtyping mistakenly did not allow for us to covariantly check tables with missing properties against table types that gave those properties optional types. This release should fix these issues, including fixes #2164.
- Type functions have a global environment that defines all of the type aliases present in the environment around the type function definition, and the API of type functions also allows you to mutate types, specifically table types and function types. Though we never supported the type functions actually mutating the aliases present in the environment around them, the mutable API allowed for users to author type functions that appeared to do so, which could be confusing when they later discover that their mutation did not take place. This release introduces new errors for type functions that attempt to call mutable APIs on types from their environment, e.g.
type myType = {} type function create_table_with_key() myType:setproperty(types.singleton "key", types.optional(types.number)) -- this errors now! return myType end local my_tbl: create_table_with_key<> = {key = "123"}
- Bidirectional inference for lambdas on extern types with generic parameters should work more consistently.
- #2166 fixes a bug with
findBindingAtPositionthat should enable LSP tools to better support finding references for local functions and their parameters. - This release also includes a broad-strokes improvement to error suppression handling. The New Type Solver should now be more consistent about not reporting (or re-reporting) errors involving
anyor*error-type*or directly downstream of an existing type error. - This release removes the experimental
DebugLuauStringSingletonBasedOnQuotesflag that trialed basing singleton type inference solely on the usage of different quote styles. We do not think we will be proceeding with this approach at this time.
- Adds an option in
Native Code Generation
- Fixes a crash in
getOffsetBasewhen the passed in IrOp is not an IrInst. - Improves inlining support by passing the argument value as the initializer for the temporary being allocated in cases like anonymous function arguments or referring to upvalues in a function body.
- Fixes the function end byte offset value, along side a number of other internal values that could lead to incorrect code size values.
- Adds a more direct implementation of code generation for
vectorequality and inequality that leads to fewer instructions in the IR and a smaller number of produced basic blocks. - Adds a more optimized code generation flow for situations where we're indexing a table with keys that have unexpected type tags.
- Fixes a bug where NCG would sometimes mistakenly optimize away necessary entry tag checks.
- Introduces a customizable per-VM storage for use from "execution callbacks" system, with NCG as its first consumer for extra spill spaces. This adds 32x 8-byte spill slots on arm64 (on top of existing 22) and 64x 8-byte spill slots on x64 (on top of existing 12*).
- Changes codegen for bit32 operations to use guards, rather than normal control flow, leading to significant (~30%) performance improvements in some benchmarks that heavily leverage these operations.
- Adds a combined instruction
UINT_TO_FLOATto replace instances where we needed to emitUINT_TO_NUMandNUM_TO_FLOATpaired up. This leads to some very modest performance improvements.
Runtime
- We previously added constant string constant folding with the results stored in AST allocator. This release also moves interpolation formatting strings to AST allocator to resolve #1965.
- #2069 adds support for using
os.clockin Emscripten build targets, like the Luau Playground. - #2149 extends the C++ Require library to support constructing aliases with tags associated with them.
- #2054 fixes a bugged comparison in
api_update_topthat would cause an unnecessary runtime error if the API was used in a way that should be a noop.
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Annie Tang annietang@roblox.com
Co-authored-by: Ariel Weiss arielweiss@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: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
OSS Contributions
- Expose
luaL_tracebackfrom Lua C API by @Nerixyz in #2167 - Handle AstStatLocalFunction in findBindingAtPosition by @JohnnyMorganz in #2166
- Track type spans in ToStringResult to support decomposition by @JohnnyMorganz in #2163
- Fix comparison issue with
api_update_topby @Sleitnick in #2054 - Add branch for Emscripten to clock by @SeyedAlirezaFatemi in #2069
- Rename
classtoexternin UDTF type tags (RFC) by @PhoenixWhitefire in #2131 - Raise stack limit for Luau.CLI.Test in MSVC Debug configuration. by @Waffle3z in #1976
New Contributors
- @Nerixyz made their first contribution in #2167
- @Sleitnick made their first contribution in #2054
- @Waffle3z made their first contribution in #1976
Full Changelog: 0.704...0.705
0.704
Hello everyone and a happy New Year!
The first sync of 2026 is already here with improvements to new type solver and native code generation.
Analysis
- Explicit type instantiation is now ready for production use (Fixes #2114, Fixes #2144, Fixes #2113, and Fixes #2119)
- When subtyping extern types and tables, we now check indexers as well as properties, which fixes a soundness bug where tables without properties but clearly incompatible indexers were considered super types of extern types:
local function f(c: Color3): { Color3 }
return c -- This used to not error and now does
end
- Using bound generics as type annotations on nested functions or lambdas now no longer leak into the quantified generics of said lambda / inner function:
local function makeApplier<A..., R...>(f: (A...) -> (R...))
return function (... : A...): R...
f(...)
end
end
local function add(x: number, y: number): number return x + y end
-- Prior, `f` would have the (incorrect) type of `<A..., R...>(A...) -> (R...)`, as it
-- erroneously picked up the generics from `makeApplier`. Now it will have
-- the correct type of `(number, number) -> number`
local f = makeApplier(add)- Lambda bidirectional inference is now slightly less sensitive to generics; prior any generic in the lambda type would prevent "pushing in" the type, but now this is restricted to potentially unbound generics that are from the function type we are pushing in, as in:
type testsuite = { case: (self: testsuite, <T>(T) -> T) -> () }
local test1: { suite: (string, (testsuite) -> ()) -> () } = nil :: any
-- Prior we would error on the _entire_ lambda ...
test1.suite("LuteTestCommand", function(suite)
-- but now we only error here
suite:case(42)
end)- Generic polarity inference has been reworked to be significantly faster, especially for large mutually recursive type aliases
- Generic type packs now more consistently infer the correct type for function calls, most importantly for
pcalland its siblings. (Fixes #2109. Fixes #2143)
local function makestr(n: number): string
return tostring(n)
end
-- `s` now has type `string` and not `unknown`
local success, s = pcall(makestr, 42)- Bidirectional inference of constants (especially booleans) should be more consistent, such as in:
type Good = { success: true, result: string }
type Bad = { success: false, error: string }
type Result = Good | Bad
-- This errors before and after, but we now recognize that you
-- meant this to be `Bad` and will note the lack of the `error` member
local a: Result = { success = false, result = 'something' }- The mechanism for generating "Recursive type being used with different parameters" has been reworked. This should mean less false positives, and we will now consistently highlight the erroneous type alias instance, but we now adhere closer to the very strict RFC.
-- Not only did this line error, but it errored even in nonstrict mode
type A = { B<any> }
type B<T> = { method: (B<T>) -> () }
-- This used to _not_ error under the new solver but now does, despite being fairly benign
type B<T = number> = { B<number> }Native Codegen
vectorlibrary operations are now performed with 32-bit floating-point precision, matching the results of the interpreter and improving performance by skipping unnecessary 32-bit to 64-bit conversions- 2-argument
vector.createconstructor will now use native lowering instead of calling out to a slower C++ fastcall function - Added native support for vector flooring division operator
//instead of calling out to a slower C++ VM utility function - Identical calls to the math library (
math.cos,math.sinand many others) are now eliminated - A larger set of identical operations on vector values are now eliminated
- Buffer length checks are now merged together when possible
-- only one range check
return buffer.readf64(b, i) * buffer.readf64(b, i + 8) * buffer.readf64(b, i + 16)
-- when stride multiplier is used, it still produces only a single range check
return buffer.readf64(b, i * 8) * buffer.readf64(b, (i + 1) * 8) * buffer.readf64(b, (i + 2) * 8)- Fixed missing constant fold of
TRUNCATE_UINTwhich could cause a lowering failure under 'LuauCodegenNumIntFolds2' flag
Autocomplete
- Fixed a crash when indexing write-only properties
Open-source contributions
- Allow two-argument explicit constructor for RequireAlias by @JohnnyMorganz in #2149
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Annie Tang annietang@roblox.com
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@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.703...0.704
0.703
This will be Luau's last release for the year! Happy holidays and we'll see y'all in 2026.
Analysis
- Fix a bug in type checking functions where oversaturation (passing too many arguments to a function) was sometimes missed, for example:
type T = { method: (T, number) -> number }
local function onT(a: T)
a:method(5, 7) -- This would not error prior
end- Type mismatch error wording has been vastly improved: instead of talking about "X could not be converted into Y," we talk about "expecting Y" but "getting X."
- Builtin type functions now use improved logic for overload resolution.
- Type annotations on for-in loops are now respected, for example:
function my_iter(): any
return {}
end
for index: number, value: string in my_iter() do
-- This now errors, whereas prior we'd infer `index` to be of type `any`
local ohno: boolean = index
end- Function statements for table members now have their types checked, for example the following used to not error:
local Library: { isnan: (number) -> number } = {} :: any
function Library.isnan(s: string): boolean
return s == "NaN"
end- Nil-able lambdas can now participate in bidirectional inference, for example:
local listdir: (string, ((string) -> boolean)?) -> { string } = nil :: any
listdir("my_directory", function (path)
-- `path` will now have type `string` here
end)- Internal compiler errors when operating on exceptionally large types should be less common, thanks to some non-recursive implementations of common visitors.
- Fix a crash that could occur when deserializing user defined type functions, one such example being:
type function identity(t: type)
return t
end
type func<parameters...> = typeof(function(...: parameters...) end)
local whomp: <T>(arg1: T) -> identity<T>
whomp(function(...) end :: func<any>)- Fix instantiation picking unhelpful (and sometimes plain incorrect) bounds. Fixes #2125. Fixes #2118.
local foo: <P>(constructor: (P) -> any) -> (P) -> any = (nil :: any)
-- Prior `fn` would be of type `(never) -> any`, and will now be the more useful
-- ({ test: true }) -> any
local fn = foo(function (value: { test: true })
return value.test
end)- Fix a class of constraint solving incomplete errors that could occur when referencing globals inside lambdas.
types.unionofandtypes.intersectionofwill now attempt to simplify their arguments, avoiding producing nested intersections and unions, as well as removing identity types likeneverandunknown.- The
setmetatabletype function now waits for its arguments before resolving, fixing a class of constraint ordering bugs. Fixes #2106:
local MyClass = {}
local MyClassMetatable = table.freeze({ __index = MyClass })
type MyClass = setmetatable<{ name: string }, typeof(MyClassMetatable)>
function MyClass.new(name: string): MyClass
return setmetatable({ name = name }, MyClassMetatable)
end
function MyClass.hello(self: MyClass): string
return `Hello, {self.name}!`
end
local instance = MyClass.new("World")
-- This would sometimes be inferred as `any` due to constraint ordering bugs.
local g = instance:hello()Native Codegen
We now internally encode true float registers, as opposed to treating all floats as doubles (as Luau does). This allows us to skip conversions to and from a double when lowering operations on floats. Additionally, we've added several optimizations for converting in between different kinds of numbers (32-bit integers, 32-bit unsigned integers, floats, doubles, etc.).
Consequently, an important notice for users of CodeGen::HostIrHooks: we are updating the behavior of LOAD_FLOAT, DOT_VEC, EXTRACT_VEC, BUFFER_READF32, BUFFER_WRITEF32, and STORE_VECTOR to produce or consume single floating-point number instead of a double. When FFlag::LuauCodegenSplitFloat is enabled, FLOAT_TO_NUM and NUM_TO_FLOAT have to be used for explicit conversions.
- Double the amount of registers that are spilt for ints and floats on x64. This fixes NCG failing to compile snippets that end up generating many transient numbers. Fixes #1468.
- Fix a bug where NCG might improperly claim a stored value (and its tag) can be elided after a GC check.
- NCG now optimizes buffer and userdata loads that can be computed from previous stores (e.g. if you write
42to the nth byte in a buffer and then immediately read said byte). - NCG will now try to remove unused temporary userdata allocations
- Fix a bug where NCG might claim a spilt register has been restored but not actually do so, causing a garbage read from a register.
- NCG now optimizes upvalue loads and stores.
- NCG now optimizes
andandorwithout generating basic blocks, allowing more optimizations to occur. - Fix an NCG bug where, on arm64, restoring spilling registers may require using an (already occupied) temporary register.
- Runtime type checks internal to a function that are redundant with type checks added through annotations are now elided.
- NCG had an off-by-one bug where loop step detection was not kicking in for non-constant end ranges in for-in loops:
i = 1,10would be optimized andi = 1,#twould not be.
Require
- Added a
to_alias_overridecallback: this allows embedders to provide an alias that cannot be overridden by users.
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Annie Tang annietang@roblox.com
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Ilya Rezvov irezvov@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
0.702
Hello!
This week, we've made a bunch of improvements to the performance and stability of the analysis system. We've also made some small improvements to inlining and native codegen.
Autocomplete
- Suggest singleton string keys from indexers
General
- Reduce stack utilization of the parser
Analysis
- User-defined type functions don't need separate irreducible errors when they error.
- Fix a performance problem that could occur when selecting an overload for a function call.
- Fix a hang that could occur in function generalization.
- Delete EqSat. It was a very promising experiment but it didn't work out.
- Properly treat negation types as being contravariant in their operands. (ie if
A <: B, then~B <: ~A) - Add a new C++ utility function
Frontend::parseType. This function allocates aTypeIdfrom a string that contains a valid Luau type annotation. - Correctly infer the type of a property lookup on a table which contains an indexer which is a union of string singletons. (eg
{["foo"|"bar"]: number})
VM
- Reevaluate the inlining cost model using constant function arguments.
- Constant-fold
string.charandstring.sub.
Native Codegen
- Fix a perfermance regression that could happen when running out of registers.
- 32-bit integer addition and subtraction using bit32 library can be performed by integer instructions without extra double conversions
Internal Contributors
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
Full Changelog: 0.701...0.702
0.701
Hello everyone!
This week we have type inference improvements for refinements and user-defined type functions as well as new optimizations in Native Code Generation.
Merged earlier, but now available in the release are implementations of math.isnan, math.isinf and math.isfinite for Math Library RFC by @PhoenixWhitefire in #2078 and long awaited Explicit type parameter instantiation RFC by @Kampfkarren in #1980. Thank you!
What's New
- Fixed a bug that incorrectly allowed chained aliases to depend on aliases defined in deeper directories
- Added an optional
to_alias_fallbackC API to natively support host-injected aliases - Fixed building fuzzers using make
- Fixed serialization of userdata type mappings from
userdataTypescompiler option which caused a crash on bytecode load
Analysis
- Recursion counters have been added to the non-strict mode typechecker to prevent crashes
- Irreducible user-defined type functions are now marked as solved, improving consistency of type inference results
- Refinements against
unknowntype now work more consistently, resulting in more accurate inference
--!strict
local Class = {}
Class.__index = Class
type Class = setmetatable<{ A: number }, typeof(Class)>
function Class.Foo(x: Class, y: Class, z: Class)
if y == z then
return
end
local bar = y.A -- correctly infers number instead of any
endRuntime
- Added load-store optimizations for loading components of a vector in Native Code Generation (NCG). This should reduce the need to place repeatedly accessed vector components in locals and improve vector component shuffling
- NCG will exit to VM earlier when unsafe environment is detected, reducing work it has to throw away
- NCG will now optimize better across interrupt callback invocations; interrupts are to observe state and error/yield, general modification of VM state is not allowed there
New Contributors
- @PhoenixWhitefire made their first contribution in #2078
Full Changelog: 0.700...0.701
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Annie Tang annietang@roblox.com
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Ilya Rezvov irezvov@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
0.700
We have reached release 700!
Analysis
table.isfrozenandtable.clearuse{}instead of generic table type to make it work with union of table types.- Relax typing definitions for
types.newtableto make it easier to specify read-only table properties - Do not drop explicit generic type packs. Hopefully fixes #2075
- Added protection against stack overflows to more spots in
Unifier2 - Improved bidirectionally inferring lambdas. When performing inference on a lambda, check right before we attempt to emplace a free type whether there's a generic.
- Reworked overload resolution interface.
OverloadResolver::resolveOverloadwas introduced to abstract and unify existing resolving machinery. instantiation2selects more useful bounds.- If we have positive or negative polarity, blindly use the upper/lower bounds respectively.
- Otherwise, attempt to find a reasonable bound by first avoiding picking
neverorunknown, then doing a subtype test to try to pick a tight bound.
- Added protection against stack overflows to the non-strict type checker
- Luau-syntax configuration extraction can now be timed out during analysis. See
CLI/src/Analyze.cppfor an example.
Require
- Support chained aliases with built-in cycle detection: luau-lang/rfcs#145.
- Resolve JohnnyMorganz/luau-lsp#1246.
Autocomplete
- Do not recommend generic types for anonymous functions being passed as arguments
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Annie Tang annietang@roblox.com
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
0.699
Hello all! Another week, another release!
Analysis
- Fixed
table.clonein the old solver to ensure intersections of tables were being entirely cloned: prior only the first table in the intersection would be copied:
type FIRST = { some: string }
type SECOND = FIRST & { thing: string }
local b: SECOND
-- c's type used to be FIRST, but should be the full type of SECOND
local c = table.clone(b)- Fixed
table.clonein the old solver to be more permissive and treat a variadic return as having at least one element. This works around some unfortunate behavior in the old solver version of nonstrict mode, see:
-- A.luau
--!nonstrict
return function()
return {}
end
-- B.luau
local A = require("A")
-- This line would previously error as `A` has type `() -> (...any)`, so
-- we might not be providing enough parameters to `table.clone`.
local _ = table.clone(A())- Fixed a bug in the new solver where error suppression was not kicking in for indexing, as in:
local function f(value: any)
if value ~= nil then
for k = 1, #value do
-- Previously this would error, claiming you cannot index into a `*error-type* | ~nil`
local _ = value[k]
end
end
end- Fix the
getmetatabletype function in the new solver to accept*error-type*andtableas valid type inputs. - Changed how error reporting for invalid
for ... inloops works: for now this may result in slightly worse error messages (see the example below), but should mean error suppression is more consistent going forward:
function my_iter(state: string, index: number)
return state, index
end
local my_state = {}
local first_index = "first"
-- Prior we would claim `my_state` and `first_index` are of the incorrect types,
-- now we claim that `my_iter` is of the incorrect type, which can be considered
-- true, but is less helpful.
for a, b in my_iter, my_state, first_index do
endRuntime
- Introduced
lua_rawgetptaggedandlua_rawsetptagged, as well as Lua 5.2+ compatibility macroslua_rawgetpandlua_rawsetp, to be able to perform lookups into tables using tagged or untaggedlightuserdatawithout additional calls and stack manipulation. This enables a more efficient lookup way forlightuserdatakeys similar to howlua_rawgetfieldandlua_rawgetiavoid extra operations for their corresponding types.
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Annie Tang annietang@roblox.com
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com
0.698
Another week, another release. Happy Halloween! 🎃
Require
- Integrate support for
.config.luaufiles intoLuau.Requireas part of the Luau-syntax configuration files RFC.is_config_presenthas been replaced withget_config_status.get_luau_config_timeouthas been added to configure extraction timeouts at runtime.
- Enable support for
.config.luaufiles inluauandluau-analyze. - Merge the
Luau.RequireNavigatorstatic library intoLuau.Require.
Analysis
- Add fuel-based limits for normalization: normalization will now take a set number of steps (the "fuel") and stop when we hit a certain number of steps ("run out of fuel"). This is in lieu of trying to check static limits on the size of its inputs. This may result in seeing more "code too complex" errors but should dramatically reduce the number of cases where Luau becomes unresponsive and uses several gigabytes of memory. We plan to tune this limit over time to find the right balance between responsiveness and completeness.
- Fix a case where refining a variable with the type
anywould cause it to becomeunknowninstead due to normalization not preservinganyin the top type position. - Improve the wording of type errors in the new non-strict mode.
- Fix #1910.
- Fix #2065.
- Fix #1483.
- Fix #2018.
Miscellaneous
- Introduce
Luau::overloadedto facilitate interacting withLuau::Variant. - Add type checking support to the Luau demo!
Open-source contributions
- Use enum and struct keywords for Luau.Require header by @Jan200101 in #2060
- Remove NBSP from Require.h by @SeyedAlirezaFatemi in #2067
New Contributors
- @SeyedAlirezaFatemi made their first contribution in #2067
Full Changelog: 0.697...0.698
Co-authored-by: Annie Tang annietang@roblox.com
Co-authored-by: Ariel Weiss arielweiss@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Ilya Rezvov irezvov@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
0.697
Another somewhat small release as we work our way up to the next stage of the new type solver!
General
- Implement configuration extraction as per the Luau-syntax configuration files RFC: we now expose a low-level
extractConfigAPI and a higher levelextractLuauConfigAPI for extracting configurations from these files. The runtime and analysis integrations withrequire, for this feature, are coming in a later release.
Analysis
- Implemented native stack guards: on Windows and MacOS spots where we attempt to guard against stack overflows by using a counter now also check whether we are close to hitting the runtime stack limit via OS specific APIs.
- Fix a performance issue that could occur when trying to reduce type functions for math operations in the new solver, causing the new solver to fail to solve all constraints and take a disproportionate amount of time to finish solving.
- Improve the new solver's non-strict checking performance when checking exceptionally large function calls and function definitions.
Full Changelog: 0.696...0.697
Co-authored-by: Andy Friesen afriesen@roblox.com
Co-authored-by: Hunter Goldstein hgoldstein@roblox.com
Co-authored-by: Sora Kanosue skanosue@roblox.com
Co-authored-by: Varun Saini vsaini@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com