Skip to content

Commit 4799090

Browse files
authored
Merge branch 'luau-lang:master' into master
2 parents c0df48f + 72f6c8b commit 4799090

Some content is hidden

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

58 files changed

+1387
-443
lines changed

Analysis/include/Luau/Type.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ struct FreeType
7474
// This one got promoted to explicit
7575
explicit FreeType(Scope* scope, TypeId lowerBound, TypeId upperBound, Polarity polarity = Polarity::Unknown);
7676
explicit FreeType(Scope* scope, TypeLevel level, TypeId lowerBound, TypeId upperBound);
77-
// Old constructors
78-
explicit FreeType(TypeLevel level);
79-
explicit FreeType(Scope* scope);
80-
FreeType(Scope* scope, TypeLevel level);
8177

8278
int index;
8379
TypeLevel level;

Analysis/include/Luau/TypeArena.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ struct TypeArena
3737
TypeId freshType(NotNull<BuiltinTypes> builtins, Scope* scope);
3838
TypeId freshType(NotNull<BuiltinTypes> builtins, Scope* scope, TypeLevel level);
3939

40-
TypeId freshType_DEPRECATED(TypeLevel level);
41-
TypeId freshType_DEPRECATED(Scope* scope);
42-
TypeId freshType_DEPRECATED(Scope* scope, TypeLevel level);
43-
4440
TypePackId freshTypePack(Scope* scope, Polarity polarity = Polarity::Unknown);
4541

4642
TypePackId addTypePack(std::initializer_list<TypeId> types);

Analysis/include/Luau/TypePack.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ TypePackIterator begin(TypePackId tp);
185185
TypePackIterator begin(TypePackId tp, const TxnLog* log);
186186
TypePackIterator end(TypePackId tp);
187187

188+
TypePackId getTail(TypePackId tp);
189+
188190
using SeenSet = std::set<std::pair<const void*, const void*>>;
189191

190192
bool areEqual(SeenSet& seen, const TypePackVar& lhs, const TypePackVar& rhs);

Analysis/src/AstJsonEncoder.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -475,26 +475,26 @@ struct AstJsonEncoder : public AstVisitor
475475
writeRaw("}");
476476
}
477477

478-
void write(const AstGenericType& genericType)
478+
void write(class AstGenericType* genericType)
479479
{
480480
writeRaw("{");
481481
bool c = pushComma();
482482
writeType("AstGenericType");
483-
write("name", genericType.name);
484-
if (genericType.defaultValue)
485-
write("luauType", genericType.defaultValue);
483+
write("name", genericType->name);
484+
if (genericType->defaultValue)
485+
write("luauType", genericType->defaultValue);
486486
popComma(c);
487487
writeRaw("}");
488488
}
489489

490-
void write(const AstGenericTypePack& genericTypePack)
490+
void write(class AstGenericTypePack* genericTypePack)
491491
{
492492
writeRaw("{");
493493
bool c = pushComma();
494494
writeType("AstGenericTypePack");
495-
write("name", genericTypePack.name);
496-
if (genericTypePack.defaultValue)
497-
write("luauType", genericTypePack.defaultValue);
495+
write("name", genericTypePack->name);
496+
if (genericTypePack->defaultValue)
497+
write("luauType", genericTypePack->defaultValue);
498498
popComma(c);
499499
writeRaw("}");
500500
}

Analysis/src/BuiltinDefinitions.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
LUAU_FASTFLAG(LuauSolverV2)
3333
LUAU_FASTFLAG(LuauNonReentrantGeneralization2)
3434
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
35-
LUAU_FASTFLAGVARIABLE(LuauFollowTableFreeze)
3635
LUAU_FASTFLAGVARIABLE(LuauUserTypeFunTypecheck)
3736
LUAU_FASTFLAGVARIABLE(LuauMagicFreezeCheckBlocked)
3837
LUAU_FASTFLAGVARIABLE(LuauFormatUseLastPosition)
@@ -1550,8 +1549,7 @@ bool MagicClone::infer(const MagicFunctionCallContext& context)
15501549
static std::optional<TypeId> freezeTable(TypeId inputType, const MagicFunctionCallContext& context)
15511550
{
15521551
TypeArena* arena = context.solver->arena;
1553-
if (FFlag::LuauFollowTableFreeze)
1554-
inputType = follow(inputType);
1552+
inputType = follow(inputType);
15551553
if (auto mt = get<MetatableType>(inputType))
15561554
{
15571555
std::optional<TypeId> frozenTable = freezeTable(mt->table, context);

Analysis/src/Constraint.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,7 @@ struct ReferenceCountInitializer : TypeOnceVisitor
5151

5252
bool visit(TypeId, const TypeFunctionInstanceType&) override
5353
{
54-
// We do not consider reference counted types that are inside a type
55-
// function to be part of the reachable reference counted types.
56-
// Otherwise, code can be constructed in just the right way such
57-
// that two type functions both claim to mutate a free type, which
58-
// prevents either type function from trying to generalize it, so
59-
// we potentially get stuck.
60-
//
61-
// The default behavior here is `true` for "visit the child types"
62-
// of this type, hence:
63-
return false;
54+
return FFlag::DebugLuauGreedyGeneralization;
6455
}
6556
};
6657

@@ -130,8 +121,10 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
130121
}
131122
else if (auto hic = get<HasIndexerConstraint>(*this))
132123
{
124+
if (FFlag::DebugLuauGreedyGeneralization)
125+
rci.traverse(hic->subjectType);
133126
rci.traverse(hic->resultType);
134-
// `HasIndexerConstraint` should not mutate `subjectType` or `indexType`.
127+
// `HasIndexerConstraint` should not mutate `indexType`.
135128
}
136129
else if (auto apc = get<AssignPropConstraint>(*this))
137130
{
@@ -150,6 +143,10 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
150143
rci.traverse(ty);
151144
// `UnpackConstraint` should not mutate `sourcePack`.
152145
}
146+
else if (auto rpc = get<ReduceConstraint>(*this); FFlag::DebugLuauGreedyGeneralization && rpc)
147+
{
148+
rci.traverse(rpc->ty);
149+
}
153150
else if (auto rpc = get<ReducePackConstraint>(*this))
154151
{
155152
rci.traverse(rpc->tp);

Analysis/src/ConstraintGenerator.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
3939

4040
LUAU_FASTFLAGVARIABLE(LuauUngeneralizedTypesForRecursiveFunctions)
4141

42-
LUAU_FASTFLAG(LuauFreeTypesMustHaveBounds)
4342
LUAU_FASTFLAG(LuauUserTypeFunTypecheck)
4443
LUAU_FASTFLAGVARIABLE(LuauRetainDefinitionAliasLocations)
4544

@@ -52,6 +51,7 @@ LUAU_FASTFLAG(LuauGlobalVariableModuleIsolation)
5251

5352
LUAU_FASTFLAGVARIABLE(LuauNoTypeFunctionsNamedTypeOf)
5453
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
54+
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
5555

5656
namespace Luau
5757
{
@@ -1409,7 +1409,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatLocalFuncti
14091409
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
14101410
sig.bodyScope->bindings[function->name] = Binding{sig.signature, function->name->location};
14111411

1412-
bool sigFullyDefined = !hasFreeType(sig.signature);
1412+
bool sigFullyDefined = FFlag::DebugLuauGreedyGeneralization ? false : !hasFreeType(sig.signature);
14131413
if (sigFullyDefined)
14141414
emplaceType<BoundType>(asMutable(functionType), sig.signature);
14151415

@@ -1471,7 +1471,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f
14711471

14721472
Checkpoint start = checkpoint(this);
14731473
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
1474-
bool sigFullyDefined = !hasFreeType(sig.signature);
1474+
bool sigFullyDefined = FFlag::DebugLuauGreedyGeneralization ? false : !hasFreeType(sig.signature);
14751475

14761476
DefId def = dfg->getDef(function->name);
14771477

@@ -2389,9 +2389,12 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
23892389
this,
23902390
[checkConstraint, callConstraint](const ConstraintPtr& constraint)
23912391
{
2392-
constraint->dependencies.emplace_back(checkConstraint);
2392+
if (!(FFlag::DebugLuauGreedyGeneralization && get<PrimitiveTypeConstraint>(*constraint)))
2393+
{
2394+
constraint->dependencies.emplace_back(checkConstraint);
23932395

2394-
callConstraint->dependencies.emplace_back(constraint.get());
2396+
callConstraint->dependencies.emplace_back(constraint.get());
2397+
}
23952398
}
23962399
);
23972400

@@ -2496,8 +2499,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprConstantStrin
24962499
}
24972500
else
24982501
{
2499-
FreeType ft =
2500-
FFlag::LuauFreeTypesMustHaveBounds ? FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType} : FreeType{scope.get()};
2502+
FreeType ft = FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType};
25012503
ft.lowerBound = arena->addType(SingletonType{StringSingleton{std::string{string->value.data, string->value.size}}});
25022504
ft.upperBound = builtinTypes->stringType;
25032505
freeTy = arena->addType(ft);
@@ -2524,8 +2526,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprConstantBool*
25242526
}
25252527
else
25262528
{
2527-
FreeType ft =
2528-
FFlag::LuauFreeTypesMustHaveBounds ? FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType} : FreeType{scope.get()};
2529+
FreeType ft = FreeType{scope.get(), builtinTypes->neverType, builtinTypes->unknownType};
25292530
ft.lowerBound = singletonType;
25302531
ft.upperBound = builtinTypes->booleanType;
25312532
freeTy = arena->addType(ft);
@@ -3076,7 +3077,7 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprLocal* local
30763077
if (ty)
30773078
{
30783079
TypeIds* localDomain = localTypes.find(*ty);
3079-
if (localDomain)
3080+
if (localDomain && !(FFlag::LuauDoNotAddUpvalueTypesToLocalType && local->upvalue))
30803081
localDomain->insert(rhsType);
30813082
}
30823083
else
@@ -3107,8 +3108,10 @@ void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprLocal* local
31073108
if (annotatedTy)
31083109
addConstraint(scope, local->location, SubtypeConstraint{rhsType, *annotatedTy});
31093110

3110-
if (TypeIds* localDomain = localTypes.find(*ty))
3111-
localDomain->insert(rhsType);
3111+
// This is vestigial.
3112+
if (!FFlag::LuauDoNotAddUpvalueTypesToLocalType)
3113+
if (TypeIds* localDomain = localTypes.find(*ty))
3114+
localDomain->insert(rhsType);
31123115
}
31133116

31143117
void ConstraintGenerator::visitLValue(const ScopePtr& scope, AstExprGlobal* global, TypeId rhsType)
@@ -3410,13 +3413,22 @@ ConstraintGenerator::FunctionSignature ConstraintGenerator::checkFunctionSignatu
34103413
bodyScope->varargPack = std::nullopt;
34113414
}
34123415

3416+
LUAU_ASSERT(nullptr != varargPack);
3417+
34133418
if (FFlag::DebugLuauGreedyGeneralization)
34143419
{
3415-
genericTypes = argTypes;
3420+
// Some of the types in argTypes will eventually be generics, and some
3421+
// will not. The ones that are not generic will be pruned when
3422+
// GeneralizationConstraint dispatches.
3423+
genericTypes.insert(genericTypes.begin(), argTypes.begin(), argTypes.end());
3424+
varargPack = follow(varargPack);
3425+
returnType = follow(returnType);
3426+
if (varargPack == returnType)
3427+
genericTypePacks = {varargPack};
3428+
else
3429+
genericTypePacks = {varargPack, returnType};
34163430
}
34173431

3418-
LUAU_ASSERT(nullptr != varargPack);
3419-
34203432
// If there is both an annotation and an expected type, the annotation wins.
34213433
// Type checking will sort out any discrepancies later.
34223434
if (FFlag::LuauStoreReturnTypesAsPackOnAst && fn->returnAnnotation)

Analysis/src/ConstraintSolver.cpp

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,6 @@ void ConstraintSolver::initFreeTypeTracking()
681681
}
682682
maybeMutatedFreeTypes.emplace(c, maybeMutatedTypesPerConstraint);
683683

684-
685684
for (NotNull<const Constraint> dep : c->dependencies)
686685
{
687686
block(dep, c);
@@ -2082,24 +2081,61 @@ bool ConstraintSolver::tryDispatch(const AssignPropConstraint& c, NotNull<const
20822081
if (auto lhsFree = getMutable<FreeType>(lhsType))
20832082
{
20842083
auto lhsFreeUpperBound = follow(lhsFree->upperBound);
2085-
if (get<TableType>(lhsFreeUpperBound) || get<MetatableType>(lhsFreeUpperBound))
2086-
lhsType = lhsFreeUpperBound;
2084+
2085+
if (FFlag::DebugLuauGreedyGeneralization)
2086+
{
2087+
const auto [blocked, maybeTy, isIndex] = lookupTableProp(constraint, lhsType, propName, ValueContext::LValue);
2088+
if (!blocked.empty())
2089+
{
2090+
for (TypeId t : blocked)
2091+
block(t, constraint);
2092+
return false;
2093+
}
2094+
else if (maybeTy)
2095+
{
2096+
bind(constraint, c.propType, isIndex ? arena->addType(UnionType{{*maybeTy, builtinTypes->nilType}}) : *maybeTy);
2097+
unify(constraint, rhsType, *maybeTy);
2098+
return true;
2099+
}
2100+
else
2101+
{
2102+
TypeId newUpperBound = arena->addType(TableType{TableState::Free, TypeLevel{}, constraint->scope});
2103+
2104+
trackInteriorFreeType(constraint->scope, newUpperBound);
2105+
2106+
TableType* upperTable = getMutable<TableType>(newUpperBound);
2107+
LUAU_ASSERT(upperTable);
2108+
2109+
upperTable->props[c.propName] = rhsType;
2110+
2111+
// Food for thought: Could we block if simplification encounters a blocked type?
2112+
lhsFree->upperBound = simplifyIntersection(constraint->scope, constraint->location, lhsFreeUpperBound, newUpperBound);
2113+
2114+
bind(constraint, c.propType, rhsType);
2115+
return true;
2116+
}
2117+
}
20872118
else
20882119
{
2089-
TypeId newUpperBound = arena->addType(TableType{TableState::Free, TypeLevel{}, constraint->scope});
2120+
if (get<TableType>(lhsFreeUpperBound) || get<MetatableType>(lhsFreeUpperBound))
2121+
lhsType = lhsFreeUpperBound;
2122+
else
2123+
{
2124+
TypeId newUpperBound = arena->addType(TableType{TableState::Free, TypeLevel{}, constraint->scope});
20902125

2091-
trackInteriorFreeType(constraint->scope, newUpperBound);
2126+
trackInteriorFreeType(constraint->scope, newUpperBound);
20922127

2093-
TableType* upperTable = getMutable<TableType>(newUpperBound);
2094-
LUAU_ASSERT(upperTable);
2128+
TableType* upperTable = getMutable<TableType>(newUpperBound);
2129+
LUAU_ASSERT(upperTable);
20952130

2096-
upperTable->props[c.propName] = rhsType;
2131+
upperTable->props[c.propName] = rhsType;
20972132

2098-
// Food for thought: Could we block if simplification encounters a blocked type?
2099-
lhsFree->upperBound = simplifyIntersection(constraint->scope, constraint->location, lhsFreeUpperBound, newUpperBound);
2133+
// Food for thought: Could we block if simplification encounters a blocked type?
2134+
lhsFree->upperBound = simplifyIntersection(constraint->scope, constraint->location, lhsFreeUpperBound, newUpperBound);
21002135

2101-
bind(constraint, c.propType, rhsType);
2102-
return true;
2136+
bind(constraint, c.propType, rhsType);
2137+
return true;
2138+
}
21032139
}
21042140
}
21052141

@@ -2873,8 +2909,21 @@ TablePropLookupResult ConstraintSolver::lookupTableProp(
28732909
{
28742910
const TypeId upperBound = follow(ft->upperBound);
28752911

2876-
if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
2877-
return lookupTableProp(constraint, upperBound, propName, context, inConditional, suppressSimplification, seen);
2912+
if (FFlag::DebugLuauGreedyGeneralization)
2913+
{
2914+
if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
2915+
{
2916+
TablePropLookupResult res = lookupTableProp(constraint, upperBound, propName, context, inConditional, suppressSimplification, seen);
2917+
// If the upper bound is a table that already has the property, we don't need to extend its bounds.
2918+
if (res.propType || get<PrimitiveType>(upperBound))
2919+
return res;
2920+
}
2921+
}
2922+
else
2923+
{
2924+
if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
2925+
return lookupTableProp(constraint, upperBound, propName, context, inConditional, suppressSimplification, seen);
2926+
}
28782927

28792928
// TODO: The upper bound could be an intersection that contains suitable tables or extern types.
28802929

Analysis/src/DataFlowGraph.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ LUAU_FASTFLAGVARIABLE(LuauPreprocessTypestatedArgument)
1717
LUAU_FASTFLAGVARIABLE(LuauDfgScopeStackTrueReset)
1818
LUAU_FASTFLAGVARIABLE(LuauDfgScopeStackNotNull)
1919
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
20-
20+
LUAU_FASTFLAGVARIABLE(LuauDoNotAddUpvalueTypesToLocalType)
21+
LUAU_FASTFLAGVARIABLE(LuauDfgIfBlocksShouldRespectControlFlow)
2122
namespace Luau
2223
{
2324

@@ -501,12 +502,26 @@ ControlFlow DataFlowGraphBuilder::visit(AstStatIf* i)
501502
}
502503

503504
DfgScope* scope = FFlag::LuauDfgScopeStackNotNull ? currentScope() : currentScope_DEPRECATED();
504-
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
505-
join(scope, scope, elseScope);
506-
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
507-
join(scope, thenScope, scope);
508-
else if ((thencf | elsecf) == ControlFlow::None)
509-
join(scope, thenScope, elseScope);
505+
if (FFlag::LuauDfgIfBlocksShouldRespectControlFlow)
506+
{
507+
// If the control flow from the `if` or `else` block is non-linear,
508+
// then we should assume that the _other_ branch is the one taken.
509+
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
510+
scope->inherit(elseScope);
511+
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
512+
scope->inherit(thenScope);
513+
else if ((thencf | elsecf) == ControlFlow::None)
514+
join(scope, thenScope, elseScope);
515+
}
516+
else
517+
{
518+
if (thencf != ControlFlow::None && elsecf == ControlFlow::None)
519+
join(scope, scope, elseScope);
520+
else if (thencf == ControlFlow::None && elsecf != ControlFlow::None)
521+
join(scope, thenScope, scope);
522+
else if ((thencf | elsecf) == ControlFlow::None)
523+
join(scope, thenScope, elseScope);
524+
}
510525

511526
if (thencf == elsecf)
512527
return thencf;
@@ -1164,7 +1179,7 @@ DefId DataFlowGraphBuilder::visitLValue(AstExprLocal* l, DefId incomingDef)
11641179
DfgScope* scope = FFlag::LuauDfgScopeStackNotNull ? currentScope() : currentScope_DEPRECATED();
11651180

11661181
// In order to avoid alias tracking, we need to clip the reference to the parent def.
1167-
if (scope->canUpdateDefinition(l->local))
1182+
if (scope->canUpdateDefinition(l->local) && !(FFlag::LuauDoNotAddUpvalueTypesToLocalType && l->upvalue))
11681183
{
11691184
DefId updated = defArena->freshCell(l->local, l->location, containsSubscriptedDefinition(incomingDef));
11701185
scope->bindings[l->local] = updated;

0 commit comments

Comments
 (0)