Skip to content

Releases: luau-lang/luau

0.706

23 Jan 18:40
Immutable release. Only release title and notes can be modified.
416fc1a

Choose a tag to compare

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 ToStringResult to support decomposition #2163
  • Expose luaL_traceback from 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

16 Jan 23:41
Immutable release. Only release title and notes can be modified.
93c83a4

Choose a tag to compare

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 | false is the same as boolean).
    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.cpp to disable the use of synthetic names, which can be used to improve the quality of hover type.
    • Fixes a bug where table.freeze would incorrectly error on arguments of any type (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 findBindingAtPosition that 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 any or *error-type* or directly downstream of an existing type error.
    • This release removes the experimental DebugLuauStringSingletonBasedOnQuotes flag 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.

Native Code Generation

  • Fixes a crash in getOffsetBase when 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 vector equality 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_FLOAT to replace instances where we needed to emit UINT_TO_NUM and NUM_TO_FLOAT paired 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.clock in 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_top that 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

New Contributors

Full Changelog: 0.704...0.705

0.704

09 Jan 20:03
Immutable release. Only release title and notes can be modified.
dc955d6

Choose a tag to compare

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 pcall and 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

  • vector library 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.create constructor 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.sin and 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_UINT which could cause a lowering failure under 'LuauCodegenNumIntFolds2' flag

Autocomplete

  • Fixed a crash when indexing write-only properties

Open-source contributions

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

12 Dec 20:12
Immutable release. Only release title and notes can be modified.
c33adf1

Choose a tag to compare

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.unionof and types.intersectionof will now attempt to simplify their arguments, avoiding producing nested intersections and unions, as well as removing identity types like never and unknown.
  • The setmetatable type 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 42 to 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 and and or without 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,10 would be optimized and i = 1,#t would not be.

Require

  • Added a to_alias_override callback: 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

02 Dec 23:27
Immutable release. Only release title and notes can be modified.
c836feb

Choose a tag to compare

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 a TypeId from 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.char and string.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

21 Nov 20:35
Immutable release. Only release title and notes can be modified.
535f925

Choose a tag to compare

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_fallback C API to natively support host-injected aliases
  • Fixed building fuzzers using make
  • Fixed serialization of userdata type mappings from userdataTypes compiler 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 unknown type 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
end

Runtime

  • 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

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

14 Nov 23:11
Immutable release. Only release title and notes can be modified.
3e1c94e

Choose a tag to compare

We have reached release 700!

Analysis

  • table.isfrozen and table.clear use {} instead of generic table type to make it work with union of table types.
  • Relax typing definitions for types.newtable to 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::resolveOverload was introduced to abstract and unify existing resolving machinery.
  • instantiation2 selects 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 never or unknown, 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.cpp for an example.

Require

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

07 Nov 20:22
Immutable release. Only release title and notes can be modified.
994b641

Choose a tag to compare

Hello all! Another week, another release!

Analysis

  • Fixed table.clone in 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.clone in 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 getmetatable type function in the new solver to accept *error-type* and table as valid type inputs.
  • Changed how error reporting for invalid for ... in loops 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
end

Runtime

  • Introduced lua_rawgetptagged and lua_rawsetptagged, as well as Lua 5.2+ compatibility macros lua_rawgetp and lua_rawsetp, to be able to perform lookups into tables using tagged or untagged lightuserdata without additional calls and stack manipulation. This enables a more efficient lookup way for lightuserdata keys similar to how lua_rawgetfield and lua_rawgeti avoid 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

31 Oct 04:32
Immutable release. Only release title and notes can be modified.
ff6d381

Choose a tag to compare

Another week, another release. Happy Halloween! 🎃

Require

  • Integrate support for .config.luau files into Luau.Require as part of the Luau-syntax configuration files RFC.
    • is_config_present has been replaced with get_config_status.
    • get_luau_config_timeout has been added to configure extraction timeouts at runtime.
  • Enable support for .config.luau files in luau and luau-analyze.
  • Merge the Luau.RequireNavigator static library into Luau.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 any would cause it to become unknown instead due to normalization not preserving any in 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::overloaded to facilitate interacting with Luau::Variant.
  • Add type checking support to the Luau demo!

Open-source contributions

New Contributors

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

24 Oct 20:34
Immutable release. Only release title and notes can be modified.
5836a9c

Choose a tag to compare

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 extractConfig API and a higher level extractLuauConfig API for extracting configurations from these files. The runtime and analysis integrations with require, 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