Skip to content

Commit a251bc6

Browse files
andyfriesenaatxealexmccordVighnesh-Vaviralg
authored
Sync to upstream/release/650 (#1502)
* New `vector` library! See https://rfcs.luau.org/vector-library.html for details * Replace the use of non-portable `strnlen` with `memchr`. `strnlen` is not part of any C or C++ standard. * Introduce `lua_newuserdatataggedwithmetatable` for faster tagged userdata creation of userdata with metatables registered with `lua_setuserdatametatable` Old Solver * It used to be the case that a module's result type would unconditionally be inferred to be `any` if it imported any module that participates in any import cycle. This is now fixed. New Solver * Improve inference of `table.freeze`: We now infer read-only properties on tables after they have been frozen. * We now correctly flag cases where `string.format` is called with 0 arguments. * Fix a bug in user-defined type functions where table properties could be lost if the table had a metatable * Reset the random number seed for each evaluation of a type function * We now retry subtyping arguments if it failed due to hidden variadics. --------- Co-authored-by: Aaron Weiss <[email protected]> Co-authored-by: Alexander McCord <[email protected]> Co-authored-by: Vighnesh <[email protected]> Co-authored-by: Aviral Goel <[email protected]> Co-authored-by: David Cope <[email protected]> Co-authored-by: Lily Brown <[email protected]> Co-authored-by: Vyacheslav Egorov <[email protected]> Co-authored-by: Junseo Yoo <[email protected]>
1 parent db80939 commit a251bc6

File tree

86 files changed

+2217
-407
lines changed

Some content is hidden

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

86 files changed

+2217
-407
lines changed

Analysis/include/Luau/TypeFunctionRuntime.h

+2
Original file line numberDiff line numberDiff line change
@@ -265,4 +265,6 @@ void registerTypeUserData(lua_State* L);
265265

266266
void setTypeFunctionEnvironment(lua_State* L);
267267

268+
void resetTypeFunctionState(lua_State* L);
269+
268270
} // namespace Luau

Analysis/src/AnyTypeSummary.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
#include <stdio.h>
4040

41-
LUAU_FASTFLAGVARIABLE(StudioReportLuauAny2, false);
41+
LUAU_FASTFLAGVARIABLE(StudioReportLuauAny2);
4242
LUAU_FASTINTVARIABLE(LuauAnySummaryRecursionLimit, 300);
4343

4444
LUAU_FASTFLAG(DebugLuauMagicTypes);
@@ -161,7 +161,7 @@ void AnyTypeSummary::visit(const Scope* scope, AstStatReturn* ret, const Module*
161161
typeInfo.push_back(ti);
162162
}
163163
}
164-
164+
165165
if (ret->list.size > 1 && !seenTP)
166166
{
167167
if (containsAny(retScope->returnType))

Analysis/src/AstQuery.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
LUAU_FASTFLAG(LuauSolverV2)
1515

16-
LUAU_FASTFLAGVARIABLE(LuauDocumentationAtPosition, false)
16+
LUAU_FASTFLAGVARIABLE(LuauDocumentationAtPosition)
1717

1818
namespace Luau
1919
{

Analysis/src/Autocomplete.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <utility>
1717

1818
LUAU_FASTFLAG(LuauSolverV2)
19-
LUAU_FASTFLAGVARIABLE(AutocompleteRequirePathSuggestions, false)
19+
LUAU_FASTFLAGVARIABLE(AutocompleteRequirePathSuggestions)
2020

2121
LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
2222
LUAU_FASTINT(LuauTypeInferIterationLimit)

Analysis/src/BuiltinDefinitions.cpp

+64-31
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "Luau/Ast.h"
55
#include "Luau/Clone.h"
6+
#include "Luau/DenseHash.h"
67
#include "Luau/Error.h"
78
#include "Luau/Frontend.h"
89
#include "Luau/Symbol.h"
@@ -29,8 +30,8 @@
2930

3031
LUAU_FASTFLAG(LuauSolverV2)
3132
LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
32-
LUAU_FASTFLAGVARIABLE(LuauTypestateBuiltins, false)
33-
LUAU_FASTFLAGVARIABLE(LuauStringFormatArityFix, false)
33+
LUAU_FASTFLAGVARIABLE(LuauTypestateBuiltins2)
34+
LUAU_FASTFLAGVARIABLE(LuauStringFormatArityFix)
3435

3536
LUAU_FASTFLAG(AutocompleteRequirePathSuggestions)
3637

@@ -421,7 +422,7 @@ void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeC
421422

422423
attachMagicFunction(ttv->props["pack"].type(), magicFunctionPack);
423424
attachDcrMagicFunction(ttv->props["pack"].type(), dcrMagicFunctionPack);
424-
if (FFlag::LuauTypestateBuiltins)
425+
if (FFlag::LuauTypestateBuiltins2)
425426
attachDcrMagicFunction(ttv->props["freeze"].type(), dcrMagicFunctionFreeze);
426427
}
427428

@@ -1338,54 +1339,86 @@ static bool dcrMagicFunctionPack(MagicFunctionCallContext context)
13381339
return true;
13391340
}
13401341

1342+
static std::optional<TypeId> freezeTable(TypeId inputType, MagicFunctionCallContext& context)
1343+
{
1344+
TypeArena* arena = context.solver->arena;
1345+
1346+
if (auto mt = get<MetatableType>(inputType))
1347+
{
1348+
std::optional<TypeId> frozenTable = freezeTable(mt->table, context);
1349+
1350+
if (!frozenTable)
1351+
return std::nullopt;
1352+
1353+
TypeId resultType = arena->addType(MetatableType{*frozenTable, mt->metatable, mt->syntheticName});
1354+
1355+
return resultType;
1356+
}
1357+
1358+
if (get<TableType>(inputType))
1359+
{
1360+
// Clone the input type, this will become our final result type after we mutate it.
1361+
CloneState cloneState{context.solver->builtinTypes};
1362+
TypeId resultType = shallowClone(inputType, *arena, cloneState);
1363+
auto tableTy = getMutable<TableType>(resultType);
1364+
// `clone` should not break this.
1365+
LUAU_ASSERT(tableTy);
1366+
tableTy->state = TableState::Sealed;
1367+
1368+
// We'll mutate the table to make every property type read-only.
1369+
for (auto iter = tableTy->props.begin(); iter != tableTy->props.end();)
1370+
{
1371+
if (iter->second.isWriteOnly())
1372+
iter = tableTy->props.erase(iter);
1373+
else
1374+
{
1375+
iter->second.writeTy = std::nullopt;
1376+
iter++;
1377+
}
1378+
}
1379+
1380+
return resultType;
1381+
}
1382+
1383+
context.solver->reportError(TypeMismatch{context.solver->builtinTypes->tableType, inputType}, context.callSite->argLocation);
1384+
return std::nullopt;
1385+
}
1386+
13411387
static bool dcrMagicFunctionFreeze(MagicFunctionCallContext context)
13421388
{
1343-
LUAU_ASSERT(FFlag::LuauTypestateBuiltins);
1389+
LUAU_ASSERT(FFlag::LuauTypestateBuiltins2);
13441390

13451391
TypeArena* arena = context.solver->arena;
13461392
const DataFlowGraph* dfg = context.solver->dfg.get();
13471393
Scope* scope = context.constraint->scope.get();
13481394

13491395
const auto& [paramTypes, paramTail] = extendTypePack(*arena, context.solver->builtinTypes, context.arguments, 1);
1350-
LUAU_ASSERT(paramTypes.size() >= 1);
1351-
1352-
TypeId inputType = follow(paramTypes.at(0));
1353-
1354-
// we'll check if it's a table first since this magic function also produces the error if it's not until we have bounded generics
1355-
if (!get<TableType>(inputType))
1396+
if (paramTypes.empty() || context.callSite->args.size == 0)
13561397
{
1357-
context.solver->reportError(TypeMismatch{context.solver->builtinTypes->tableType, inputType}, context.callSite->argLocation);
1398+
context.solver->reportError(CountMismatch{1, std::nullopt, 0}, context.callSite->argLocation);
13581399
return false;
13591400
}
13601401

1402+
TypeId inputType = follow(paramTypes[0]);
1403+
13611404
AstExpr* targetExpr = context.callSite->args.data[0];
13621405
std::optional<DefId> resultDef = dfg->getDefOptional(targetExpr);
13631406
std::optional<TypeId> resultTy = resultDef ? scope->lookup(*resultDef) : std::nullopt;
13641407

1365-
// Clone the input type, this will become our final result type after we mutate it.
1366-
CloneState cloneState{context.solver->builtinTypes};
1367-
TypeId clonedType = shallowClone(inputType, *arena, cloneState);
1368-
auto tableTy = getMutable<TableType>(clonedType);
1369-
// `clone` should not break this.
1370-
LUAU_ASSERT(tableTy);
1371-
tableTy->state = TableState::Sealed;
1372-
tableTy->syntheticName = std::nullopt;
1373-
1374-
// We'll mutate the table to make every property type read-only.
1375-
for (auto iter = tableTy->props.begin(); iter != tableTy->props.end();)
1408+
std::optional<TypeId> frozenType = freezeTable(inputType, context);
1409+
1410+
if (!frozenType)
13761411
{
1377-
if (iter->second.isWriteOnly())
1378-
iter = tableTy->props.erase(iter);
1379-
else
1380-
{
1381-
iter->second.writeTy = std::nullopt;
1382-
iter++;
1383-
}
1412+
if (resultTy)
1413+
asMutable(*resultTy)->ty.emplace<BoundType>(context.solver->builtinTypes->errorType);
1414+
asMutable(context.result)->ty.emplace<BoundTypePack>(context.solver->builtinTypes->errorTypePack);
1415+
1416+
return true;
13841417
}
13851418

13861419
if (resultTy)
1387-
asMutable(*resultTy)->ty.emplace<BoundType>(clonedType);
1388-
asMutable(context.result)->ty.emplace<BoundTypePack>(arena->addTypePack({clonedType}));
1420+
asMutable(*resultTy)->ty.emplace<BoundType>(*frozenType);
1421+
asMutable(context.result)->ty.emplace<BoundTypePack>(arena->addTypePack({*frozenType}));
13891422

13901423
return true;
13911424
}

Analysis/src/ConstraintGenerator.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ LUAU_FASTINT(LuauCheckRecursionLimit)
3131
LUAU_FASTFLAG(DebugLuauLogSolverToJson)
3232
LUAU_FASTFLAG(DebugLuauMagicTypes)
3333
LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
34-
LUAU_FASTFLAG(LuauTypestateBuiltins)
34+
LUAU_FASTFLAG(LuauTypestateBuiltins2)
3535

36-
LUAU_FASTFLAGVARIABLE(LuauNewSolverVisitErrorExprLvalues, false)
36+
LUAU_FASTFLAGVARIABLE(LuauNewSolverVisitErrorExprLvalues)
3737

3838
namespace Luau
3939
{
@@ -1078,7 +1078,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatLocal* stat
10781078
addConstraint(scope, value->location, NameConstraint{*firstValueType, var->name.value, /*synthetic*/ true});
10791079
else if (const AstExprCall* call = value->as<AstExprCall>())
10801080
{
1081-
if (FFlag::LuauTypestateBuiltins)
1081+
if (FFlag::LuauTypestateBuiltins2)
10821082
{
10831083
if (matchSetMetatable(*call))
10841084
addConstraint(scope, value->location, NameConstraint{*firstValueType, var->name.value, /*synthetic*/ true});
@@ -2062,7 +2062,7 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
20622062
return InferencePack{arena->addTypePack({resultTy}), {refinementArena.variadic(returnRefinements)}};
20632063
}
20642064

2065-
if (FFlag::LuauTypestateBuiltins && shouldTypestateForFirstArgument(*call) && call->args.size > 0 && isLValue(call->args.data[0]))
2065+
if (FFlag::LuauTypestateBuiltins2 && shouldTypestateForFirstArgument(*call) && call->args.size > 0 && isLValue(call->args.data[0]))
20662066
{
20672067
AstExpr* targetExpr = call->args.data[0];
20682068
auto resultTy = arena->addType(BlockedType{});
@@ -2913,7 +2913,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr,
29132913
std::vector<TypeId> toBlock;
29142914
if (DFInt::LuauTypeSolverRelease >= 648)
29152915
{
2916-
// This logic is incomplete as we want to re-run this
2916+
// This logic is incomplete as we want to re-run this
29172917
// _after_ blocked types have resolved, but this
29182918
// allows us to do some bidirectional inference.
29192919
toBlock = findBlockedTypesIn(expr, NotNull{&module->astTypes});
@@ -2931,7 +2931,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr,
29312931
toBlock
29322932
);
29332933
// The visitor we ran prior should ensure that there are no
2934-
// blocked types that we would encounter while matching on
2934+
// blocked types that we would encounter while matching on
29352935
// this expression.
29362936
LUAU_ASSERT(toBlock.empty());
29372937
}

Analysis/src/ConstraintSolver.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@
2727
#include <algorithm>
2828
#include <utility>
2929

30-
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolver, false)
31-
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverIncludeDependencies, false)
32-
LUAU_FASTFLAGVARIABLE(DebugLuauLogBindings, false)
30+
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolver)
31+
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverIncludeDependencies)
32+
LUAU_FASTFLAGVARIABLE(DebugLuauLogBindings)
3333
LUAU_FASTINTVARIABLE(LuauSolverRecursionLimit, 500)
3434
LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
35-
LUAU_FASTFLAGVARIABLE(LuauRemoveNotAnyHack, false)
35+
LUAU_FASTFLAGVARIABLE(LuauRemoveNotAnyHack)
3636

3737
namespace Luau
3838
{
@@ -1337,7 +1337,7 @@ bool ConstraintSolver::tryDispatch(const FunctionCheckConstraint& c, NotNull<con
13371337
{
13381338
// This is expensive as we need to traverse a (potentially large)
13391339
// literal up front in order to determine if there are any blocked
1340-
// types, otherwise we may run `matchTypeLiteral` multiple times,
1340+
// types, otherwise we may run `matchTypeLiteral` multiple times,
13411341
// which right now may fail due to being non-idempotent (it
13421342
// destructively updates the underlying literal type).
13431343
auto blockedTypes = findBlockedArgTypesIn(c.callSite, c.astTypes);

Analysis/src/DataFlowGraph.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
LUAU_FASTFLAG(DebugLuauFreezeArena)
1515
LUAU_FASTFLAG(LuauSolverV2)
16-
LUAU_FASTFLAG(LuauTypestateBuiltins)
16+
LUAU_FASTFLAG(LuauTypestateBuiltins2)
1717

1818
namespace Luau
1919
{
@@ -939,7 +939,7 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprCall* c)
939939
{
940940
visitExpr(c->func);
941941

942-
if (FFlag::LuauTypestateBuiltins && shouldTypestateForFirstArgument(*c) && c->args.size > 1 && isLValue(*c->args.begin()))
942+
if (FFlag::LuauTypestateBuiltins2 && shouldTypestateForFirstArgument(*c) && c->args.size > 1 && isLValue(*c->args.begin()))
943943
{
944944
AstExpr* firstArg = *c->args.begin();
945945

Analysis/src/EmbeddedBuiltinDefinitions.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
LUAU_FASTFLAG(LuauMathMap)
55

6+
LUAU_FASTFLAGVARIABLE(LuauVectorDefinitions)
7+
68
namespace Luau
79
{
810

@@ -450,9 +452,39 @@ declare buffer: {
450452
451453
)BUILTIN_SRC";
452454

455+
static const std::string kBuiltinDefinitionVectorSrc = R"BUILTIN_SRC(
456+
457+
-- TODO: this will be replaced with a built-in primitive type
458+
declare class vector end
459+
460+
declare vector: {
461+
create: @checked (x: number, y: number, z: number) -> vector,
462+
magnitude: @checked (vec: vector) -> number,
463+
normalize: @checked (vec: vector) -> vector,
464+
cross: @checked (vec1: vector, vec2: vector) -> vector,
465+
dot: @checked (vec1: vector, vec2: vector) -> number,
466+
angle: @checked (vec1: vector, vec2: vector, axis: vector?) -> number,
467+
floor: @checked (vec: vector) -> vector,
468+
ceil: @checked (vec: vector) -> vector,
469+
abs: @checked (vec: vector) -> vector,
470+
sign: @checked (vec: vector) -> vector,
471+
clamp: @checked (vec: vector, min: vector, max: vector) -> vector,
472+
max: @checked (vector, ...vector) -> vector,
473+
min: @checked (vector, ...vector) -> vector,
474+
475+
zero: vector,
476+
one: vector,
477+
}
478+
479+
)BUILTIN_SRC";
480+
453481
std::string getBuiltinDefinitionSource()
454482
{
455483
std::string result = FFlag::LuauMathMap ? kBuiltinDefinitionLuaSrcChecked : kBuiltinDefinitionLuaSrcChecked_DEPRECATED;
484+
485+
if (FFlag::LuauVectorDefinitions)
486+
result += kBuiltinDefinitionVectorSrc;
487+
456488
return result;
457489
}
458490

Analysis/src/Frontend.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,20 @@ LUAU_FASTINT(LuauTypeInferIterationLimit)
3636
LUAU_FASTINT(LuauTypeInferRecursionLimit)
3737
LUAU_FASTINT(LuauTarjanChildLimit)
3838
LUAU_FASTFLAG(LuauInferInNoCheckMode)
39-
LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3, false)
40-
LUAU_FASTFLAGVARIABLE(LuauStoreCommentsForDefinitionFiles, false)
39+
LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3)
40+
LUAU_FASTFLAGVARIABLE(LuauStoreCommentsForDefinitionFiles)
4141
LUAU_FASTFLAG(LuauSolverV2)
42-
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson, false)
43-
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJsonFile, false)
44-
LUAU_FASTFLAGVARIABLE(DebugLuauForbidInternalTypes, false)
45-
LUAU_FASTFLAGVARIABLE(DebugLuauForceStrictMode, false)
46-
LUAU_FASTFLAGVARIABLE(DebugLuauForceNonStrictMode, false)
47-
LUAU_FASTFLAGVARIABLE(LuauUserDefinedTypeFunctionNoEvaluation, false)
42+
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson)
43+
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJsonFile)
44+
LUAU_FASTFLAGVARIABLE(DebugLuauForbidInternalTypes)
45+
LUAU_FASTFLAGVARIABLE(DebugLuauForceStrictMode)
46+
LUAU_FASTFLAGVARIABLE(DebugLuauForceNonStrictMode)
47+
LUAU_FASTFLAGVARIABLE(LuauUserDefinedTypeFunctionNoEvaluation)
4848
LUAU_DYNAMIC_FASTFLAGVARIABLE(LuauRunCustomModuleChecks, false)
49-
LUAU_FASTFLAGVARIABLE(LuauMoreThoroughCycleDetection, false)
49+
LUAU_FASTFLAGVARIABLE(LuauMoreThoroughCycleDetection)
5050

5151
LUAU_FASTFLAG(StudioReportLuauAny2)
52-
LUAU_FASTFLAGVARIABLE(LuauStoreDFGOnModule2, false)
52+
LUAU_FASTFLAGVARIABLE(LuauStoreDFGOnModule2)
5353

5454
namespace Luau
5555
{

Analysis/src/Linter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ LUAU_FASTFLAG(LuauSolverV2)
1818

1919
LUAU_FASTFLAG(LuauAttribute)
2020
LUAU_FASTFLAG(LuauNativeAttribute)
21-
LUAU_FASTFLAGVARIABLE(LintRedundantNativeAttribute, false)
21+
LUAU_FASTFLAGVARIABLE(LintRedundantNativeAttribute)
2222

2323
namespace Luau
2424
{

Analysis/src/NonStrictTypeChecker.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <iostream>
2020
#include <iterator>
2121

22+
LUAU_FASTFLAGVARIABLE(LuauUserTypeFunNonstrict)
23+
2224
namespace Luau
2325
{
2426

@@ -421,7 +423,9 @@ struct NonStrictTypeChecker
421423

422424
NonStrictContext visit(AstStatTypeFunction* typeFunc)
423425
{
424-
reportError(GenericError{"This syntax is not supported"}, typeFunc->location);
426+
if (!FFlag::LuauUserTypeFunNonstrict)
427+
reportError(GenericError{"This syntax is not supported"}, typeFunc->location);
428+
425429
return {};
426430
}
427431

0 commit comments

Comments
 (0)