Skip to content

Commit c33adf1

Browse files
authored
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.
1 parent c836feb commit c33adf1

File tree

123 files changed

+9782
-2552
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+9782
-2552
lines changed

Analysis/include/Luau/BuiltinTypeFunctions.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ struct BuiltinTypeFunctions
3333

3434
TypeFunction ltFunc;
3535
TypeFunction leFunc;
36-
TypeFunction eqFunc;
3736

3837
TypeFunction refineFunc;
3938
TypeFunction singletonFunc;

Analysis/include/Luau/ConstraintGenerator.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ struct InferencePack
5858
}
5959
};
6060

61+
struct Checkpoint
62+
{
63+
size_t offset = 0;
64+
};
65+
6166
struct ConstraintGenerator
6267
{
6368
// A list of all the scopes in the module. This vector holds ownership of the
@@ -290,6 +295,13 @@ struct ConstraintGenerator
290295
);
291296

292297
InferencePack checkPack(const ScopePtr& scope, AstExprCall* call);
298+
InferencePack checkExprCall(
299+
const ScopePtr& scope,
300+
AstExprCall* call,
301+
TypeId fnType,
302+
Checkpoint funcBeginCheckpoint,
303+
Checkpoint funcEndCheckpoint
304+
);
293305

294306
/**
295307
* Checks an expression that is expected to evaluate to one type.

Analysis/include/Luau/FileResolver.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ struct ModuleInfo
3636

3737
struct RequireAlias
3838
{
39+
explicit RequireAlias(std::string alias)
40+
: alias(std::move(alias))
41+
{
42+
}
43+
3944
std::string alias; // Unprefixed alias name (no leading `@`).
4045
std::vector<std::string> tags = {};
4146
};
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2+
#pragma once
3+
4+
#include "Luau/Type.h"
5+
#include "Luau/TypePack.h"
6+
#include "Luau/Set.h"
7+
8+
#include <string>
9+
10+
namespace Luau
11+
{
12+
13+
struct IterativeTypeVisitor
14+
{
15+
using SeenSet = Set<const void*>;
16+
17+
// We avoid Luau::Variant here because we can move the tag bit and make this struct 64 bits shorter.
18+
struct WorkItem
19+
{
20+
WorkItem(TypeId ty, int32_t parent);
21+
WorkItem(TypePackId tp, int32_t parent);
22+
23+
const TypeId* asType() const;
24+
const TypePackId* asTypePack() const;
25+
26+
bool operator==(TypeId ty) const;
27+
bool operator==(TypePackId tp) const;
28+
29+
private:
30+
// TypeId if isType, else TypePackId
31+
const void* t;
32+
bool isType;
33+
34+
public:
35+
// -1 indicates no parent
36+
int32_t parent;
37+
};
38+
39+
explicit IterativeTypeVisitor(std::string visitorName, bool skipBoundTypes);
40+
explicit IterativeTypeVisitor(std::string visitorName, bool visitOnce, bool skipBoundTypes);
41+
explicit IterativeTypeVisitor(std::string visitorName, SeenSet seen, bool visitOnce, bool skipBoundTypes);
42+
43+
IterativeTypeVisitor(const IterativeTypeVisitor&) = delete;
44+
IterativeTypeVisitor& operator=(const IterativeTypeVisitor&) = delete;
45+
46+
virtual ~IterativeTypeVisitor() = default;
47+
48+
virtual void cycle(TypeId);
49+
virtual void cycle(TypePackId);
50+
51+
virtual bool visit(TypeId ty);
52+
virtual bool visit(TypeId ty, const BoundType& btv);
53+
virtual bool visit(TypeId ty, const FreeType& ftv);
54+
virtual bool visit(TypeId ty, const GenericType& gtv);
55+
virtual bool visit(TypeId ty, const ErrorType& etv);
56+
virtual bool visit(TypeId ty, const PrimitiveType& ptv);
57+
virtual bool visit(TypeId ty, const FunctionType& ftv);
58+
virtual bool visit(TypeId ty, const TableType& ttv);
59+
virtual bool visit(TypeId ty, const MetatableType& mtv);
60+
virtual bool visit(TypeId ty, const ExternType& etv);
61+
virtual bool visit(TypeId ty, const AnyType& atv);
62+
virtual bool visit(TypeId ty, const NoRefineType& nrt);
63+
virtual bool visit(TypeId ty, const UnknownType& utv);
64+
virtual bool visit(TypeId ty, const NeverType& ntv);
65+
virtual bool visit(TypeId ty, const UnionType& utv);
66+
virtual bool visit(TypeId ty, const IntersectionType& itv);
67+
virtual bool visit(TypeId ty, const BlockedType& btv);
68+
virtual bool visit(TypeId ty, const PendingExpansionType& petv);
69+
virtual bool visit(TypeId ty, const SingletonType& stv);
70+
virtual bool visit(TypeId ty, const NegationType& ntv);
71+
virtual bool visit(TypeId ty, const TypeFunctionInstanceType& tfit);
72+
73+
virtual bool visit(TypePackId tp);
74+
virtual bool visit(TypePackId tp, const BoundTypePack& btp);
75+
virtual bool visit(TypePackId tp, const FreeTypePack& ftp);
76+
virtual bool visit(TypePackId tp, const GenericTypePack& gtp);
77+
virtual bool visit(TypePackId tp, const ErrorTypePack& etp);
78+
virtual bool visit(TypePackId tp, const TypePack& pack);
79+
virtual bool visit(TypePackId tp, const VariadicTypePack& vtp);
80+
virtual bool visit(TypePackId tp, const BlockedTypePack& btp);
81+
virtual bool visit(TypePackId tp, const TypeFunctionInstanceTypePack& tfitp);
82+
83+
void run(TypeId ty);
84+
void run(TypePackId tp);
85+
86+
protected:
87+
/// Add this type (or pack) to the queue of things to traverse. Does not
88+
/// immediately process the thing! You cannot use this to effect in-order
89+
/// traversal.
90+
void traverse(TypeId ty);
91+
void traverse(TypePackId tp);
92+
93+
private:
94+
void process(TypeId ty);
95+
void process(TypePackId tp);
96+
97+
bool hasSeen(const void* tv);
98+
void unsee(const void* tv);
99+
100+
template<typename TID>
101+
bool isCyclic(TID ty) const;
102+
103+
void processWorkQueue();
104+
105+
SeenSet seen{nullptr};
106+
107+
std::vector<WorkItem> workQueue;
108+
int32_t parentCursor = -1;
109+
uint32_t workCursor = 0;
110+
111+
const std::string visitorName;
112+
bool skipBoundTypes = false;
113+
bool visitOnce = true;
114+
};
115+
116+
} // namespace Luau

Analysis/include/Luau/Normalize.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,9 @@ class Normalizer
355355

356356
std::optional<TypePackId> intersectionOfTypePacks(TypePackId here, TypePackId there);
357357

358-
// Move to private with LuauNormalizerStepwiseFuel
358+
private:
359359
std::optional<TypePackId> intersectionOfTypePacks_INTERNAL(TypePackId here, TypePackId there);
360360

361-
private:
362361
// ------- Cached TypeIds
363362
TypeId unionType(TypeId here, TypeId there);
364363
TypeId intersectionType(TypeId here, TypeId there);

Analysis/include/Luau/OverloadResolution.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ using IncompatibilityReason = Variant<SubtypingReasonings, ErrorVec>;
4242
*/
4343
struct SelectedOverload
4444
{
45-
/**
45+
/**
4646
* An unambiguous overload, if one can be selected. This is _not_ necessarily
4747
* an overload that is valid for the argument pack provided. For example:
4848
*
@@ -302,7 +302,8 @@ struct SolveResult
302302
// Helper utility, presently used for binary operator type functions.
303303
//
304304
// Given a function and a set of arguments, select a suitable overload.
305-
SolveResult solveFunctionCall(
305+
// Clip with FFlag::LuauBuiltinTypeFunctionsUseNewOverloadResolution
306+
SolveResult solveFunctionCall_DEPRECATED(
306307
NotNull<TypeArena> arena,
307308
NotNull<BuiltinTypes> builtinTypes,
308309
NotNull<Normalizer> normalizer,

Analysis/include/Luau/Set.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Set
2626
class const_iterator;
2727
using iterator = const_iterator;
2828

29-
Set(const T& empty_key)
29+
explicit Set(const T& empty_key)
3030
: mapping{empty_key}
3131
{
3232
}

Analysis/include/Luau/Subtyping.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ struct Subtyping
298298
const SingletonType* superSingleton,
299299
NotNull<Scope> scope
300300
);
301-
SubtypingResult isCovariantWith(SubtypingEnvironment& env, const TableType* subTable, const TableType* superTable, NotNull<Scope> scope);
302301
SubtypingResult isCovariantWith(
303302
SubtypingEnvironment& env,
304303
const TableType* subTable,

Analysis/include/Luau/TypeChecker2.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
#include "Luau/Subtyping.h"
1010
#include "Luau/Type.h"
1111
#include "Luau/TypeFwd.h"
12-
#include "Luau/TypeOrPack.h"
1312
#include "Luau/TypeUtils.h"
1413

14+
LUAU_FASTFLAG(LuauBetterTypeMismatchErrors)
15+
1516
namespace Luau
1617
{
1718

@@ -44,7 +45,7 @@ struct Reasonings
4445
// sort the reasons here to achieve a stable error
4546
// stringification.
4647
std::sort(reasons.begin(), reasons.end());
47-
std::string allReasons = "\nthis is because ";
48+
std::string allReasons = (FFlag::LuauBetterTypeMismatchErrors && reasons.size() < 2) ? "\n" : "\nthis is because ";
4849
for (const std::string& reason : reasons)
4950
{
5051
if (reasons.size() > 1)

Analysis/src/AstJsonEncoder.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
#include <math.h>
1010

11-
LUAU_FASTFLAG(LuauAutocompleteAttributes)
12-
1311
namespace Luau
1412
{
1513

@@ -1167,10 +1165,7 @@ struct AstJsonEncoder : public AstVisitor
11671165
"AstAttr",
11681166
[&]()
11691167
{
1170-
if (FFlag::LuauAutocompleteAttributes)
1171-
write("name", node->name);
1172-
else
1173-
write("name", node->type);
1168+
write("name", node->name);
11741169
}
11751170
);
11761171
}

0 commit comments

Comments
 (0)