Skip to content

Commit 3eb0c13

Browse files
andyfriesenhgoldsteinvrn-snayoungbloodrbxmenarulalam
authored
Sync to upstream/release/673 (#1812)
# General Changes * Remove a `static_assert` that prevented Luau from building on 32-bit targets. * Fix `proxyrequire` (see #1804) * Replace contents API with new `loadname` API in Luau.Require * Store the positions of `:` symbols in the CST. * Fix a minor bug in the new incremental autocomplete engine: Properly suggest `else` and `elseif` if the cursor is currently within an `if` block. # New Type Solver * Allow generics to be substituted for negation types when performing subtype tests * Crash fixes * Surface subtyping errors more consistently. * Avoid creating double-negation types (like `~~(false?)`) when generating constraints. # Internal Contributors Co-authored-by: Andy Friesen <[email protected]> Co-authored-by: Ariel Weiss <[email protected]> Co-authored-by: Aviral Goel <[email protected]> Co-authored-by: Hunter Goldstein <[email protected]> Co-authored-by: Sora Kanosue <[email protected]> Co-authored-by: Talha Pathan <[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: Hunter Goldstein <[email protected]> Co-authored-by: Varun Saini <[email protected]> Co-authored-by: Alexander Youngblood <[email protected]> Co-authored-by: Menarul Alam <[email protected]> Co-authored-by: Aviral Goel <[email protected]> Co-authored-by: Vighnesh <[email protected]> Co-authored-by: Vyacheslav Egorov <[email protected]> Co-authored-by: Ariel Weiss <[email protected]>
1 parent 42281aa commit 3eb0c13

Some content is hidden

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

60 files changed

+1326
-2384
lines changed

Analysis/include/Luau/Constraint.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ struct GeneralizationConstraint
5151

5252
std::vector<TypeId> interiorTypes;
5353
bool hasDeprecatedAttribute = false;
54+
55+
/// If true, never introduce generics. Always replace free types by their
56+
/// bounds or unknown. Presently used only to generalize the whole module.
57+
bool noGenerics = false;
5458
};
5559

5660
// variables ~ iterate iterator

Analysis/include/Luau/TypeChecker2.h

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include "Luau/TypeOrPack.h"
1414
#include "Luau/TypeUtils.h"
1515

16-
LUAU_FASTFLAG(LuauImproveTypePathsInErrors)
17-
1816
namespace Luau
1917
{
2018

@@ -40,29 +38,18 @@ struct Reasonings
4038

4139
std::string toString()
4240
{
43-
if (FFlag::LuauImproveTypePathsInErrors && reasons.empty())
41+
if (reasons.empty())
4442
return "";
4543

4644
// DenseHashSet ordering is entirely undefined, so we want to
4745
// sort the reasons here to achieve a stable error
4846
// stringification.
4947
std::sort(reasons.begin(), reasons.end());
50-
std::string allReasons = FFlag::LuauImproveTypePathsInErrors ? "\nthis is because " : "";
51-
bool first = true;
48+
std::string allReasons = "\nthis is because ";
5249
for (const std::string& reason : reasons)
5350
{
54-
if (FFlag::LuauImproveTypePathsInErrors)
55-
{
56-
if (reasons.size() > 1)
57-
allReasons += "\n\t * ";
58-
}
59-
else
60-
{
61-
if (first)
62-
first = false;
63-
else
64-
allReasons += "\n\t";
65-
}
51+
if (reasons.size() > 1)
52+
allReasons += "\n\t * ";
6653

6754
allReasons += reason;
6855
}

Analysis/src/BuiltinDefinitions.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ LUAU_FASTFLAG(LuauSolverV2)
3333
LUAU_FASTFLAG(LuauNonReentrantGeneralization2)
3434
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
3535
LUAU_FASTFLAGVARIABLE(LuauUserTypeFunTypecheck)
36-
LUAU_FASTFLAGVARIABLE(LuauMagicFreezeCheckBlocked)
36+
LUAU_FASTFLAGVARIABLE(LuauMagicFreezeCheckBlocked2)
3737
LUAU_FASTFLAGVARIABLE(LuauFormatUseLastPosition)
3838

3939
namespace Luau
@@ -1616,11 +1616,11 @@ bool MagicFreeze::infer(const MagicFunctionCallContext& context)
16161616
std::optional<DefId> resultDef = dfg->getDefOptional(targetExpr);
16171617
std::optional<TypeId> resultTy = resultDef ? scope->lookup(*resultDef) : std::nullopt;
16181618

1619-
if (FFlag::LuauMagicFreezeCheckBlocked)
1619+
if (FFlag::LuauMagicFreezeCheckBlocked2)
16201620
{
1621-
if (resultTy && !get<BlockedType>(resultTy))
1621+
if (resultTy && !get<BlockedType>(follow(resultTy)))
16221622
{
1623-
// If there's an existing result type but it's _not_ blocked, then
1623+
// If there's an existing result type, but it's _not_ blocked, then
16241624
// we aren't type stating this builtin and should fall back to
16251625
// regular inference.
16261626
return false;
@@ -1629,6 +1629,8 @@ bool MagicFreeze::infer(const MagicFunctionCallContext& context)
16291629

16301630
std::optional<TypeId> frozenType = freezeTable(inputType, context);
16311631

1632+
// At this point: we know for sure that if `resultTy` exists, it is a
1633+
// blocked type, and can safely emplace it.
16321634
if (!frozenType)
16331635
{
16341636
if (resultTy)

Analysis/src/Clone.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ LUAU_FASTFLAG(LuauSolverV2)
1414
LUAU_FASTINTVARIABLE(LuauTypeCloneIterationLimit, 100'000)
1515
LUAU_FASTFLAGVARIABLE(LuauClonedTableAndFunctionTypesMustHaveScopes)
1616
LUAU_FASTFLAGVARIABLE(LuauDoNotClonePersistentBindings)
17-
LUAU_FASTFLAG(LuauIncrementalAutocompleteDemandBasedCloning)
1817
namespace Luau
1918
{
2019

@@ -549,11 +548,6 @@ class FragmentAutocompleteTypeCloner final : public TypeCloner
549548
void cloneChildren(LazyType* t) override
550549
{
551550
// Do not clone lazy types
552-
if (!FFlag::LuauIncrementalAutocompleteDemandBasedCloning)
553-
{
554-
if (auto unwrapped = t->unwrapped.load())
555-
t->unwrapped.store(shallowClone(unwrapped));
556-
}
557551
}
558552
};
559553

Analysis/src/ConstraintGenerator.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ LUAU_FASTFLAGVARIABLE(LuauUngeneralizedTypesForRecursiveFunctions)
4242
LUAU_FASTFLAG(LuauUserTypeFunTypecheck)
4343
LUAU_FASTFLAGVARIABLE(LuauRetainDefinitionAliasLocations)
4444

45-
LUAU_FASTFLAG(LuauDeprecatedAttribute)
4645
LUAU_FASTFLAGVARIABLE(LuauCacheInferencePerAstExpr)
4746
LUAU_FASTFLAGVARIABLE(LuauAlwaysResolveAstTypes)
4847
LUAU_FASTFLAGVARIABLE(LuauWeakNilRefinementType)
@@ -52,6 +51,7 @@ LUAU_FASTFLAG(LuauGlobalVariableModuleIsolation)
5251
LUAU_FASTFLAGVARIABLE(LuauNoTypeFunctionsNamedTypeOf)
5352
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
5453
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
54+
LUAU_FASTFLAGVARIABLE(LuauAvoidDoubleNegation)
5555

5656
namespace Luau
5757
{
@@ -288,7 +288,9 @@ void ConstraintGenerator::visitModuleRoot(AstStatBlock* block)
288288
GeneralizationConstraint{
289289
result,
290290
moduleFnTy,
291-
std::vector<TypeId>{},
291+
/*interiorTypes*/ std::vector<TypeId>{},
292+
/*hasDeprecatedAttribute*/ false,
293+
/*noGenerics*/ true
292294
}
293295
);
294296

@@ -573,7 +575,17 @@ void ConstraintGenerator::computeRefinement(
573575

574576
// if we have a negative sense, then we need to negate the discriminant
575577
if (!sense)
576-
discriminantTy = arena->addType(NegationType{discriminantTy});
578+
{
579+
if (FFlag::LuauAvoidDoubleNegation)
580+
{
581+
if (auto nt = get<NegationType>(follow(discriminantTy)))
582+
discriminantTy = nt->ty;
583+
else
584+
discriminantTy = arena->addType(NegationType{discriminantTy});
585+
}
586+
else
587+
discriminantTy = arena->addType(NegationType{discriminantTy});
588+
}
577589

578590
if (eq)
579591
discriminantTy = createTypeFunctionInstance(builtinTypeFunctions().singletonFunc, {discriminantTy}, {}, scope, location);
@@ -1377,7 +1389,6 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatRepeat* rep
13771389

13781390
static void propagateDeprecatedAttributeToConstraint(ConstraintV& c, const AstExprFunction* func)
13791391
{
1380-
LUAU_ASSERT(FFlag::LuauDeprecatedAttribute);
13811392
if (GeneralizationConstraint* genConstraint = c.get_if<GeneralizationConstraint>())
13821393
{
13831394
genConstraint->hasDeprecatedAttribute = func->hasAttribute(AstAttr::Type::Deprecated);
@@ -1386,7 +1397,6 @@ static void propagateDeprecatedAttributeToConstraint(ConstraintV& c, const AstEx
13861397

13871398
static void propagateDeprecatedAttributeToType(TypeId signature, const AstExprFunction* func)
13881399
{
1389-
LUAU_ASSERT(FFlag::LuauDeprecatedAttribute);
13901400
FunctionType* fty = getMutable<FunctionType>(signature);
13911401
LUAU_ASSERT(fty);
13921402
fty->isDeprecatedFunction = func->hasAttribute(AstAttr::Type::Deprecated);
@@ -1429,8 +1439,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatLocalFuncti
14291439
std::unique_ptr<Constraint> c =
14301440
std::make_unique<Constraint>(constraintScope, function->name->location, GeneralizationConstraint{functionType, sig.signature});
14311441

1432-
if (FFlag::LuauDeprecatedAttribute)
1433-
propagateDeprecatedAttributeToConstraint(c->c, function->func);
1442+
propagateDeprecatedAttributeToConstraint(c->c, function->func);
14341443

14351444
Constraint* previous = nullptr;
14361445
forEachConstraint(
@@ -1457,8 +1466,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatLocalFuncti
14571466
else
14581467
{
14591468
module->astTypes[function->func] = sig.signature;
1460-
if (FFlag::LuauDeprecatedAttribute)
1461-
propagateDeprecatedAttributeToType(sig.signature, function->func);
1469+
propagateDeprecatedAttributeToType(sig.signature, function->func);
14621470
}
14631471

14641472
return ControlFlow::None;
@@ -1502,8 +1510,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f
15021510
if (sigFullyDefined)
15031511
{
15041512
emplaceType<BoundType>(asMutable(generalizedType), sig.signature);
1505-
if (FFlag::LuauDeprecatedAttribute)
1506-
propagateDeprecatedAttributeToType(sig.signature, function->func);
1513+
propagateDeprecatedAttributeToType(sig.signature, function->func);
15071514
}
15081515
else
15091516
{
@@ -1512,8 +1519,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f
15121519
NotNull<Constraint> c = addConstraint(constraintScope, function->name->location, GeneralizationConstraint{generalizedType, sig.signature});
15131520
getMutable<BlockedType>(generalizedType)->setOwner(c);
15141521

1515-
if (FFlag::LuauDeprecatedAttribute)
1516-
propagateDeprecatedAttributeToConstraint(c->c, function->func);
1522+
propagateDeprecatedAttributeToConstraint(c->c, function->func);
15171523

15181524
Constraint* previous = nullptr;
15191525
forEachConstraint(
@@ -2054,8 +2060,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatDeclareFunc
20542060

20552061
FunctionType* ftv = getMutable<FunctionType>(fnType);
20562062
ftv->isCheckedFunction = global->isCheckedFunction();
2057-
if (FFlag::LuauDeprecatedAttribute)
2058-
ftv->isDeprecatedFunction = global->hasAttribute(AstAttr::Type::Deprecated);
2063+
ftv->isDeprecatedFunction = global->hasAttribute(AstAttr::Type::Deprecated);
20592064

20602065
ftv->argNames.reserve(global->paramNames.size);
20612066
for (const auto& el : global->paramNames)
@@ -3710,8 +3715,7 @@ TypeId ConstraintGenerator::resolveFunctionType(
37103715
// how to quantify/instantiate it.
37113716
FunctionType ftv{TypeLevel{}, {}, {}, argTypes, returnTypes};
37123717
ftv.isCheckedFunction = fn->isCheckedFunction();
3713-
if (FFlag::LuauDeprecatedAttribute)
3714-
ftv.isDeprecatedFunction = fn->hasAttribute(AstAttr::Type::Deprecated);
3718+
ftv.isDeprecatedFunction = fn->hasAttribute(AstAttr::Type::Deprecated);
37153719

37163720
// This replicates the behavior of the appropriate FunctionType
37173721
// constructors.

Analysis/src/ConstraintSolver.cpp

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ LUAU_FASTFLAGVARIABLE(LuauHasPropProperBlock)
3636
LUAU_FASTFLAGVARIABLE(DebugLuauGreedyGeneralization)
3737
LUAU_FASTFLAG(LuauDeprecatedAttribute)
3838
LUAU_FASTFLAG(LuauNonReentrantGeneralization2)
39-
LUAU_FASTFLAG(LuauBidirectionalInferenceCollectIndexerTypes)
4039
LUAU_FASTFLAG(LuauNewTypeFunReductionChecks2)
4140
LUAU_FASTFLAGVARIABLE(LuauTrackInferredFunctionTypeFromCall)
4241
LUAU_FASTFLAGVARIABLE(LuauAddCallConstraintForIterableFunctions)
42+
LUAU_FASTFLAGVARIABLE(LuauGuardAgainstMalformedTypeAliasExpansion)
4343

4444
namespace Luau
4545
{
@@ -870,13 +870,10 @@ bool ConstraintSolver::tryDispatch(const GeneralizationConstraint& c, NotNull<co
870870
else
871871
unify(constraint, generalizedType, *generalizedTy);
872872

873-
if (FFlag::LuauDeprecatedAttribute)
873+
if (FunctionType* fty = getMutable<FunctionType>(follow(generalizedType)))
874874
{
875-
if (FunctionType* fty = getMutable<FunctionType>(follow(generalizedType)))
876-
{
877-
if (c.hasDeprecatedAttribute)
878-
fty->isDeprecatedFunction = true;
879-
}
875+
if (c.hasDeprecatedAttribute)
876+
fty->isDeprecatedFunction = true;
880877
}
881878
}
882879
else
@@ -933,6 +930,23 @@ bool ConstraintSolver::tryDispatch(const GeneralizationConstraint& c, NotNull<co
933930
}
934931
}
935932

933+
if (FFlag::DebugLuauGreedyGeneralization)
934+
{
935+
if (c.noGenerics)
936+
{
937+
if (auto ft = getMutable<FunctionType>(c.sourceType))
938+
{
939+
for (TypeId gen : ft->generics)
940+
asMutable(gen)->ty.emplace<BoundType>(builtinTypes->unknownType);
941+
ft->generics.clear();
942+
943+
for (TypePackId gen : ft->genericPacks)
944+
asMutable(gen)->ty.emplace<BoundTypePack>(builtinTypes->unknownTypePack);
945+
ft->genericPacks.clear();
946+
}
947+
}
948+
}
949+
936950
return true;
937951
}
938952

@@ -1213,7 +1227,19 @@ bool ConstraintSolver::tryDispatch(const TypeAliasExpansionConstraint& c, NotNul
12131227
// deterministic.
12141228
if (TypeId* cached = instantiatedAliases.find(signature))
12151229
{
1216-
bindResult(*cached);
1230+
// However, we might now be revealing a malformed mutually recursive
1231+
// alias. `instantiatedAliases` can change from underneath us in a
1232+
// way that can cause a cached type id to bind to itself if we don't
1233+
// do this check.
1234+
if (FFlag::LuauGuardAgainstMalformedTypeAliasExpansion && occursCheck(follow(c.target), *cached))
1235+
{
1236+
reportError(OccursCheckFailed{}, constraint->location);
1237+
bindResult(errorRecoveryType());
1238+
}
1239+
else
1240+
{
1241+
bindResult(*cached);
1242+
}
12171243
return true;
12181244
}
12191245

@@ -1633,45 +1659,13 @@ bool ConstraintSolver::tryDispatch(const FunctionCheckConstraint& c, NotNull<con
16331659
for (auto generic : ftv->generics)
16341660
{
16351661
replacements[generic] = builtinTypes->unknownType;
1636-
if (FFlag::LuauBidirectionalInferenceCollectIndexerTypes)
1637-
containsGenerics.generics.insert(generic);
1662+
containsGenerics.generics.insert(generic);
16381663
}
16391664

16401665
for (auto genericPack : ftv->genericPacks)
16411666
{
16421667
replacementPacks[genericPack] = builtinTypes->unknownTypePack;
1643-
if (FFlag::LuauBidirectionalInferenceCollectIndexerTypes)
1644-
containsGenerics.generics.insert(genericPack);
1645-
}
1646-
1647-
// If the type of the function has generics, we don't actually want to push any of the generics themselves
1648-
// into the argument types as expected types because this creates an unnecessary loop. Instead, we want to
1649-
// replace these types with `unknown` (and `...unknown`) to keep any structure but not create the cycle.
1650-
if (!FFlag::LuauBidirectionalInferenceCollectIndexerTypes)
1651-
{
1652-
if (!replacements.empty() || !replacementPacks.empty())
1653-
{
1654-
Replacer replacer{arena, std::move(replacements), std::move(replacementPacks)};
1655-
1656-
std::optional<TypeId> res = replacer.substitute(fn);
1657-
if (res)
1658-
{
1659-
if (*res != fn)
1660-
{
1661-
FunctionType* ftvMut = getMutable<FunctionType>(*res);
1662-
LUAU_ASSERT(ftvMut);
1663-
ftvMut->generics.clear();
1664-
ftvMut->genericPacks.clear();
1665-
}
1666-
1667-
fn = *res;
1668-
ftv = get<FunctionType>(*res);
1669-
LUAU_ASSERT(ftv);
1670-
1671-
// we've potentially copied type functions here, so we need to reproduce their reduce constraint.
1672-
reproduceConstraints(constraint->scope, constraint->location, replacer);
1673-
}
1674-
}
1668+
containsGenerics.generics.insert(genericPack);
16751669
}
16761670

16771671
const std::vector<TypeId> expectedArgs = flatten(ftv->argTypes).first;
@@ -1690,7 +1684,7 @@ bool ConstraintSolver::tryDispatch(const FunctionCheckConstraint& c, NotNull<con
16901684
(*c.astExpectedTypes)[expr] = expectedArgTy;
16911685

16921686
// Generic types are skipped over entirely, for now.
1693-
if (FFlag::LuauBidirectionalInferenceCollectIndexerTypes && containsGenerics.hasGeneric(expectedArgTy))
1687+
if (containsGenerics.hasGeneric(expectedArgTy))
16941688
continue;
16951689

16961690
const FunctionType* expectedLambdaTy = get<FunctionType>(expectedArgTy);
@@ -1857,7 +1851,7 @@ bool ConstraintSolver::tryDispatchHasIndexer(
18571851
return true;
18581852
}
18591853

1860-
if (auto ft = get<FreeType>(subjectType))
1854+
if (auto ft = getMutable<FreeType>(subjectType))
18611855
{
18621856
if (auto tbl = get<TableType>(follow(ft->upperBound)); tbl && tbl->indexer)
18631857
{
@@ -1874,7 +1868,19 @@ bool ConstraintSolver::tryDispatchHasIndexer(
18741868
TypeId upperBound =
18751869
arena->addType(TableType{/* props */ {}, TableIndexer{indexType, resultType}, TypeLevel{}, ft->scope, TableState::Unsealed});
18761870

1877-
unify(constraint, subjectType, upperBound);
1871+
if (FFlag::DebugLuauGreedyGeneralization)
1872+
{
1873+
TypeId sr = follow(simplifyIntersection(constraint->scope, constraint->location, ft->upperBound, upperBound));
1874+
1875+
if (get<NeverType>(sr))
1876+
bind(constraint, resultType, builtinTypes->errorType);
1877+
else
1878+
ft->upperBound = sr;
1879+
}
1880+
else
1881+
{
1882+
unify(constraint, subjectType, upperBound);
1883+
}
18781884

18791885
return true;
18801886
}

0 commit comments

Comments
 (0)