Skip to content

Commit 77295c3

Browse files
Vighnesh-Vaatxealexmccordandyfriesenaviralg
authored
Sync to upstream/release/647 (#1469)
# General Updates Fix an old solver crash that occurs in the presence of cyclic `requires()` ## New Solver - Improvements to Luau user-defined type function library - Avoid asserting on unexpected metatable types - Properties in user defined type functions should have a consistent iteration order - in this case it is insertion ordering # Runtime - Track VM allocations for telemetry --- Co-authored-by: Aaron Weiss <[email protected]> Co-authored-by: Andy Friesen <[email protected]> Co-authored-by: Hunter Goldstein <[email protected]> Co-authored-by: James McNellis <[email protected]> Co-authored-by: Varun Saini <[email protected]> Co-authored-by: Vighnesh Vijay <[email protected]> Co-authored-by: Vyacheslav Egorov <[email protected]> --------- Co-authored-by: Aaron Weiss <[email protected]> Co-authored-by: Alexander McCord <[email protected]> Co-authored-by: Andy Friesen <[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 4559ef2 commit 77295c3

26 files changed

+426
-175
lines changed

Analysis/include/Luau/TypeFunctionRuntime.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include <optional>
88
#include <string>
9-
#include <unordered_map>
9+
#include <map>
1010
#include <vector>
1111

1212
using lua_State = struct lua_State;
@@ -182,7 +182,7 @@ struct TypeFunctionProperty
182182
struct TypeFunctionTableType
183183
{
184184
using Name = std::string;
185-
using Props = std::unordered_map<Name, TypeFunctionProperty>;
185+
using Props = std::map<Name, TypeFunctionProperty>;
186186

187187
Props props;
188188

@@ -195,7 +195,7 @@ struct TypeFunctionTableType
195195
struct TypeFunctionClassType
196196
{
197197
using Name = std::string;
198-
using Props = std::unordered_map<Name, TypeFunctionProperty>;
198+
using Props = std::map<Name, TypeFunctionProperty>;
199199

200200
Props props;
201201

@@ -260,6 +260,7 @@ bool isTypeUserData(lua_State* L, int idx);
260260
TypeFunctionTypeId getTypeUserData(lua_State* L, int idx);
261261
std::optional<TypeFunctionTypeId> optionalTypeUserData(lua_State* L, int idx);
262262

263+
void registerTypesLibrary(lua_State* L);
263264
void registerTypeUserData(lua_State* L);
264265

265266
void setTypeFunctionEnvironment(lua_State* L);

Analysis/src/BuiltinDefinitions.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
*/
2727

2828
LUAU_FASTFLAG(LuauSolverV2);
29-
LUAU_FASTFLAGVARIABLE(LuauDCRMagicFunctionTypeChecker, false);
3029

3130
namespace Luau
3231
{
@@ -931,8 +930,7 @@ TypeId makeStringMetatable(NotNull<BuiltinTypes> builtinTypes)
931930
formatFTV.isCheckedFunction = true;
932931
const TypeId formatFn = arena->addType(formatFTV);
933932
attachDcrMagicFunction(formatFn, dcrMagicFunctionFormat);
934-
if (FFlag::LuauDCRMagicFunctionTypeChecker)
935-
attachDcrMagicFunctionTypeCheck(formatFn, dcrMagicFunctionTypeCheckFormat);
933+
attachDcrMagicFunctionTypeCheck(formatFn, dcrMagicFunctionTypeCheckFormat);
936934

937935

938936
const TypeId stringToStringType = makeFunction(*arena, std::nullopt, {}, {}, {stringType}, {}, {stringType}, /* checked */ true);

Analysis/src/ConstraintSolver.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ LUAU_FASTFLAGVARIABLE(DebugLuauLogSolver, false)
3131
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverIncludeDependencies, false)
3232
LUAU_FASTFLAGVARIABLE(DebugLuauLogBindings, false)
3333
LUAU_FASTINTVARIABLE(LuauSolverRecursionLimit, 500)
34-
35-
// The default value here is 643 because the first release in which this was implemented is 644,
36-
// and actively we want new changes to be off by default until they're enabled consciously.
37-
LUAU_DYNAMIC_FASTINTVARIABLE(LuauTypeSolverRelease, 643)
34+
LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
3835

3936
namespace Luau
4037
{

Analysis/src/Differ.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace Luau
1515
{
16+
1617
std::string DiffPathNode::toString() const
1718
{
1819
switch (kind)
@@ -944,12 +945,14 @@ std::vector<std::pair<TypeId, TypeId>>::const_reverse_iterator DifferEnvironment
944945
return visitingStack.crend();
945946
}
946947

948+
947949
DifferResult diff(TypeId ty1, TypeId ty2)
948950
{
949951
DifferEnvironment differEnv{ty1, ty2, std::nullopt, std::nullopt};
950952
return diffUsingEnv(differEnv, ty1, ty2);
951953
}
952954

955+
953956
DifferResult diffWithSymbols(TypeId ty1, TypeId ty2, std::optional<std::string> symbol1, std::optional<std::string> symbol2)
954957
{
955958
DifferEnvironment differEnv{ty1, ty2, symbol1, symbol2};

Analysis/src/Frontend.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJsonFile, false)
4444
LUAU_FASTFLAGVARIABLE(DebugLuauForbidInternalTypes, false)
4545
LUAU_FASTFLAGVARIABLE(DebugLuauForceStrictMode, false)
4646
LUAU_FASTFLAGVARIABLE(DebugLuauForceNonStrictMode, false)
47-
LUAU_FASTFLAGVARIABLE(LuauSourceModuleUpdatedWithSelectedMode, false)
4847
LUAU_FASTFLAGVARIABLE(LuauUserDefinedTypeFunctionNoEvaluation, false)
4948
LUAU_DYNAMIC_FASTFLAGVARIABLE(LuauRunCustomModuleChecks, false)
49+
LUAU_FASTFLAGVARIABLE(LuauMoreThoroughCycleDetection, false)
5050

5151
LUAU_FASTFLAG(StudioReportLuauAny2)
5252

@@ -883,14 +883,18 @@ void Frontend::addBuildQueueItems(
883883
data.environmentScope = getModuleEnvironment(*sourceModule, data.config, frontendOptions.forAutocomplete);
884884
data.recordJsonLog = FFlag::DebugLuauLogSolverToJson;
885885

886-
Mode mode = sourceModule->mode.value_or(data.config.mode);
886+
const Mode mode = sourceModule->mode.value_or(data.config.mode);
887887

888-
// in NoCheck mode we only need to compute the value of .cyclic for typeck
889888
// in the future we could replace toposort with an algorithm that can flag cyclic nodes by itself
890889
// however, for now getRequireCycles isn't expensive in practice on the cases we care about, and long term
891890
// all correct programs must be acyclic so this code triggers rarely
892891
if (cycleDetected)
893-
data.requireCycles = getRequireCycles(fileResolver, sourceNodes, sourceNode.get(), mode == Mode::NoCheck);
892+
{
893+
if (FFlag::LuauMoreThoroughCycleDetection)
894+
data.requireCycles = getRequireCycles(fileResolver, sourceNodes, sourceNode.get(), false);
895+
else
896+
data.requireCycles = getRequireCycles(fileResolver, sourceNodes, sourceNode.get(), mode == Mode::NoCheck);
897+
}
894898

895899
data.options = frontendOptions;
896900

@@ -922,8 +926,7 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item)
922926
else
923927
mode = sourceModule.mode.value_or(config.mode);
924928

925-
if (FFlag::LuauSourceModuleUpdatedWithSelectedMode)
926-
item.sourceModule->mode = {mode};
929+
item.sourceModule->mode = {mode};
927930
ScopePtr environmentScope = item.environmentScope;
928931
double timestamp = getTimestamp();
929932
const std::vector<RequireCycle>& requireCycles = item.requireCycles;

Analysis/src/Normalize.cpp

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,13 @@
1616
#include "Luau/Unifier.h"
1717

1818
LUAU_FASTFLAGVARIABLE(DebugLuauCheckNormalizeInvariant, false)
19-
LUAU_FASTFLAGVARIABLE(LuauFixReduceStackPressure, false);
20-
LUAU_FASTFLAGVARIABLE(LuauFixCyclicTablesBlowingStack, false);
2119

2220
LUAU_FASTINTVARIABLE(LuauNormalizeCacheLimit, 100000);
2321
LUAU_FASTFLAG(LuauSolverV2);
2422

2523
LUAU_FASTFLAGVARIABLE(LuauUseNormalizeIntersectionLimit, false)
2624
LUAU_FASTINTVARIABLE(LuauNormalizeIntersectionLimit, 200)
2725

28-
static bool fixReduceStackPressure()
29-
{
30-
return FFlag::LuauFixReduceStackPressure || FFlag::LuauSolverV2;
31-
}
32-
33-
static bool fixCyclicTablesBlowingStack()
34-
{
35-
return FFlag::LuauFixCyclicTablesBlowingStack || FFlag::LuauSolverV2;
36-
}
37-
3826
namespace Luau
3927
{
4028

@@ -2583,43 +2571,29 @@ std::optional<TypeId> Normalizer::intersectionOfTables(TypeId here, TypeId there
25832571
if (tprop.readTy.has_value())
25842572
{
25852573
// if the intersection of the read types of a property is uninhabited, the whole table is `never`.
2586-
if (fixReduceStackPressure())
2574+
// We've seen these table prop elements before and we're about to ask if their intersection
2575+
// is inhabited
2576+
if (seenSet.contains(*hprop.readTy) && seenSet.contains(*tprop.readTy))
25872577
{
2588-
// We've seen these table prop elements before and we're about to ask if their intersection
2589-
// is inhabited
2590-
if (fixCyclicTablesBlowingStack())
2591-
{
2592-
if (seenSet.contains(*hprop.readTy) && seenSet.contains(*tprop.readTy))
2593-
{
2594-
seenSet.erase(*hprop.readTy);
2595-
seenSet.erase(*tprop.readTy);
2596-
return {builtinTypes->neverType};
2597-
}
2598-
else
2599-
{
2600-
seenSet.insert(*hprop.readTy);
2601-
seenSet.insert(*tprop.readTy);
2602-
}
2603-
}
2604-
2605-
NormalizationResult res = isIntersectionInhabited(*hprop.readTy, *tprop.readTy);
2606-
2607-
// Cleanup
2608-
if (fixCyclicTablesBlowingStack())
2609-
{
2610-
seenSet.erase(*hprop.readTy);
2611-
seenSet.erase(*tprop.readTy);
2612-
}
2613-
2614-
if (NormalizationResult::True != res)
2615-
return {builtinTypes->neverType};
2578+
seenSet.erase(*hprop.readTy);
2579+
seenSet.erase(*tprop.readTy);
2580+
return {builtinTypes->neverType};
26162581
}
26172582
else
26182583
{
2619-
if (NormalizationResult::False == isIntersectionInhabited(*hprop.readTy, *tprop.readTy))
2620-
return {builtinTypes->neverType};
2584+
seenSet.insert(*hprop.readTy);
2585+
seenSet.insert(*tprop.readTy);
26212586
}
26222587

2588+
NormalizationResult res = isIntersectionInhabited(*hprop.readTy, *tprop.readTy);
2589+
2590+
// Cleanup
2591+
seenSet.erase(*hprop.readTy);
2592+
seenSet.erase(*tprop.readTy);
2593+
2594+
if (NormalizationResult::True != res)
2595+
return {builtinTypes->neverType};
2596+
26232597
TypeId ty = simplifyIntersection(builtinTypes, NotNull{arena}, *hprop.readTy, *tprop.readTy).result;
26242598
prop.readTy = ty;
26252599
hereSubThere &= (ty == hprop.readTy);

Analysis/src/TypeChecker2.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,8 +1625,11 @@ void TypeChecker2::indexExprMetatableHelper(AstExprIndexExpr* indexExpr, const M
16251625
indexExprMetatableHelper(indexExpr, mtmt, exprType, indexType);
16261626
else
16271627
{
1628-
LUAU_ASSERT(tt || get<PrimitiveType>(follow(metaTable->table)));
1629-
1628+
if (!(DFInt::LuauTypeSolverRelease >= 647))
1629+
{
1630+
LUAU_ASSERT(tt || get<PrimitiveType>(follow(metaTable->table)));
1631+
}
1632+
// CLI-122161: We're not handling unions correctly (probably).
16301633
reportError(CannotExtendTable{exprType, CannotExtendTable::Indexer, "indexer??"}, indexExpr->location);
16311634
}
16321635
}

Analysis/src/TypeFunction.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ LUAU_DYNAMIC_FASTINTVARIABLE(LuauTypeFamilyUseGuesserDepth, -1);
4848
LUAU_FASTFLAGVARIABLE(DebugLuauLogTypeFamilies, false)
4949
LUAU_FASTFLAGVARIABLE(LuauUserDefinedTypeFunctions2, false)
5050
LUAU_FASTFLAG(LuauUserDefinedTypeFunctionNoEvaluation)
51+
LUAU_FASTFLAG(LuauUserTypeFunFixRegister)
5152

5253
LUAU_DYNAMIC_FASTINT(LuauTypeSolverRelease)
5354

@@ -1018,9 +1019,11 @@ void TypeFunctionRuntime::prepareState()
10181019

10191020
setTypeFunctionEnvironment(L);
10201021

1021-
// Register type userdata
10221022
registerTypeUserData(L);
10231023

1024+
if (FFlag::LuauUserTypeFunFixRegister)
1025+
registerTypesLibrary(L);
1026+
10241027
luaL_sandbox(L);
10251028
luaL_sandboxthread(L);
10261029
}

0 commit comments

Comments
 (0)