Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Tags: luau-lang/luau

Tags

0.704

Toggle 0.704's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/704 (#2180)

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:
```luau
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:
```luau
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:
```luau
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)
```luau
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:
```luau
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](https://rfcs.luau.org/recursive-type-restriction.html).
```luau
-- 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
```luau
-- 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

# Internal Contributors

Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Annie Tang <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Vighnesh Vijay <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

0.703

Toggle 0.703's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/703 (#2146)

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:
```luau
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 improved: instead of talking
about "X could not be converted into Y," we talk about "expecting X" but
"getting Y."
* Builtin type functions now use improved logic for overload resolution.
* Type annotations on for-in loops are now respected, for example:
```luau
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:
```luau
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:
```luau
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:
```luau
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.
```luau
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:
```luau
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 a bug where NCG 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.

0.702

Toggle 0.702's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/702 (#2126)

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 <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Sora Kanosue <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

---------

Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Alexander Youngblood <[email protected]>
Co-authored-by: Menarul Alam <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: Vighnesh <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Ilya Rezvov <[email protected]>

0.701

Toggle 0.701's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/701 (#2099)

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](https://rfcs.luau.org/math-isnan-isfinite-isinf.html) RFC and
long awaited [Explicit type parameter
instantiation](https://rfcs.luau.org/explicit-type-parameter-instantiation.html)
RFC!

### 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
```luau
--!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 in it

## Internal Contributors

Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Annie Tang <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Ilya Rezvov <[email protected]>
Co-authored-by: Sora Kanosue <[email protected]>
Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

0.700

Toggle 0.700's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Infra: validate version format before creating draft release (#2091)

This should help us catch the (somewhat common) case where a release
gets tagged `xyz` instead of `0.xyz`.

0.699

Toggle 0.699's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/699 (#2082)

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:
```luau
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:
```luau
-- 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:
```luau
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:
```luau
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 <[email protected]>
Co-authored-by: Annie Tang <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

---------

Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Alexander Youngblood <[email protected]>
Co-authored-by: Menarul Alam <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: Vighnesh <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>

0.698

Toggle 0.698's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/698 (#2070)

# General

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](https://rfcs.luau.org/config-luauconfig.html).
  - `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](https://luau.org/demo)!

---

Co-authored-by: Annie Tang <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Ilya Rezvov <[email protected]>
Co-authored-by: Sora Kanosue <[email protected]>
Co-authored-by: Varun Saini <[email protected]>

0.697

Toggle 0.697's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/697 (#2058)

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](https://github.com/luau-lang/rfcs/blob/master/docs/config-luauconfig.md):
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.

---------

Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Alexander Youngblood <[email protected]>
Co-authored-by: Menarul Alam <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: Vighnesh <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
Co-authored-by: Ariel Weiss <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>

696

Toggle 696's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/696 (#2050)

Hey everyone. In preparation for the next phase of the New Type Solver
rollout, we have another round of important bugfixes.

We've also got a few improvements to the new require alias machinery and
a little optimization to native codegen.

## New Type Solver

* Fix a case where Luau would erroneously simplify `{} & { p: number |
string }` to `number`.
* Fix a crash that could occur within generic substitution. TODO: Sora
to help word this.
* Fix a case where Luau would infer a spurious union type as the result
of a `setmetatable` call.
* Fix #1803
* Improve bidirectional inference of table literals in the case that the
expected type has an indexer.

## Luau.Require

* Zero-initialize `luarequire_Configuration` function pointers before
user initialization
* Error if ambiguity is detected during alias discovery

## Native Codegen

* Do not replace known constant value with a load propagation in
STORE_TVALUE

---------

Co-authored-by: Annie Tang <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Sora Kanosue <[email protected]>
Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

0.696

Toggle 0.696's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Sync to upstream/release/696 (#2050)

Hey everyone. In preparation for the next phase of the New Type Solver
rollout, we have another round of important bugfixes.

We've also got a few improvements to the new require alias machinery and
a little optimization to native codegen.

## New Type Solver

* Fix a case where Luau would erroneously simplify `{} & { p: number |
string }` to `number`.
* Fix a crash that could occur within generic substitution. TODO: Sora
to help word this.
* Fix a case where Luau would infer a spurious union type as the result
of a `setmetatable` call.
* Fix #1803
* Improve bidirectional inference of table literals in the case that the
expected type has an indexer.

## Luau.Require

* Zero-initialize `luarequire_Configuration` function pointers before
user initialization
* Error if ambiguity is detected during alias discovery

## Native Codegen

* Do not replace known constant value with a load propagation in
STORE_TVALUE

---------

Co-authored-by: Annie Tang <[email protected]>
Co-authored-by: Hunter Goldstein <[email protected]>
Co-authored-by: Sora Kanosue <[email protected]>
Co-authored-by: Varun Saini <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>