Skip to content

Sync to upstream/release/740 - #2990

Merged
hgoldstein merged 119 commits into
masterfrom
merge
Sep 25, 2026
Merged

hgoldstein merged 119 commits into
masterfrom
merge

Conversation

@hgoldstein

Copy link
Copy Markdown
Contributor

Language

  • Introducing an experimental feature to make tables "exact" by default. See RFC: Exact Table Types rfcs#11 for full details, but the gist is to differentiate between tables that may have extraneous fields and tables that do not. We believe that this behavior better aligns with user expectations, and allows us to make the type system more predictable.
-- This table may have extra fields
type Inexact = { x: number, y: number, ... }
-- This table _does not_ have extra fields
type Exact = { x: number, y: number }

local _: Inexact = { x = 3, y = 4, foo = "spooky" } -- OK!
local _: Exact = { x = 3, y = 4, foo = "spooky" } -- Not OK!
  • if local is still experimental but is moving closer to a full release.

Analysis

  • Removed Luau::Set, now entirely subsumed by the new DenseHashSet implementation.
  • Fixed an internal error that could occur when processing exceptionally large types ("Internal recursion counter limit exceeded in ReferenceCountInitializer").
  • Fixed a bug in function normalization that meant we'd use argument types as return types:
function g(x : (() -> string | number) & (() -> number | boolean))
    local z : () -> () = x -- This should not be allowed
end

Runtime

  • Fixed an issue where OOMing during table re-hashing or freezing could leave the underlying table in an unexpected state.
  • When dumping bytecode, upvalues are now prefixed with U
  • Fixed integer.idiv(x, y) not being floored in some configurations, resulting in differing behavior across the interpreter, NCG backends, and constant folding.

Co-authored-by: Andreas Haeberlen andreas.haeberlen@roblox.com
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: Thomas Schollenberger tschollenberger@roblox.com
Co-authored-by: Vighnesh Vijay vvijay@roblox.com
Co-authored-by: Vyacheslav Egorov vegorov@roblox.com

annieetang and others added 24 commits August 14, 2026 09:21
Howdy folks! Welcome to a somewhat language feature heavy Luau update!

* Introducing an experimental feature to make tables "exact" by default. See luau-lang/rfcs#11 for full details, but the gist is to differentiate between tables that may have extraneous fields and tables that do not. We believe that this behavior better aligns with user expectations, and allows us to make the type system more predictable.
```luau
-- This table may have extra fields
type Inexact = { x: number, y: number, ... }
-- This table _does not_ have extra fields
type Exact = { x: number, y: number }

local _: Inexact = { x = 3, y = 4, foo = "spooky" } -- OK!
local _: Exact = { x = 3, y = 4, foo = "spooky" } -- Not OK!
```
* `if local` **is still experimental** but is moving closer to a full release.

* Removed `Luau::Set`, now entirely subsumed by the new `DenseHashSet` implementation.
* Fixed an internal error that could occur when processing exceptionally large types ("Internal recursion counter limit exceeded in ReferenceCountInitializer").
* Fixed a bug in function normalization that meant we'd use argument types as return types:
```luau
function g(x : (() -> string | number) & (() -> number | boolean))
    local z : () -> () = x -- This should not be allowed
end
```

* Fixed an issue where OOMing during table re-hashing or freezing could leave the underlying table in an unexpected state.
* When dumping bytecode, upvalues are now prefixed with `U`
* Fixed `integer.idiv(x, y)` not being floored in some configurations, resulting in differing behavior across the interpreter, NCG backends, and constant folding.

Co-authored-by: Andreas Haeberlen <andreas.haeberlen@roblox.com>
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: Thomas Schollenberger <tschollenberger@roblox.com>
Co-authored-by: Vighnesh Vijay <vvijay@roblox.com>
Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
return here;

if (get<NeverType>(here))
return there;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem quite right to me, it reads like never & t == t.

@hgoldstein hgoldstein Sep 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also agree, though I can see that this exact block is in the old implementation; frankly this method has really confusing preconditions (we expect here and there to be ... I think always tables or any?), so we'll get back to y'all on this one.

@hgoldstein
hgoldstein marked this pull request as ready for review September 25, 2026 18:10
@hgoldstein
hgoldstein requested a review from a team as a code owner September 25, 2026 18:10
@hgoldstein
hgoldstein merged commit c0e346e into master Sep 25, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants