mirror of
https://github.com/luau-lang/luau.git
synced 2025-08-26 11:27:08 +01:00
Sync to upstream/release/675 (#1845)
## General - Introduce `Frontend::parseModules` for parsing a group of modules at once. - Support chained function types in the CST. ## New Type Solver - Enable write-only table properties (described in [this RFC](https://rfcs.luau.org/property-writeonly.html)). - Disable singleton inference for large tables to improve performance. - Fix a bug that occurs when we try to expand a type alias to itself. - Catch cancelation during the type-checking phase in addition to during constraint solving. - Fix stringification of the empty type pack: `()`. - Improve errors for calls being rejected on the primitive `function` type. - Rework generalization: We now generalize types as soon as the last constraint relating to them is finished. We think this will reduce the number of cases where type inference fails to complete and reduce the number of instances where `*blocked*` types appear in the inference result. ## VM/Runtime - Dynamically disable native execution for functions that incur a slowdown (relative to bytecode execution). - Improve names for `thread`/`closure`/`proto` in the Luau heap dump. --- Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Ariel Weiss <aaronweiss@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: Talha Pathan <tpathan@roblox.com> Co-authored-by: Varun Saini <vsaini@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> --------- Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: Alexander Youngblood <ayoungblood@roblox.com> Co-authored-by: Menarul Alam <malam@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Vighnesh <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> Co-authored-by: Ariel Weiss <aaronweiss@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com>
This commit is contained in:
parent
92cce5776c
commit
5965818283
70 changed files with 3153 additions and 925 deletions
|
@ -175,6 +175,10 @@ private:
|
||||||
|
|
||||||
std::vector<TypeId> unionsToSimplify;
|
std::vector<TypeId> unionsToSimplify;
|
||||||
|
|
||||||
|
// Used to keep track of when we are inside a large table and should
|
||||||
|
// opt *not* to do type inference for singletons.
|
||||||
|
size_t largeTableDepth = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fabricates a new free type belonging to a given scope.
|
* Fabricates a new free type belonging to a given scope.
|
||||||
* @param scope the scope the free type belongs to.
|
* @param scope the scope the free type belongs to.
|
||||||
|
|
|
@ -225,7 +225,7 @@ public:
|
||||||
bool tryDispatch(const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);
|
bool tryDispatch(const IterableConstraint& c, NotNull<const Constraint> constraint, bool force);
|
||||||
bool tryDispatch(const NameConstraint& c, NotNull<const Constraint> constraint);
|
bool tryDispatch(const NameConstraint& c, NotNull<const Constraint> constraint);
|
||||||
bool tryDispatch(const TypeAliasExpansionConstraint& c, NotNull<const Constraint> constraint);
|
bool tryDispatch(const TypeAliasExpansionConstraint& c, NotNull<const Constraint> constraint);
|
||||||
bool tryDispatch(const FunctionCallConstraint& c, NotNull<const Constraint> constraint);
|
bool tryDispatch(const FunctionCallConstraint& c, NotNull<const Constraint> constraint, bool force);
|
||||||
bool tryDispatch(const TableCheckConstraint& c, NotNull<const Constraint> constraint);
|
bool tryDispatch(const TableCheckConstraint& c, NotNull<const Constraint> constraint);
|
||||||
bool tryDispatch(const FunctionCheckConstraint& c, NotNull<const Constraint> constraint);
|
bool tryDispatch(const FunctionCheckConstraint& c, NotNull<const Constraint> constraint);
|
||||||
bool tryDispatch(const PrimitiveTypeConstraint& c, NotNull<const Constraint> constraint);
|
bool tryDispatch(const PrimitiveTypeConstraint& c, NotNull<const Constraint> constraint);
|
||||||
|
|
|
@ -166,6 +166,7 @@ struct Frontend
|
||||||
|
|
||||||
// Parse module graph and prepare SourceNode/SourceModule data, including required dependencies without running typechecking
|
// Parse module graph and prepare SourceNode/SourceModule data, including required dependencies without running typechecking
|
||||||
void parse(const ModuleName& name);
|
void parse(const ModuleName& name);
|
||||||
|
void parseModules(const std::vector<ModuleName>& name);
|
||||||
|
|
||||||
// Parse and typecheck module graph
|
// Parse and typecheck module graph
|
||||||
CheckResult check(const ModuleName& name, std::optional<FrontendOptions> optionOverride = {}); // new shininess
|
CheckResult check(const ModuleName& name, std::optional<FrontendOptions> optionOverride = {}); // new shininess
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct OverloadResolver
|
||||||
InsertionOrderedMap<TypeId, std::pair<OverloadResolver::Analysis, size_t>> resolution;
|
InsertionOrderedMap<TypeId, std::pair<OverloadResolver::Analysis, size_t>> resolution;
|
||||||
|
|
||||||
|
|
||||||
std::pair<OverloadResolver::Analysis, TypeId> selectOverload(TypeId ty, TypePackId args);
|
std::pair<OverloadResolver::Analysis, TypeId> selectOverload(TypeId ty, TypePackId args, bool useFreeTypeBounds);
|
||||||
void resolve(TypeId fnTy, const TypePack* args, AstExpr* selfExpr, const std::vector<AstExpr*>* argExprs);
|
void resolve(TypeId fnTy, const TypePack* args, AstExpr* selfExpr, const std::vector<AstExpr*>* argExprs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -72,6 +72,11 @@ struct SubtypingResult
|
||||||
/// isSubtype is false, depending on the input types.
|
/// isSubtype is false, depending on the input types.
|
||||||
SubtypingReasonings reasoning{kEmptyReasoning};
|
SubtypingReasonings reasoning{kEmptyReasoning};
|
||||||
|
|
||||||
|
// If this subtype result required testing free types, we might be making
|
||||||
|
// assumptions about what the free type eventually resolves to. If so,
|
||||||
|
// those assumptions are recorded here.
|
||||||
|
std::vector<SubtypeConstraint> assumedConstraints;
|
||||||
|
|
||||||
SubtypingResult& andAlso(const SubtypingResult& other);
|
SubtypingResult& andAlso(const SubtypingResult& other);
|
||||||
SubtypingResult& orElse(const SubtypingResult& other);
|
SubtypingResult& orElse(const SubtypingResult& other);
|
||||||
SubtypingResult& withBothComponent(TypePath::Component component);
|
SubtypingResult& withBothComponent(TypePath::Component component);
|
||||||
|
|
|
@ -24,7 +24,6 @@ LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTINT(LuauTypeInferIterationLimit)
|
LUAU_FASTINT(LuauTypeInferIterationLimit)
|
||||||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauMagicVariableNames)
|
LUAU_FASTFLAGVARIABLE(DebugLuauMagicVariableNames)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauAutocompleteUsesModuleForTypeCompatibility)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauAutocompleteMissingFollows)
|
LUAU_FASTFLAGVARIABLE(LuauAutocompleteMissingFollows)
|
||||||
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
||||||
|
|
||||||
|
@ -163,8 +162,6 @@ static bool checkTypeMatch(
|
||||||
UnifierSharedState unifierState(&iceReporter);
|
UnifierSharedState unifierState(&iceReporter);
|
||||||
SimplifierPtr simplifier = newSimplifier(NotNull{typeArena}, builtinTypes);
|
SimplifierPtr simplifier = newSimplifier(NotNull{typeArena}, builtinTypes);
|
||||||
Normalizer normalizer{typeArena, builtinTypes, NotNull{&unifierState}};
|
Normalizer normalizer{typeArena, builtinTypes, NotNull{&unifierState}};
|
||||||
if (FFlag::LuauAutocompleteUsesModuleForTypeCompatibility)
|
|
||||||
{
|
|
||||||
if (module.checkedInNewSolver)
|
if (module.checkedInNewSolver)
|
||||||
{
|
{
|
||||||
TypeCheckLimits limits;
|
TypeCheckLimits limits;
|
||||||
|
@ -199,43 +196,6 @@ static bool checkTypeMatch(
|
||||||
|
|
||||||
return unifier.canUnify(subTy, superTy).empty();
|
return unifier.canUnify(subTy, superTy).empty();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FFlag::LuauSolverV2)
|
|
||||||
{
|
|
||||||
TypeCheckLimits limits;
|
|
||||||
TypeFunctionRuntime typeFunctionRuntime{
|
|
||||||
NotNull{&iceReporter}, NotNull{&limits}
|
|
||||||
}; // TODO: maybe subtyping checks should not invoke user-defined type function runtime
|
|
||||||
|
|
||||||
unifierState.counters.recursionLimit = FInt::LuauTypeInferRecursionLimit;
|
|
||||||
unifierState.counters.iterationLimit = FInt::LuauTypeInferIterationLimit;
|
|
||||||
|
|
||||||
Subtyping subtyping{
|
|
||||||
builtinTypes,
|
|
||||||
NotNull{typeArena},
|
|
||||||
NotNull{simplifier.get()},
|
|
||||||
NotNull{&normalizer},
|
|
||||||
NotNull{&typeFunctionRuntime},
|
|
||||||
NotNull{&iceReporter}
|
|
||||||
};
|
|
||||||
|
|
||||||
return subtyping.isSubtype(subTy, superTy, scope).isSubtype;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Unifier unifier(NotNull<Normalizer>{&normalizer}, scope, Location(), Variance::Covariant);
|
|
||||||
|
|
||||||
// Cost of normalization can be too high for autocomplete response time requirements
|
|
||||||
unifier.normalize = false;
|
|
||||||
unifier.checkInhabited = false;
|
|
||||||
unifierState.counters.recursionLimit = FInt::LuauTypeInferRecursionLimit;
|
|
||||||
unifierState.counters.iterationLimit = FInt::LuauTypeInferIterationLimit;
|
|
||||||
|
|
||||||
return unifier.canUnify(subTy, superTy).empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeCorrectKind checkTypeCorrectKind(
|
static TypeCorrectKind checkTypeCorrectKind(
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
|
LUAU_FASTFLAGVARIABLE(LuauTableCloneClonesType3)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauMagicFreezeCheckBlocked2)
|
LUAU_FASTFLAGVARIABLE(LuauMagicFreezeCheckBlocked2)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauFormatUseLastPosition)
|
LUAU_FASTFLAGVARIABLE(LuauFormatUseLastPosition)
|
||||||
|
@ -310,8 +310,8 @@ void registerBuiltinGlobals(Frontend& frontend, GlobalTypes& globals, bool typeC
|
||||||
|
|
||||||
TypeArena& arena = globals.globalTypes;
|
TypeArena& arena = globals.globalTypes;
|
||||||
NotNull<BuiltinTypes> builtinTypes = globals.builtinTypes;
|
NotNull<BuiltinTypes> builtinTypes = globals.builtinTypes;
|
||||||
Scope* globalScope = nullptr; // NotNull<Scope> when removing FFlag::LuauNonReentrantGeneralization3
|
Scope* globalScope = nullptr; // NotNull<Scope> when removing FFlag::LuauEagerGeneralization
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
globalScope = globals.globalScope.get();
|
globalScope = globals.globalScope.get();
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2)
|
if (FFlag::LuauSolverV2)
|
||||||
|
|
|
@ -12,8 +12,6 @@ LUAU_FASTFLAG(LuauSolverV2)
|
||||||
|
|
||||||
// For each `Luau::clone` call, we will clone only up to N amount of types _and_ packs, as controlled by this limit.
|
// For each `Luau::clone` call, we will clone only up to N amount of types _and_ packs, as controlled by this limit.
|
||||||
LUAU_FASTINTVARIABLE(LuauTypeCloneIterationLimit, 100'000)
|
LUAU_FASTINTVARIABLE(LuauTypeCloneIterationLimit, 100'000)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauClonedTableAndFunctionTypesMustHaveScopes)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauDoNotClonePersistentBindings)
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -514,10 +512,7 @@ public:
|
||||||
free->scope = replacementForNullScope;
|
free->scope = replacementForNullScope;
|
||||||
}
|
}
|
||||||
else if (auto tt = getMutable<TableType>(target))
|
else if (auto tt = getMutable<TableType>(target))
|
||||||
{
|
|
||||||
if (FFlag::LuauClonedTableAndFunctionTypesMustHaveScopes)
|
|
||||||
tt->scope = replacementForNullScope;
|
tt->scope = replacementForNullScope;
|
||||||
}
|
|
||||||
|
|
||||||
(*types)[ty] = target;
|
(*types)[ty] = target;
|
||||||
queue.emplace_back(target);
|
queue.emplace_back(target);
|
||||||
|
@ -733,7 +728,7 @@ Binding cloneIncremental(const Binding& binding, TypeArena& dest, CloneState& cl
|
||||||
b.deprecatedSuggestion = binding.deprecatedSuggestion;
|
b.deprecatedSuggestion = binding.deprecatedSuggestion;
|
||||||
b.documentationSymbol = binding.documentationSymbol;
|
b.documentationSymbol = binding.documentationSymbol;
|
||||||
b.location = binding.location;
|
b.location = binding.location;
|
||||||
b.typeId = FFlag::LuauDoNotClonePersistentBindings && binding.typeId->persistent ? binding.typeId : cloner.clone(binding.typeId);
|
b.typeId = binding.typeId->persistent ? binding.typeId : cloner.clone(binding.typeId);
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "Luau/Constraint.h"
|
#include "Luau/Constraint.h"
|
||||||
#include "Luau/VisitType.h"
|
#include "Luau/VisitType.h"
|
||||||
|
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -17,8 +17,8 @@ Constraint::Constraint(NotNull<Scope> scope, const Location& location, Constrain
|
||||||
|
|
||||||
struct ReferenceCountInitializer : TypeOnceVisitor
|
struct ReferenceCountInitializer : TypeOnceVisitor
|
||||||
{
|
{
|
||||||
|
|
||||||
DenseHashSet<TypeId>* result;
|
DenseHashSet<TypeId>* result;
|
||||||
|
bool traverseIntoTypeFunctions = true;
|
||||||
|
|
||||||
explicit ReferenceCountInitializer(DenseHashSet<TypeId>* result)
|
explicit ReferenceCountInitializer(DenseHashSet<TypeId>* result)
|
||||||
: result(result)
|
: result(result)
|
||||||
|
@ -51,7 +51,7 @@ struct ReferenceCountInitializer : TypeOnceVisitor
|
||||||
|
|
||||||
bool visit(TypeId, const TypeFunctionInstanceType&) override
|
bool visit(TypeId, const TypeFunctionInstanceType&) override
|
||||||
{
|
{
|
||||||
return FFlag::DebugLuauGreedyGeneralization;
|
return FFlag::LuauEagerGeneralization && traverseIntoTypeFunctions;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,10 +104,12 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
|
||||||
{
|
{
|
||||||
rci.traverse(fchc->argsPack);
|
rci.traverse(fchc->argsPack);
|
||||||
}
|
}
|
||||||
else if (auto fcc = get<FunctionCallConstraint>(*this); fcc && FFlag::DebugLuauGreedyGeneralization)
|
else if (auto fcc = get<FunctionCallConstraint>(*this); fcc && FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
|
rci.traverseIntoTypeFunctions = false;
|
||||||
rci.traverse(fcc->fn);
|
rci.traverse(fcc->fn);
|
||||||
rci.traverse(fcc->argsPack);
|
rci.traverse(fcc->argsPack);
|
||||||
|
rci.traverseIntoTypeFunctions = true;
|
||||||
}
|
}
|
||||||
else if (auto ptc = get<PrimitiveTypeConstraint>(*this))
|
else if (auto ptc = get<PrimitiveTypeConstraint>(*this))
|
||||||
{
|
{
|
||||||
|
@ -116,12 +118,12 @@ DenseHashSet<TypeId> Constraint::getMaybeMutatedFreeTypes() const
|
||||||
else if (auto hpc = get<HasPropConstraint>(*this))
|
else if (auto hpc = get<HasPropConstraint>(*this))
|
||||||
{
|
{
|
||||||
rci.traverse(hpc->resultType);
|
rci.traverse(hpc->resultType);
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
rci.traverse(hpc->subjectType);
|
rci.traverse(hpc->subjectType);
|
||||||
}
|
}
|
||||||
else if (auto hic = get<HasIndexerConstraint>(*this))
|
else if (auto hic = get<HasIndexerConstraint>(*this))
|
||||||
{
|
{
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
rci.traverse(hic->subjectType);
|
rci.traverse(hic->subjectType);
|
||||||
rci.traverse(hic->resultType);
|
rci.traverse(hic->resultType);
|
||||||
// `HasIndexerConstraint` should not mutate `indexType`.
|
// `HasIndexerConstraint` should not mutate `indexType`.
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
LUAU_FASTINT(LuauCheckRecursionLimit)
|
LUAU_FASTINT(LuauCheckRecursionLimit)
|
||||||
LUAU_FASTFLAG(DebugLuauLogSolverToJson)
|
LUAU_FASTFLAG(DebugLuauLogSolverToJson)
|
||||||
LUAU_FASTFLAG(DebugLuauMagicTypes)
|
LUAU_FASTFLAG(DebugLuauMagicTypes)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauRetainDefinitionAliasLocations)
|
LUAU_FASTFLAGVARIABLE(LuauRetainDefinitionAliasLocations)
|
||||||
|
|
||||||
|
@ -42,12 +42,15 @@ LUAU_FASTFLAGVARIABLE(LuauWeakNilRefinementType)
|
||||||
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
||||||
LUAU_FASTFLAG(LuauGlobalVariableModuleIsolation)
|
LUAU_FASTFLAG(LuauGlobalVariableModuleIsolation)
|
||||||
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions)
|
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauEnableWriteOnlyProperties)
|
||||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||||
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauAvoidDoubleNegation)
|
LUAU_FASTFLAGVARIABLE(LuauAvoidDoubleNegation)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauSimplifyOutOfLine)
|
LUAU_FASTFLAGVARIABLE(LuauSimplifyOutOfLine)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauDisablePrimitiveInferenceInLargeTables)
|
||||||
|
LUAU_FASTINTVARIABLE(LuauPrimitiveInferenceInTableLimit, 500)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -251,7 +254,7 @@ void ConstraintGenerator::visitModuleRoot(AstStatBlock* block)
|
||||||
rootScope->location = block->location;
|
rootScope->location = block->location;
|
||||||
module->astScopes[block] = NotNull{scope.get()};
|
module->astScopes[block] = NotNull{scope.get()};
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.emplace_back();
|
interiorFreeTypes.emplace_back();
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.emplace_back();
|
DEPRECATED_interiorTypes.emplace_back();
|
||||||
|
@ -287,7 +290,7 @@ void ConstraintGenerator::visitModuleRoot(AstStatBlock* block)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
scope->interiorFreeTypes = std::move(interiorFreeTypes.back().types);
|
scope->interiorFreeTypes = std::move(interiorFreeTypes.back().types);
|
||||||
scope->interiorFreeTypePacks = std::move(interiorFreeTypes.back().typePacks);
|
scope->interiorFreeTypePacks = std::move(interiorFreeTypes.back().typePacks);
|
||||||
|
@ -306,7 +309,7 @@ void ConstraintGenerator::visitModuleRoot(AstStatBlock* block)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.pop_back();
|
interiorFreeTypes.pop_back();
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.pop_back();
|
DEPRECATED_interiorTypes.pop_back();
|
||||||
|
@ -344,13 +347,13 @@ void ConstraintGenerator::visitFragmentRoot(const ScopePtr& resumeScope, AstStat
|
||||||
// We prepopulate global data in the resumeScope to avoid writing data into the old modules scopes
|
// We prepopulate global data in the resumeScope to avoid writing data into the old modules scopes
|
||||||
prepopulateGlobalScopeForFragmentTypecheck(globalScope, resumeScope, block);
|
prepopulateGlobalScopeForFragmentTypecheck(globalScope, resumeScope, block);
|
||||||
// Pre
|
// Pre
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.emplace_back();
|
interiorFreeTypes.emplace_back();
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.emplace_back();
|
DEPRECATED_interiorTypes.emplace_back();
|
||||||
visitBlockWithoutChildScope(resumeScope, block);
|
visitBlockWithoutChildScope(resumeScope, block);
|
||||||
// Post
|
// Post
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.pop_back();
|
interiorFreeTypes.pop_back();
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.pop_back();
|
DEPRECATED_interiorTypes.pop_back();
|
||||||
|
@ -380,12 +383,12 @@ void ConstraintGenerator::visitFragmentRoot(const ScopePtr& resumeScope, AstStat
|
||||||
|
|
||||||
TypeId ConstraintGenerator::freshType(const ScopePtr& scope, Polarity polarity)
|
TypeId ConstraintGenerator::freshType(const ScopePtr& scope, Polarity polarity)
|
||||||
{
|
{
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
auto ft = Luau::freshType(arena, builtinTypes, scope.get(), polarity);
|
auto ft = Luau::freshType(arena, builtinTypes, scope.get(), polarity);
|
||||||
interiorFreeTypes.back().types.push_back(ft);
|
interiorFreeTypes.back().types.push_back(ft);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
freeTypes.insert(ft);
|
freeTypes.insert(ft);
|
||||||
|
|
||||||
return ft;
|
return ft;
|
||||||
|
@ -402,7 +405,7 @@ TypePackId ConstraintGenerator::freshTypePack(const ScopePtr& scope, Polarity po
|
||||||
{
|
{
|
||||||
FreeTypePack f{scope.get(), polarity};
|
FreeTypePack f{scope.get(), polarity};
|
||||||
TypePackId result = arena->addTypePack(TypePackVar{std::move(f)});
|
TypePackId result = arena->addTypePack(TypePackVar{std::move(f)});
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.back().typePacks.push_back(result);
|
interiorFreeTypes.back().typePacks.push_back(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1393,7 +1396,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatLocalFuncti
|
||||||
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
|
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
|
||||||
sig.bodyScope->bindings[function->name] = Binding{sig.signature, function->name->location};
|
sig.bodyScope->bindings[function->name] = Binding{sig.signature, function->name->location};
|
||||||
|
|
||||||
bool sigFullyDefined = FFlag::DebugLuauGreedyGeneralization ? false : !hasFreeType(sig.signature);
|
bool sigFullyDefined = FFlag::LuauEagerGeneralization ? false : !hasFreeType(sig.signature);
|
||||||
if (sigFullyDefined)
|
if (sigFullyDefined)
|
||||||
emplaceType<BoundType>(asMutable(functionType), sig.signature);
|
emplaceType<BoundType>(asMutable(functionType), sig.signature);
|
||||||
|
|
||||||
|
@ -1453,7 +1456,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f
|
||||||
|
|
||||||
Checkpoint start = checkpoint(this);
|
Checkpoint start = checkpoint(this);
|
||||||
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
|
FunctionSignature sig = checkFunctionSignature(scope, function->func, /* expectedType */ std::nullopt, function->name->location);
|
||||||
bool sigFullyDefined = FFlag::DebugLuauGreedyGeneralization ? false : !hasFreeType(sig.signature);
|
bool sigFullyDefined = FFlag::LuauEagerGeneralization ? false : !hasFreeType(sig.signature);
|
||||||
|
|
||||||
DefId def = dfg->getDef(function->name);
|
DefId def = dfg->getDef(function->name);
|
||||||
|
|
||||||
|
@ -1767,7 +1770,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatTypeFunctio
|
||||||
// Place this function as a child of the non-type function scope
|
// Place this function as a child of the non-type function scope
|
||||||
scope->children.push_back(NotNull{sig.signatureScope.get()});
|
scope->children.push_back(NotNull{sig.signatureScope.get()});
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.emplace_back();
|
interiorFreeTypes.emplace_back();
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.push_back(std::vector<TypeId>{});
|
DEPRECATED_interiorTypes.push_back(std::vector<TypeId>{});
|
||||||
|
@ -1785,7 +1788,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatTypeFunctio
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
sig.signatureScope->interiorFreeTypes = std::move(interiorFreeTypes.back().types);
|
sig.signatureScope->interiorFreeTypes = std::move(interiorFreeTypes.back().types);
|
||||||
sig.signatureScope->interiorFreeTypePacks = std::move(interiorFreeTypes.back().typePacks);
|
sig.signatureScope->interiorFreeTypePacks = std::move(interiorFreeTypes.back().typePacks);
|
||||||
|
@ -1794,7 +1797,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatTypeFunctio
|
||||||
sig.signatureScope->interiorFreeTypes = std::move(DEPRECATED_interiorTypes.back());
|
sig.signatureScope->interiorFreeTypes = std::move(DEPRECATED_interiorTypes.back());
|
||||||
|
|
||||||
getMutable<BlockedType>(generalizedTy)->setOwner(gc);
|
getMutable<BlockedType>(generalizedTy)->setOwner(gc);
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.pop_back();
|
interiorFreeTypes.pop_back();
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.pop_back();
|
DEPRECATED_interiorTypes.pop_back();
|
||||||
|
@ -2358,14 +2361,10 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
|
||||||
argEndCheckpoint,
|
argEndCheckpoint,
|
||||||
this,
|
this,
|
||||||
[checkConstraint, callConstraint](const ConstraintPtr& constraint)
|
[checkConstraint, callConstraint](const ConstraintPtr& constraint)
|
||||||
{
|
|
||||||
if (!(FFlag::DebugLuauGreedyGeneralization && get<PrimitiveTypeConstraint>(*constraint)))
|
|
||||||
{
|
{
|
||||||
constraint->dependencies.emplace_back(checkConstraint);
|
constraint->dependencies.emplace_back(checkConstraint);
|
||||||
|
|
||||||
callConstraint->dependencies.emplace_back(constraint.get());
|
callConstraint->dependencies.emplace_back(constraint.get());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return InferencePack{rets, {refinementArena.variadic(returnRefinements)}};
|
return InferencePack{rets, {refinementArena.variadic(returnRefinements)}};
|
||||||
|
@ -2457,8 +2456,17 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprConstantStrin
|
||||||
if (forceSingleton)
|
if (forceSingleton)
|
||||||
return Inference{arena->addType(SingletonType{StringSingleton{std::string{string->value.data, string->value.size}}})};
|
return Inference{arena->addType(SingletonType{StringSingleton{std::string{string->value.data, string->value.size}}})};
|
||||||
|
|
||||||
|
// Consider a table like:
|
||||||
|
//
|
||||||
|
// local DICTIONARY = { "aback", "abacus", "abandon", --[[ so on and so forth ]] }
|
||||||
|
//
|
||||||
|
// The intent is (probably) not for this to be an array-like table with a massive
|
||||||
|
// union for the value, but instead a `{ string }`.
|
||||||
|
if (FFlag::LuauDisablePrimitiveInferenceInLargeTables && largeTableDepth > 0)
|
||||||
|
return Inference{builtinTypes->stringType};
|
||||||
|
|
||||||
TypeId freeTy = nullptr;
|
TypeId freeTy = nullptr;
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
freeTy = freshType(scope, Polarity::Positive);
|
freeTy = freshType(scope, Polarity::Positive);
|
||||||
FreeType* ft = getMutable<FreeType>(freeTy);
|
FreeType* ft = getMutable<FreeType>(freeTy);
|
||||||
|
@ -2484,8 +2492,22 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprConstantBool*
|
||||||
if (forceSingleton)
|
if (forceSingleton)
|
||||||
return Inference{singletonType};
|
return Inference{singletonType};
|
||||||
|
|
||||||
|
// Consider a table like:
|
||||||
|
//
|
||||||
|
// local FLAGS = {
|
||||||
|
// Foo = true,
|
||||||
|
// Bar = false,
|
||||||
|
// Baz = true,
|
||||||
|
// -- so on and so forth
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The intent is (probably) not for this to be a table where each element
|
||||||
|
// is potentially `true` or `false` as a singleton, but just `boolean`.
|
||||||
|
if (FFlag::LuauDisablePrimitiveInferenceInLargeTables && largeTableDepth > 0)
|
||||||
|
return Inference{builtinTypes->booleanType};
|
||||||
|
|
||||||
TypeId freeTy = nullptr;
|
TypeId freeTy = nullptr;
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
freeTy = freshType(scope, Polarity::Positive);
|
freeTy = freshType(scope, Polarity::Positive);
|
||||||
FreeType* ft = getMutable<FreeType>(freeTy);
|
FreeType* ft = getMutable<FreeType>(freeTy);
|
||||||
|
@ -2646,7 +2668,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprFunction* fun
|
||||||
Checkpoint startCheckpoint = checkpoint(this);
|
Checkpoint startCheckpoint = checkpoint(this);
|
||||||
FunctionSignature sig = checkFunctionSignature(scope, func, expectedType);
|
FunctionSignature sig = checkFunctionSignature(scope, func, expectedType);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.emplace_back();
|
interiorFreeTypes.emplace_back();
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.push_back(std::vector<TypeId>{});
|
DEPRECATED_interiorTypes.push_back(std::vector<TypeId>{});
|
||||||
|
@ -2664,7 +2686,7 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprFunction* fun
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
sig.signatureScope->interiorFreeTypes = std::move(interiorFreeTypes.back().types);
|
sig.signatureScope->interiorFreeTypes = std::move(interiorFreeTypes.back().types);
|
||||||
sig.signatureScope->interiorFreeTypePacks = std::move(interiorFreeTypes.back().typePacks);
|
sig.signatureScope->interiorFreeTypePacks = std::move(interiorFreeTypes.back().typePacks);
|
||||||
|
@ -3168,7 +3190,10 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr,
|
||||||
ttv->definitionLocation = expr->location;
|
ttv->definitionLocation = expr->location;
|
||||||
ttv->scope = scope.get();
|
ttv->scope = scope.get();
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauDisablePrimitiveInferenceInLargeTables && FInt::LuauPrimitiveInferenceInTableLimit > 0 && expr->items.size > size_t(FInt::LuauPrimitiveInferenceInTableLimit))
|
||||||
|
largeTableDepth++;
|
||||||
|
|
||||||
|
if (FFlag::LuauEagerGeneralization)
|
||||||
interiorFreeTypes.back().types.push_back(ty);
|
interiorFreeTypes.back().types.push_back(ty);
|
||||||
else
|
else
|
||||||
DEPRECATED_interiorTypes.back().push_back(ty);
|
DEPRECATED_interiorTypes.back().push_back(ty);
|
||||||
|
@ -3276,6 +3301,9 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprTable* expr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FFlag::LuauDisablePrimitiveInferenceInLargeTables && FInt::LuauPrimitiveInferenceInTableLimit > 0 && expr->items.size > size_t(FInt::LuauPrimitiveInferenceInTableLimit))
|
||||||
|
largeTableDepth--;
|
||||||
|
|
||||||
return Inference{ty};
|
return Inference{ty};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3425,7 +3453,7 @@ ConstraintGenerator::FunctionSignature ConstraintGenerator::checkFunctionSignatu
|
||||||
|
|
||||||
LUAU_ASSERT(nullptr != varargPack);
|
LUAU_ASSERT(nullptr != varargPack);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// Some of the types in argTypes will eventually be generics, and some
|
// Some of the types in argTypes will eventually be generics, and some
|
||||||
// will not. The ones that are not generic will be pruned when
|
// will not. The ones that are not generic will be pruned when
|
||||||
|
@ -3490,7 +3518,7 @@ ConstraintGenerator::FunctionSignature ConstraintGenerator::checkFunctionSignatu
|
||||||
if (expectedType && get<FreeType>(*expectedType))
|
if (expectedType && get<FreeType>(*expectedType))
|
||||||
bindFreeType(*expectedType, actualFunctionType);
|
bindFreeType(*expectedType, actualFunctionType);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
scopeToFunction[signatureScope.get()] = actualFunctionType;
|
scopeToFunction[signatureScope.get()] = actualFunctionType;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -3625,8 +3653,11 @@ TypeId ConstraintGenerator::resolveTableType(const ScopePtr& scope, AstType* ty,
|
||||||
p.readTy = propTy;
|
p.readTy = propTy;
|
||||||
break;
|
break;
|
||||||
case AstTableAccess::Write:
|
case AstTableAccess::Write:
|
||||||
|
if (!FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
{
|
||||||
reportError(*prop.accessLocation, GenericError{"write keyword is illegal here"});
|
reportError(*prop.accessLocation, GenericError{"write keyword is illegal here"});
|
||||||
p.readTy = propTy;
|
p.readTy = propTy;
|
||||||
|
}
|
||||||
p.writeTy = propTy;
|
p.writeTy = propTy;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -33,12 +33,12 @@ LUAU_FASTFLAGVARIABLE(DebugLuauLogBindings)
|
||||||
LUAU_FASTINTVARIABLE(LuauSolverRecursionLimit, 500)
|
LUAU_FASTINTVARIABLE(LuauSolverRecursionLimit, 500)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauEqSatSimplification)
|
LUAU_FASTFLAGVARIABLE(DebugLuauEqSatSimplification)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauHasPropProperBlock)
|
LUAU_FASTFLAGVARIABLE(LuauHasPropProperBlock)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauDeprecatedAttribute)
|
LUAU_FASTFLAG(LuauDeprecatedAttribute)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauTrackInferredFunctionTypeFromCall)
|
LUAU_FASTFLAGVARIABLE(LuauTrackInferredFunctionTypeFromCall)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauAddCallConstraintForIterableFunctions)
|
LUAU_FASTFLAGVARIABLE(LuauAddCallConstraintForIterableFunctions)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauGuardAgainstMalformedTypeAliasExpansion)
|
LUAU_FASTFLAGVARIABLE(LuauGuardAgainstMalformedTypeAliasExpansion2)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauInsertErrorTypesIntoIndexerResult)
|
LUAU_FASTFLAGVARIABLE(LuauInsertErrorTypesIntoIndexerResult)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauClipVariadicAnysFromArgsToGenericFuncs2)
|
LUAU_FASTFLAGVARIABLE(LuauClipVariadicAnysFromArgsToGenericFuncs2)
|
||||||
LUAU_FASTFLAG(LuauSubtypeGenericsAndNegations)
|
LUAU_FASTFLAG(LuauSubtypeGenericsAndNegations)
|
||||||
|
@ -418,7 +418,7 @@ void ConstraintSolver::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free types that have no constraints at all can be generalized right away.
|
// Free types that have no constraints at all can be generalized right away.
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
for (TypeId ty : constraintSet.freeTypes)
|
for (TypeId ty : constraintSet.freeTypes)
|
||||||
{
|
{
|
||||||
|
@ -479,7 +479,7 @@ void ConstraintSolver::run()
|
||||||
// expansion types, etc, so we need to follow it.
|
// expansion types, etc, so we need to follow it.
|
||||||
ty = follow(ty);
|
ty = follow(ty);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (seen.contains(ty))
|
if (seen.contains(ty))
|
||||||
continue;
|
continue;
|
||||||
|
@ -498,7 +498,7 @@ void ConstraintSolver::run()
|
||||||
if (refCount <= 1)
|
if (refCount <= 1)
|
||||||
unblock(ty, Location{});
|
unblock(ty, Location{});
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization && refCount == 0)
|
if (FFlag::LuauEagerGeneralization && refCount == 0)
|
||||||
generalizeOneType(ty);
|
generalizeOneType(ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -676,7 +676,7 @@ void ConstraintSolver::initFreeTypeTracking()
|
||||||
auto [refCount, _] = unresolvedConstraints.try_insert(ty, 0);
|
auto [refCount, _] = unresolvedConstraints.try_insert(ty, 0);
|
||||||
refCount += 1;
|
refCount += 1;
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
auto [it, fresh] = mutatedFreeTypeToConstraint.try_emplace(ty, nullptr);
|
auto [it, fresh] = mutatedFreeTypeToConstraint.try_emplace(ty, nullptr);
|
||||||
it->second.insert(c.get());
|
it->second.insert(c.get());
|
||||||
|
@ -691,7 +691,7 @@ void ConstraintSolver::initFreeTypeTracking()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also check flag integrity while we're here
|
// Also check flag integrity while we're here
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
LUAU_ASSERT(FFlag::LuauSubtypeGenericsAndNegations);
|
LUAU_ASSERT(FFlag::LuauSubtypeGenericsAndNegations);
|
||||||
LUAU_ASSERT(FFlag::LuauNoMoreInjectiveTypeFunctions);
|
LUAU_ASSERT(FFlag::LuauNoMoreInjectiveTypeFunctions);
|
||||||
|
@ -739,7 +739,7 @@ void ConstraintSolver::bind(NotNull<const Constraint> constraint, TypeId ty, Typ
|
||||||
constraint, ty, constraint->scope, builtinTypes->neverType, builtinTypes->unknownType, Polarity::Mixed
|
constraint, ty, constraint->scope, builtinTypes->neverType, builtinTypes->unknownType, Polarity::Mixed
|
||||||
); // FIXME? Is this the right polarity?
|
); // FIXME? Is this the right polarity?
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
trackInteriorFreeType(constraint->scope, ty);
|
trackInteriorFreeType(constraint->scope, ty);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -806,7 +806,7 @@ bool ConstraintSolver::tryDispatch(NotNull<const Constraint> constraint, bool fo
|
||||||
else if (auto taec = get<TypeAliasExpansionConstraint>(*constraint))
|
else if (auto taec = get<TypeAliasExpansionConstraint>(*constraint))
|
||||||
success = tryDispatch(*taec, constraint);
|
success = tryDispatch(*taec, constraint);
|
||||||
else if (auto fcc = get<FunctionCallConstraint>(*constraint))
|
else if (auto fcc = get<FunctionCallConstraint>(*constraint))
|
||||||
success = tryDispatch(*fcc, constraint);
|
success = tryDispatch(*fcc, constraint, force);
|
||||||
else if (auto fcc = get<FunctionCheckConstraint>(*constraint))
|
else if (auto fcc = get<FunctionCheckConstraint>(*constraint))
|
||||||
success = tryDispatch(*fcc, constraint);
|
success = tryDispatch(*fcc, constraint);
|
||||||
else if (auto tcc = get<TableCheckConstraint>(*constraint))
|
else if (auto tcc = get<TableCheckConstraint>(*constraint))
|
||||||
|
@ -900,7 +900,7 @@ bool ConstraintSolver::tryDispatch(const GeneralizationConstraint& c, NotNull<co
|
||||||
{
|
{
|
||||||
for (TypeId ty : *constraint->scope->interiorFreeTypes) // NOLINT(bugprone-unchecked-optional-access)
|
for (TypeId ty : *constraint->scope->interiorFreeTypes) // NOLINT(bugprone-unchecked-optional-access)
|
||||||
{
|
{
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
ty = follow(ty);
|
ty = follow(ty);
|
||||||
if (auto freeTy = get<FreeType>(ty))
|
if (auto freeTy = get<FreeType>(ty))
|
||||||
|
@ -922,7 +922,7 @@ bool ConstraintSolver::tryDispatch(const GeneralizationConstraint& c, NotNull<co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (constraint->scope->interiorFreeTypePacks)
|
if (constraint->scope->interiorFreeTypePacks)
|
||||||
{
|
{
|
||||||
|
@ -942,7 +942,7 @@ bool ConstraintSolver::tryDispatch(const GeneralizationConstraint& c, NotNull<co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (c.noGenerics)
|
if (c.noGenerics)
|
||||||
{
|
{
|
||||||
|
@ -1158,8 +1158,17 @@ bool ConstraintSolver::tryDispatch(const TypeAliasExpansionConstraint& c, NotNul
|
||||||
{
|
{
|
||||||
auto cTarget = follow(c.target);
|
auto cTarget = follow(c.target);
|
||||||
LUAU_ASSERT(get<PendingExpansionType>(cTarget));
|
LUAU_ASSERT(get<PendingExpansionType>(cTarget));
|
||||||
|
// We do this check here to ensure that we don't bind an alias to itself
|
||||||
|
if (FFlag::LuauGuardAgainstMalformedTypeAliasExpansion2 && occursCheck(cTarget, result))
|
||||||
|
{
|
||||||
|
reportError(OccursCheckFailed{}, constraint->location);
|
||||||
|
bind(constraint, cTarget, builtinTypes->errorRecoveryType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
shiftReferences(cTarget, result);
|
shiftReferences(cTarget, result);
|
||||||
bind(constraint, cTarget, result);
|
bind(constraint, cTarget, result);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<TypeFun> tf = (petv->prefix) ? constraint->scope->lookupImportedType(petv->prefix->value, petv->name.value)
|
std::optional<TypeFun> tf = (petv->prefix) ? constraint->scope->lookupImportedType(petv->prefix->value, petv->name.value)
|
||||||
|
@ -1238,20 +1247,8 @@ bool ConstraintSolver::tryDispatch(const TypeAliasExpansionConstraint& c, NotNul
|
||||||
// instantiate the alias again, since the instantiation should be
|
// instantiate the alias again, since the instantiation should be
|
||||||
// deterministic.
|
// deterministic.
|
||||||
if (TypeId* cached = instantiatedAliases.find(signature))
|
if (TypeId* cached = instantiatedAliases.find(signature))
|
||||||
{
|
|
||||||
// However, we might now be revealing a malformed mutually recursive
|
|
||||||
// alias. `instantiatedAliases` can change from underneath us in a
|
|
||||||
// way that can cause a cached type id to bind to itself if we don't
|
|
||||||
// do this check.
|
|
||||||
if (FFlag::LuauGuardAgainstMalformedTypeAliasExpansion && occursCheck(follow(c.target), *cached))
|
|
||||||
{
|
|
||||||
reportError(OccursCheckFailed{}, constraint->location);
|
|
||||||
bindResult(errorRecoveryType());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
bindResult(*cached);
|
bindResult(*cached);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1385,13 +1382,13 @@ void ConstraintSolver::fillInDiscriminantTypes(NotNull<const Constraint> constra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConstraintSolver::tryDispatch(const FunctionCallConstraint& c, NotNull<const Constraint> constraint)
|
bool ConstraintSolver::tryDispatch(const FunctionCallConstraint& c, NotNull<const Constraint> constraint, bool force)
|
||||||
{
|
{
|
||||||
TypeId fn = follow(c.fn);
|
TypeId fn = follow(c.fn);
|
||||||
TypePackId argsPack = follow(c.argsPack);
|
TypePackId argsPack = follow(c.argsPack);
|
||||||
TypePackId result = follow(c.result);
|
TypePackId result = follow(c.result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (isBlocked(fn))
|
if (isBlocked(fn))
|
||||||
return block(c.fn, constraint);
|
return block(c.fn, constraint);
|
||||||
|
@ -1521,7 +1518,7 @@ bool ConstraintSolver::tryDispatch(const FunctionCallConstraint& c, NotNull<cons
|
||||||
NotNull{&limits},
|
NotNull{&limits},
|
||||||
constraint->location
|
constraint->location
|
||||||
};
|
};
|
||||||
auto [status, overload] = resolver.selectOverload(fn, argsPack);
|
auto [status, overload] = resolver.selectOverload(fn, argsPack, /*useFreeTypeBounds*/ force);
|
||||||
TypeId overloadToUse = fn;
|
TypeId overloadToUse = fn;
|
||||||
if (status == OverloadResolver::Analysis::Ok)
|
if (status == OverloadResolver::Analysis::Ok)
|
||||||
overloadToUse = overload;
|
overloadToUse = overload;
|
||||||
|
@ -1531,7 +1528,7 @@ bool ConstraintSolver::tryDispatch(const FunctionCallConstraint& c, NotNull<cons
|
||||||
|
|
||||||
const bool occursCheckPassed = u2.unify(overloadToUse, inferredTy);
|
const bool occursCheckPassed = u2.unify(overloadToUse, inferredTy);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
for (TypeId freeTy : u2.newFreshTypes)
|
for (TypeId freeTy : u2.newFreshTypes)
|
||||||
trackInteriorFreeType(constraint->scope, freeTy);
|
trackInteriorFreeType(constraint->scope, freeTy);
|
||||||
|
@ -1945,7 +1942,7 @@ bool ConstraintSolver::tryDispatchHasIndexer(
|
||||||
TypeId upperBound =
|
TypeId upperBound =
|
||||||
arena->addType(TableType{/* props */ {}, TableIndexer{indexType, resultType}, TypeLevel{}, ft->scope, TableState::Unsealed});
|
arena->addType(TableType{/* props */ {}, TableIndexer{indexType, resultType}, TypeLevel{}, ft->scope, TableState::Unsealed});
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
TypeId sr = follow(simplifyIntersection(constraint->scope, constraint->location, ft->upperBound, upperBound));
|
TypeId sr = follow(simplifyIntersection(constraint->scope, constraint->location, ft->upperBound, upperBound));
|
||||||
|
|
||||||
|
@ -1976,7 +1973,7 @@ bool ConstraintSolver::tryDispatchHasIndexer(
|
||||||
|
|
||||||
FreeType freeResult{tt->scope, builtinTypes->neverType, builtinTypes->unknownType, Polarity::Mixed};
|
FreeType freeResult{tt->scope, builtinTypes->neverType, builtinTypes->unknownType, Polarity::Mixed};
|
||||||
emplace<FreeType>(constraint, resultType, freeResult);
|
emplace<FreeType>(constraint, resultType, freeResult);
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
trackInteriorFreeType(constraint->scope, resultType);
|
trackInteriorFreeType(constraint->scope, resultType);
|
||||||
|
|
||||||
tt->indexer = TableIndexer{indexType, resultType};
|
tt->indexer = TableIndexer{indexType, resultType};
|
||||||
|
@ -2166,7 +2163,7 @@ bool ConstraintSolver::tryDispatch(const AssignPropConstraint& c, NotNull<const
|
||||||
{
|
{
|
||||||
auto lhsFreeUpperBound = follow(lhsFree->upperBound);
|
auto lhsFreeUpperBound = follow(lhsFree->upperBound);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
const auto [blocked, maybeTy, isIndex] = lookupTableProp(constraint, lhsType, propName, ValueContext::LValue);
|
const auto [blocked, maybeTy, isIndex] = lookupTableProp(constraint, lhsType, propName, ValueContext::LValue);
|
||||||
if (!blocked.empty())
|
if (!blocked.empty())
|
||||||
|
@ -3067,7 +3064,7 @@ TablePropLookupResult ConstraintSolver::lookupTableProp(
|
||||||
{
|
{
|
||||||
const TypeId upperBound = follow(ft->upperBound);
|
const TypeId upperBound = follow(ft->upperBound);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
|
if (get<TableType>(upperBound) || get<PrimitiveType>(upperBound))
|
||||||
{
|
{
|
||||||
|
@ -3535,7 +3532,7 @@ void ConstraintSolver::shiftReferences(TypeId source, TypeId target)
|
||||||
|
|
||||||
// Any constraint that might have mutated source may now mutate target
|
// Any constraint that might have mutated source may now mutate target
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
auto it = mutatedFreeTypeToConstraint.find(source);
|
auto it = mutatedFreeTypeToConstraint.find(source);
|
||||||
if (it != mutatedFreeTypeToConstraint.end())
|
if (it != mutatedFreeTypeToConstraint.end())
|
||||||
|
|
|
@ -18,7 +18,6 @@ LUAU_FASTFLAGVARIABLE(LuauDfgScopeStackNotNull)
|
||||||
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauDoNotAddUpvalueTypesToLocalType)
|
LUAU_FASTFLAGVARIABLE(LuauDoNotAddUpvalueTypesToLocalType)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauDfgIfBlocksShouldRespectControlFlow)
|
LUAU_FASTFLAGVARIABLE(LuauDfgIfBlocksShouldRespectControlFlow)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauDfgMatchCGScopes)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauDfgAllowUpdatesInLoops)
|
LUAU_FASTFLAGVARIABLE(LuauDfgAllowUpdatesInLoops)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
|
@ -1240,18 +1239,9 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprUnary* u)
|
||||||
DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprBinary* b)
|
DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprBinary* b)
|
||||||
{
|
{
|
||||||
visitExpr(b->left);
|
visitExpr(b->left);
|
||||||
if (FFlag::LuauDfgMatchCGScopes)
|
|
||||||
{
|
|
||||||
PushScope _{scopeStack, makeChildScope()};
|
|
||||||
visitExpr(b->right);
|
visitExpr(b->right);
|
||||||
return {defArena->freshCell(Symbol{}, b->location), nullptr};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
visitExpr(b->right);
|
|
||||||
return {defArena->freshCell(Symbol{}, b->location), nullptr};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return {defArena->freshCell(Symbol{}, b->location), nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprTypeAssertion* t)
|
DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprTypeAssertion* t)
|
||||||
|
@ -1264,29 +1254,9 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprTypeAssertion* t)
|
||||||
|
|
||||||
DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprIfElse* i)
|
DataFlowResult DataFlowGraphBuilder::visitExpr(AstExprIfElse* i)
|
||||||
{
|
{
|
||||||
if (FFlag::LuauDfgMatchCGScopes)
|
|
||||||
{
|
|
||||||
// In the constraint generator, the condition, consequence, and
|
|
||||||
// alternative all have distinct scopes.
|
|
||||||
{
|
|
||||||
PushScope _{scopeStack, makeChildScope()};
|
|
||||||
visitExpr(i->condition);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
PushScope _{scopeStack, makeChildScope()};
|
|
||||||
visitExpr(i->trueExpr);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
PushScope _{scopeStack, makeChildScope()};
|
|
||||||
visitExpr(i->falseExpr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
visitExpr(i->condition);
|
visitExpr(i->condition);
|
||||||
visitExpr(i->trueExpr);
|
visitExpr(i->trueExpr);
|
||||||
visitExpr(i->falseExpr);
|
visitExpr(i->falseExpr);
|
||||||
}
|
|
||||||
|
|
||||||
return {defArena->freshCell(Symbol{}, i->location), nullptr};
|
return {defArena->freshCell(Symbol{}, i->location), nullptr};
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
LUAU_FASTINTVARIABLE(LuauIndentTypeMismatchMaxTypeLength, 10)
|
LUAU_FASTINTVARIABLE(LuauIndentTypeMismatchMaxTypeLength, 10)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauBetterCannotCallFunctionPrimitive)
|
||||||
|
|
||||||
static std::string wrongNumberOfArgsString(
|
static std::string wrongNumberOfArgsString(
|
||||||
size_t expectedCount,
|
size_t expectedCount,
|
||||||
|
@ -446,6 +448,12 @@ struct ErrorConverter
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FFlag::LuauBetterCannotCallFunctionPrimitive)
|
||||||
|
{
|
||||||
|
if (auto primitiveTy = get<PrimitiveType>(follow(e.ty)); primitiveTy && primitiveTy->type == PrimitiveType::Function)
|
||||||
|
return "The type " + toString(e.ty) + " is not precise enough for us to determine the appropriate result type of this call.";
|
||||||
|
}
|
||||||
|
|
||||||
return "Cannot call a value of type " + toString(e.ty);
|
return "Cannot call a value of type " + toString(e.ty);
|
||||||
}
|
}
|
||||||
std::string operator()(const Luau::ExtraInformation& e) const
|
std::string operator()(const Luau::ExtraInformation& e) const
|
||||||
|
@ -655,7 +663,7 @@ struct ErrorConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
// binary operators
|
// binary operators
|
||||||
const auto binaryOps = FFlag::DebugLuauGreedyGeneralization ? kBinaryOps : DEPRECATED_kBinaryOps;
|
const auto binaryOps = FFlag::LuauEagerGeneralization ? kBinaryOps : DEPRECATED_kBinaryOps;
|
||||||
if (auto binaryString = binaryOps.find(tfit->function->name); binaryString != binaryOps.end())
|
if (auto binaryString = binaryOps.find(tfit->function->name); binaryString != binaryOps.end())
|
||||||
{
|
{
|
||||||
std::string result = "Operator '" + std::string(binaryString->second) + "' could not be applied to operands of types ";
|
std::string result = "Operator '" + std::string(binaryString->second) + "' could not be applied to operands of types ";
|
||||||
|
@ -710,7 +718,7 @@ struct ErrorConverter
|
||||||
"'";
|
"'";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((FFlag::DebugLuauGreedyGeneralization ? kUnreachableTypeFunctions : DEPRECATED_kUnreachableTypeFunctions).count(tfit->function->name))
|
if ((FFlag::LuauEagerGeneralization ? kUnreachableTypeFunctions : DEPRECATED_kUnreachableTypeFunctions).count(tfit->function->name))
|
||||||
{
|
{
|
||||||
return "Type function instance " + Luau::toString(e.ty) + " is uninhabited\n" +
|
return "Type function instance " + Luau::toString(e.ty) + " is uninhabited\n" +
|
||||||
"This is likely to be a bug, please report it at https://github.com/luau-lang/luau/issues";
|
"This is likely to be a bug, please report it at https://github.com/luau-lang/luau/issues";
|
||||||
|
|
|
@ -29,10 +29,6 @@ LUAU_FASTINT(LuauTypeInferIterationLimit);
|
||||||
LUAU_FASTINT(LuauTarjanChildLimit)
|
LUAU_FASTINT(LuauTarjanChildLimit)
|
||||||
|
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLogFragmentsFromAutocomplete)
|
LUAU_FASTFLAGVARIABLE(DebugLogFragmentsFromAutocomplete)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauBetterCursorInCommentDetection)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauAllFreeTypesHaveScopes)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauPersistConstraintGenerationScopes)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauCloneTypeAliasBindings)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauBetterScopeSelection)
|
LUAU_FASTFLAGVARIABLE(LuauBetterScopeSelection)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauBlockDiffFragmentSelection)
|
LUAU_FASTFLAGVARIABLE(LuauBlockDiffFragmentSelection)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauFragmentAcMemoryLeak)
|
LUAU_FASTFLAGVARIABLE(LuauFragmentAcMemoryLeak)
|
||||||
|
@ -1261,11 +1257,8 @@ FragmentAutocompleteStatusResult tryFragmentAutocomplete(
|
||||||
StringCompletionCallback stringCompletionCB
|
StringCompletionCallback stringCompletionCB
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (FFlag::LuauBetterCursorInCommentDetection)
|
|
||||||
{
|
|
||||||
if (isWithinComment(context.freshParse.commentLocations, cursorPosition))
|
if (isWithinComment(context.freshParse.commentLocations, cursorPosition))
|
||||||
return {FragmentAutocompleteStatus::Success, std::nullopt};
|
return {FragmentAutocompleteStatus::Success, std::nullopt};
|
||||||
}
|
|
||||||
// TODO: we should calculate fragmentEnd position here, by using context.newAstRoot and cursorPosition
|
// TODO: we should calculate fragmentEnd position here, by using context.newAstRoot and cursorPosition
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,12 +39,13 @@ LUAU_FASTINT(LuauTarjanChildLimit)
|
||||||
LUAU_FASTFLAG(LuauInferInNoCheckMode)
|
LUAU_FASTFLAG(LuauInferInNoCheckMode)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3)
|
LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3)
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson)
|
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJsonFile)
|
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJsonFile)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauForbidInternalTypes)
|
LUAU_FASTFLAGVARIABLE(DebugLuauForbidInternalTypes)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauForceStrictMode)
|
LUAU_FASTFLAGVARIABLE(DebugLuauForceStrictMode)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauForceNonStrictMode)
|
LUAU_FASTFLAGVARIABLE(DebugLuauForceNonStrictMode)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauNewSolverTypecheckCatchTimeouts)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -408,6 +409,38 @@ void Frontend::parse(const ModuleName& name)
|
||||||
parseGraph(buildQueue, name, false);
|
parseGraph(buildQueue, name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Frontend::parseModules(const std::vector<ModuleName>& names)
|
||||||
|
{
|
||||||
|
LUAU_TIMETRACE_SCOPE("Frontend::parseModules", "Frontend");
|
||||||
|
|
||||||
|
DenseHashSet<Luau::ModuleName> seen{{}};
|
||||||
|
|
||||||
|
for (const ModuleName& name : names)
|
||||||
|
{
|
||||||
|
if (seen.contains(name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (auto it = sourceNodes.find(name); it != sourceNodes.end() && !it->second->hasDirtySourceModule())
|
||||||
|
{
|
||||||
|
seen.insert(name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ModuleName> queue;
|
||||||
|
parseGraph(
|
||||||
|
queue,
|
||||||
|
name,
|
||||||
|
false,
|
||||||
|
[&seen](const ModuleName& name)
|
||||||
|
{
|
||||||
|
return seen.contains(name);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
seen.insert(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CheckResult Frontend::check(const ModuleName& name, std::optional<FrontendOptions> optionOverride)
|
CheckResult Frontend::check(const ModuleName& name, std::optional<FrontendOptions> optionOverride)
|
||||||
{
|
{
|
||||||
LUAU_TIMETRACE_SCOPE("Frontend::check", "Frontend");
|
LUAU_TIMETRACE_SCOPE("Frontend::check", "Frontend");
|
||||||
|
@ -1403,13 +1436,13 @@ ModulePtr check(
|
||||||
requireCycles
|
requireCycles
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: Delete this flag when clipping FFlag::DebugLuauGreedyGeneralization.
|
// FIXME: Delete this flag when clipping FFlag::LuauEagerGeneralization.
|
||||||
//
|
//
|
||||||
// This optional<> only exists so that we can run one constructor when the flag
|
// This optional<> only exists so that we can run one constructor when the flag
|
||||||
// is set, and another when it is unset.
|
// is set, and another when it is unset.
|
||||||
std::optional<ConstraintSolver> cs;
|
std::optional<ConstraintSolver> cs;
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
ConstraintSet constraintSet = cg.run(sourceModule.root);
|
ConstraintSet constraintSet = cg.run(sourceModule.root);
|
||||||
result->errors = std::move(constraintSet.errors);
|
result->errors = std::move(constraintSet.errors);
|
||||||
|
@ -1495,6 +1528,52 @@ ModulePtr check(
|
||||||
for (auto& [name, tf] : result->exportedTypeBindings)
|
for (auto& [name, tf] : result->exportedTypeBindings)
|
||||||
tf.type = builtinTypes->errorRecoveryType();
|
tf.type = builtinTypes->errorRecoveryType();
|
||||||
}
|
}
|
||||||
|
else if (FFlag::LuauNewSolverTypecheckCatchTimeouts)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case Mode::Nonstrict:
|
||||||
|
Luau::checkNonStrict(
|
||||||
|
builtinTypes,
|
||||||
|
NotNull{simplifier.get()},
|
||||||
|
NotNull{&typeFunctionRuntime},
|
||||||
|
iceHandler,
|
||||||
|
NotNull{&unifierState},
|
||||||
|
NotNull{&dfg},
|
||||||
|
NotNull{&limits},
|
||||||
|
sourceModule,
|
||||||
|
result.get()
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case Mode::Definition:
|
||||||
|
// fallthrough intentional
|
||||||
|
case Mode::Strict:
|
||||||
|
Luau::check(
|
||||||
|
builtinTypes,
|
||||||
|
NotNull{simplifier.get()},
|
||||||
|
NotNull{&typeFunctionRuntime},
|
||||||
|
NotNull{&unifierState},
|
||||||
|
NotNull{&limits},
|
||||||
|
logger.get(),
|
||||||
|
sourceModule,
|
||||||
|
result.get()
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case Mode::NoCheck:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (const TimeLimitError&)
|
||||||
|
{
|
||||||
|
result->timeout = true;
|
||||||
|
}
|
||||||
|
catch (const UserCancelError&)
|
||||||
|
{
|
||||||
|
result->cancelled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (mode)
|
switch (mode)
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
#include "Luau/Substitution.h"
|
#include "Luau/Substitution.h"
|
||||||
#include "Luau/VisitType.h"
|
#include "Luau/VisitType.h"
|
||||||
|
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEnableWriteOnlyProperties)
|
||||||
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAGVARIABLE(LuauEagerGeneralization)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -469,7 +469,7 @@ struct FreeTypeSearcher : TypeVisitor
|
||||||
|
|
||||||
bool visit(TypeId ty, const FreeType& ft) override
|
bool visit(TypeId ty, const FreeType& ft) override
|
||||||
{
|
{
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (!subsumes(scope, ft.scope))
|
if (!subsumes(scope, ft.scope))
|
||||||
return true;
|
return true;
|
||||||
|
@ -520,7 +520,7 @@ struct FreeTypeSearcher : TypeVisitor
|
||||||
|
|
||||||
if ((tt.state == TableState::Free || tt.state == TableState::Unsealed) && subsumes(scope, tt.scope))
|
if ((tt.state == TableState::Free || tt.state == TableState::Unsealed) && subsumes(scope, tt.scope))
|
||||||
{
|
{
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
unsealedTables.insert(ty);
|
unsealedTables.insert(ty);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -543,6 +543,40 @@ struct FreeTypeSearcher : TypeVisitor
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [_name, prop] : tt.props)
|
for (const auto& [_name, prop] : tt.props)
|
||||||
|
{
|
||||||
|
if (FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
{
|
||||||
|
if (prop.isReadOnly())
|
||||||
|
{
|
||||||
|
traverse(*prop.readTy);
|
||||||
|
}
|
||||||
|
else if (prop.isWriteOnly())
|
||||||
|
{
|
||||||
|
Polarity p = polarity;
|
||||||
|
polarity = Polarity::Negative;
|
||||||
|
traverse(*prop.writeTy);
|
||||||
|
polarity = p;
|
||||||
|
}
|
||||||
|
else if (prop.isShared())
|
||||||
|
{
|
||||||
|
Polarity p = polarity;
|
||||||
|
polarity = Polarity::Mixed;
|
||||||
|
traverse(prop.type());
|
||||||
|
polarity = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LUAU_ASSERT(prop.isReadWrite() && !prop.isShared());
|
||||||
|
|
||||||
|
traverse(*prop.readTy);
|
||||||
|
Polarity p = polarity;
|
||||||
|
polarity = Polarity::Negative;
|
||||||
|
traverse(*prop.writeTy);
|
||||||
|
polarity = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (prop.isReadOnly())
|
if (prop.isReadOnly())
|
||||||
traverse(*prop.readTy);
|
traverse(*prop.readTy);
|
||||||
|
@ -556,10 +590,11 @@ struct FreeTypeSearcher : TypeVisitor
|
||||||
polarity = p;
|
polarity = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tt.indexer)
|
if (tt.indexer)
|
||||||
{
|
{
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// {[K]: V} is equivalent to three functions: get, set, and iterate
|
// {[K]: V} is equivalent to three functions: get, set, and iterate
|
||||||
//
|
//
|
||||||
|
@ -617,7 +652,7 @@ struct FreeTypeSearcher : TypeVisitor
|
||||||
if (!subsumes(scope, ftp.scope))
|
if (!subsumes(scope, ftp.scope))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
GeneralizationParams<TypePackId>& params = typePacks[tp];
|
GeneralizationParams<TypePackId>& params = typePacks[tp];
|
||||||
++params.useCount;
|
++params.useCount;
|
||||||
|
@ -1241,7 +1276,7 @@ GeneralizationResult<TypeId> generalizeType(
|
||||||
|
|
||||||
if (!hasLowerBound && !hasUpperBound)
|
if (!hasLowerBound && !hasUpperBound)
|
||||||
{
|
{
|
||||||
if (!isWithinFunction || (!FFlag::DebugLuauGreedyGeneralization && (params.polarity != Polarity::Mixed && params.useCount == 1)))
|
if (!isWithinFunction || (!FFlag::LuauEagerGeneralization && (params.polarity != Polarity::Mixed && params.useCount == 1)))
|
||||||
emplaceType<BoundType>(asMutable(freeTy), builtinTypes->unknownType);
|
emplaceType<BoundType>(asMutable(freeTy), builtinTypes->unknownType);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1273,7 +1308,7 @@ GeneralizationResult<TypeId> generalizeType(
|
||||||
|
|
||||||
if (follow(lb) != freeTy)
|
if (follow(lb) != freeTy)
|
||||||
emplaceType<BoundType>(asMutable(freeTy), lb);
|
emplaceType<BoundType>(asMutable(freeTy), lb);
|
||||||
else if (!isWithinFunction || (!FFlag::DebugLuauGreedyGeneralization && params.useCount == 1))
|
else if (!isWithinFunction || (!FFlag::LuauEagerGeneralization && params.useCount == 1))
|
||||||
emplaceType<BoundType>(asMutable(freeTy), builtinTypes->unknownType);
|
emplaceType<BoundType>(asMutable(freeTy), builtinTypes->unknownType);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1390,7 +1425,7 @@ std::optional<TypeId> generalize(
|
||||||
FreeTypeSearcher fts{scope, cachedTypes};
|
FreeTypeSearcher fts{scope, cachedTypes};
|
||||||
fts.traverse(ty);
|
fts.traverse(ty);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
FunctionType* functionTy = getMutable<FunctionType>(ty);
|
FunctionType* functionTy = getMutable<FunctionType>(ty);
|
||||||
auto pushGeneric = [&](TypeId t)
|
auto pushGeneric = [&](TypeId t)
|
||||||
|
@ -1520,6 +1555,40 @@ struct GenericCounter : TypeVisitor
|
||||||
const Polarity previous = polarity;
|
const Polarity previous = polarity;
|
||||||
|
|
||||||
for (const auto& [_name, prop] : tt.props)
|
for (const auto& [_name, prop] : tt.props)
|
||||||
|
{
|
||||||
|
if (FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
{
|
||||||
|
if (prop.isReadOnly())
|
||||||
|
{
|
||||||
|
traverse(*prop.readTy);
|
||||||
|
}
|
||||||
|
else if (prop.isWriteOnly())
|
||||||
|
{
|
||||||
|
Polarity p = polarity;
|
||||||
|
polarity = Polarity::Negative;
|
||||||
|
traverse(*prop.writeTy);
|
||||||
|
polarity = p;
|
||||||
|
}
|
||||||
|
else if (prop.isShared())
|
||||||
|
{
|
||||||
|
Polarity p = polarity;
|
||||||
|
polarity = Polarity::Mixed;
|
||||||
|
traverse(prop.type());
|
||||||
|
polarity = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LUAU_ASSERT(prop.isReadWrite() && !prop.isShared());
|
||||||
|
|
||||||
|
traverse(*prop.readTy);
|
||||||
|
Polarity p = polarity;
|
||||||
|
polarity = Polarity::Negative;
|
||||||
|
traverse(*prop.writeTy);
|
||||||
|
polarity = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (prop.isReadOnly())
|
if (prop.isReadOnly())
|
||||||
traverse(*prop.readTy);
|
traverse(*prop.readTy);
|
||||||
|
@ -1527,9 +1596,11 @@ struct GenericCounter : TypeVisitor
|
||||||
{
|
{
|
||||||
LUAU_ASSERT(prop.isShared());
|
LUAU_ASSERT(prop.isShared());
|
||||||
|
|
||||||
|
Polarity p = polarity;
|
||||||
polarity = Polarity::Mixed;
|
polarity = Polarity::Mixed;
|
||||||
traverse(prop.type());
|
traverse(prop.type());
|
||||||
polarity = previous;
|
polarity = p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1582,7 +1653,7 @@ void pruneUnnecessaryGenerics(
|
||||||
TypeId ty
|
TypeId ty
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!FFlag::DebugLuauGreedyGeneralization)
|
if (!FFlag::LuauEagerGeneralization)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ty = follow(ty);
|
ty = follow(ty);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "Luau/Scope.h"
|
#include "Luau/Scope.h"
|
||||||
#include "Luau/VisitType.h"
|
#include "Luau/VisitType.h"
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -133,7 +133,7 @@ struct InferPolarity : TypeVisitor
|
||||||
template<typename TID>
|
template<typename TID>
|
||||||
static void inferGenericPolarities_(NotNull<TypeArena> arena, NotNull<Scope> scope, TID ty)
|
static void inferGenericPolarities_(NotNull<TypeArena> arena, NotNull<Scope> scope, TID ty)
|
||||||
{
|
{
|
||||||
if (!FFlag::LuauNonReentrantGeneralization3)
|
if (!FFlag::LuauEagerGeneralization)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
InferPolarity infer{arena, scope};
|
InferPolarity infer{arena, scope};
|
||||||
|
|
|
@ -40,7 +40,7 @@ OverloadResolver::OverloadResolver(
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<OverloadResolver::Analysis, TypeId> OverloadResolver::selectOverload(TypeId ty, TypePackId argsPack)
|
std::pair<OverloadResolver::Analysis, TypeId> OverloadResolver::selectOverload(TypeId ty, TypePackId argsPack, bool useFreeTypeBounds)
|
||||||
{
|
{
|
||||||
auto tryOne = [&](TypeId f)
|
auto tryOne = [&](TypeId f)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,9 @@ std::pair<OverloadResolver::Analysis, TypeId> OverloadResolver::selectOverload(T
|
||||||
SubtypingResult r = subtyping.isSubtype(argsPack, ftv->argTypes, scope);
|
SubtypingResult r = subtyping.isSubtype(argsPack, ftv->argTypes, scope);
|
||||||
subtyping.variance = variance;
|
subtyping.variance = variance;
|
||||||
|
|
||||||
|
if (!useFreeTypeBounds && !r.assumedConstraints.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (r.isSubtype)
|
if (r.isSubtype)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -461,7 +464,7 @@ static std::optional<TypeId> selectOverload(
|
||||||
{
|
{
|
||||||
auto resolver =
|
auto resolver =
|
||||||
std::make_unique<OverloadResolver>(builtinTypes, arena, simplifier, normalizer, typeFunctionRuntime, scope, iceReporter, limits, location);
|
std::make_unique<OverloadResolver>(builtinTypes, arena, simplifier, normalizer, typeFunctionRuntime, scope, iceReporter, limits, location);
|
||||||
auto [status, overload] = resolver->selectOverload(fn, argsPack);
|
auto [status, overload] = resolver->selectOverload(fn, argsPack, /*useFreeTypeBounds*/ false);
|
||||||
|
|
||||||
if (status == OverloadResolver::Analysis::Ok)
|
if (status == OverloadResolver::Analysis::Ok)
|
||||||
return overload;
|
return overload;
|
||||||
|
|
|
@ -21,6 +21,7 @@ LUAU_FASTFLAGVARIABLE(DebugLuauSubtypingCheckPathValidity)
|
||||||
LUAU_FASTINTVARIABLE(LuauSubtypingReasoningLimit, 100)
|
LUAU_FASTINTVARIABLE(LuauSubtypingReasoningLimit, 100)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauSubtypeGenericsAndNegations)
|
LUAU_FASTFLAGVARIABLE(LuauSubtypeGenericsAndNegations)
|
||||||
LUAU_FASTFLAG(LuauClipVariadicAnysFromArgsToGenericFuncs2)
|
LUAU_FASTFLAG(LuauClipVariadicAnysFromArgsToGenericFuncs2)
|
||||||
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -680,6 +681,44 @@ SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, TypeId sub
|
||||||
result.isSubtype = ok;
|
result.isSubtype = ok;
|
||||||
result.isCacheable = false;
|
result.isCacheable = false;
|
||||||
}
|
}
|
||||||
|
else if (auto pair = get2<FreeType, FreeType>(subTy, superTy); FFlag::LuauEagerGeneralization && pair)
|
||||||
|
{
|
||||||
|
// Any two free types are potentially subtypes of one another because
|
||||||
|
// both of them could be narrowed to never.
|
||||||
|
result = {true};
|
||||||
|
result.assumedConstraints.emplace_back(SubtypeConstraint{subTy, superTy});
|
||||||
|
}
|
||||||
|
else if (auto superFree = get<FreeType>(superTy); superFree && FFlag::LuauEagerGeneralization)
|
||||||
|
{
|
||||||
|
// Given SubTy <: (LB <: SuperTy <: UB)
|
||||||
|
//
|
||||||
|
// If SubTy <: UB, then it is possible that SubTy <: SuperTy.
|
||||||
|
// If SubTy </: UB, then it is definitely the case that SubTy </: SuperTy.
|
||||||
|
//
|
||||||
|
// It's always possible for SuperTy's upper bound to later be
|
||||||
|
// constrained, so this relation may not actually hold.
|
||||||
|
|
||||||
|
result = isCovariantWith(env, subTy, superFree->upperBound, scope);
|
||||||
|
|
||||||
|
if (result.isSubtype)
|
||||||
|
result.assumedConstraints.emplace_back(SubtypeConstraint{subTy, superTy});
|
||||||
|
}
|
||||||
|
else if (auto subFree = get<FreeType>(subTy); subFree && FFlag::LuauEagerGeneralization)
|
||||||
|
{
|
||||||
|
// Given (LB <: SubTy <: UB) <: SuperTy
|
||||||
|
//
|
||||||
|
// If UB <: SuperTy, then it is certainly the case that SubTy <: SuperTy.
|
||||||
|
// If SuperTy <: UB and LB <: SuperTy, then it is possible that UB will later be narrowed such that SubTy <: SuperTy.
|
||||||
|
// If LB </: SuperTy, then SubTy </: SuperTy
|
||||||
|
|
||||||
|
if (isCovariantWith(env, subFree->lowerBound, superTy, scope).isSubtype)
|
||||||
|
{
|
||||||
|
result = {true};
|
||||||
|
result.assumedConstraints.emplace_back(SubtypeConstraint{subTy, superTy});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = {false};
|
||||||
|
}
|
||||||
else if (auto p = get2<NegationType, NegationType>(subTy, superTy))
|
else if (auto p = get2<NegationType, NegationType>(subTy, superTy))
|
||||||
result = isCovariantWith(env, p.first->ty, p.second->ty, scope).withBothComponent(TypePath::TypeField::Negated);
|
result = isCovariantWith(env, p.first->ty, p.second->ty, scope).withBothComponent(TypePath::TypeField::Negated);
|
||||||
else if (auto subNegation = get<NegationType>(subTy))
|
else if (auto subNegation = get<NegationType>(subTy))
|
||||||
|
@ -1411,8 +1450,24 @@ SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const Tabl
|
||||||
{
|
{
|
||||||
SubtypingResult result{true};
|
SubtypingResult result{true};
|
||||||
|
|
||||||
|
if (FFlag::LuauEagerGeneralization)
|
||||||
|
{
|
||||||
|
if (subTable->props.empty() && !subTable->indexer && subTable->state == TableState::Sealed && superTable->indexer)
|
||||||
|
{
|
||||||
|
// While it is certainly the case that {} </: {T}, the story is a little bit different for {| |} <: {T}
|
||||||
|
// The shape of an unsealed tabel is still in flux, so it is probably the case that the unsealed table
|
||||||
|
// will later gain the necessary indexer as type inference proceeds.
|
||||||
|
//
|
||||||
|
// Unsealed tables are always sealed by the time inference completes, so this should never affect the
|
||||||
|
// type checking phase.
|
||||||
|
return {false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (subTable->props.empty() && !subTable->indexer && superTable->indexer)
|
if (subTable->props.empty() && !subTable->indexer && superTable->indexer)
|
||||||
return {false};
|
return {false};
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& [name, superProp] : superTable->props)
|
for (const auto& [name, superProp] : superTable->props)
|
||||||
{
|
{
|
||||||
|
@ -1451,6 +1506,12 @@ SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const Tabl
|
||||||
{
|
{
|
||||||
if (subTable->indexer)
|
if (subTable->indexer)
|
||||||
result.andAlso(isInvariantWith(env, *subTable->indexer, *superTable->indexer, scope));
|
result.andAlso(isInvariantWith(env, *subTable->indexer, *superTable->indexer, scope));
|
||||||
|
else if (FFlag::LuauEagerGeneralization && subTable->state != TableState::Sealed)
|
||||||
|
{
|
||||||
|
// As above, we assume that {| |} <: {T} because the unsealed table
|
||||||
|
// on the left will eventually gain the necessary indexer.
|
||||||
|
return {true};
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return {false};
|
return {false};
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ LUAU_FASTFLAGVARIABLE(LuauStringPartLengthLimit)
|
||||||
*/
|
*/
|
||||||
LUAU_FASTINTVARIABLE(DebugLuauVerboseTypeNames, 0)
|
LUAU_FASTINTVARIABLE(DebugLuauVerboseTypeNames, 0)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauToStringNoLexicalSort)
|
LUAU_FASTFLAGVARIABLE(DebugLuauToStringNoLexicalSort)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauFixEmptyTypePackStringification)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -479,6 +480,9 @@ struct TypeStringifier
|
||||||
|
|
||||||
bool wrap = !singleTp && get<TypePack>(follow(tp));
|
bool wrap = !singleTp && get<TypePack>(follow(tp));
|
||||||
|
|
||||||
|
if (FFlag::LuauFixEmptyTypePackStringification)
|
||||||
|
wrap &= !isEmpty(tp);
|
||||||
|
|
||||||
if (wrap)
|
if (wrap)
|
||||||
state.emit("(");
|
state.emit("(");
|
||||||
|
|
||||||
|
@ -687,14 +691,18 @@ struct TypeStringifier
|
||||||
|
|
||||||
state.emit("(");
|
state.emit("(");
|
||||||
|
|
||||||
if (state.opts.functionTypeArguments)
|
if (FFlag::LuauFixEmptyTypePackStringification && isEmpty(ftv.argTypes))
|
||||||
|
{
|
||||||
|
// if we've got an empty argument pack, we're done.
|
||||||
|
}
|
||||||
|
else if (state.opts.functionTypeArguments)
|
||||||
stringify(ftv.argTypes, ftv.argNames);
|
stringify(ftv.argTypes, ftv.argNames);
|
||||||
else
|
else
|
||||||
stringify(ftv.argTypes);
|
stringify(ftv.argTypes);
|
||||||
|
|
||||||
state.emit(") -> ");
|
state.emit(") -> ");
|
||||||
|
|
||||||
bool plural = true;
|
bool plural = FFlag::LuauFixEmptyTypePackStringification ? !isEmpty(ftv.retTypes) : true;
|
||||||
|
|
||||||
auto retBegin = begin(ftv.retTypes);
|
auto retBegin = begin(ftv.retTypes);
|
||||||
auto retEnd = end(ftv.retTypes);
|
auto retEnd = end(ftv.retTypes);
|
||||||
|
@ -1235,6 +1243,16 @@ struct TypePackStringifier
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FFlag::LuauFixEmptyTypePackStringification)
|
||||||
|
{
|
||||||
|
if (tp.head.empty() && (!tp.tail || isEmpty(*tp.tail)))
|
||||||
|
{
|
||||||
|
state.emit("()");
|
||||||
|
state.unsee(&tp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (const auto& typeId : tp.head)
|
for (const auto& typeId : tp.head)
|
||||||
|
@ -1782,6 +1800,22 @@ std::string toStringNamedFunction(const std::string& funcName, const FunctionTyp
|
||||||
|
|
||||||
state.emit("): ");
|
state.emit("): ");
|
||||||
|
|
||||||
|
if (FFlag::LuauFixEmptyTypePackStringification)
|
||||||
|
{
|
||||||
|
size_t retSize = size(ftv.retTypes);
|
||||||
|
bool hasTail = !finite(ftv.retTypes);
|
||||||
|
bool wrap = get<TypePack>(follow(ftv.retTypes)) && (hasTail ? retSize != 0 : retSize > 1);
|
||||||
|
|
||||||
|
if (wrap)
|
||||||
|
state.emit("(");
|
||||||
|
|
||||||
|
tvs.stringify(ftv.retTypes);
|
||||||
|
|
||||||
|
if (wrap)
|
||||||
|
state.emit(")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
size_t retSize = size(ftv.retTypes);
|
size_t retSize = size(ftv.retTypes);
|
||||||
bool hasTail = !finite(ftv.retTypes);
|
bool hasTail = !finite(ftv.retTypes);
|
||||||
bool wrap = get<TypePack>(follow(ftv.retTypes)) && (hasTail ? retSize != 0 : retSize != 1);
|
bool wrap = get<TypePack>(follow(ftv.retTypes)) && (hasTail ? retSize != 0 : retSize != 1);
|
||||||
|
@ -1793,6 +1827,7 @@ std::string toStringNamedFunction(const std::string& funcName, const FunctionTyp
|
||||||
|
|
||||||
if (wrap)
|
if (wrap)
|
||||||
state.emit(")");
|
state.emit(")");
|
||||||
|
}
|
||||||
|
|
||||||
return result.name;
|
return result.name;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,6 @@ LUAU_FASTINTVARIABLE(LuauTypeMaximumStringifierLength, 500)
|
||||||
LUAU_FASTINTVARIABLE(LuauTableTypeMaximumStringifierLength, 0)
|
LUAU_FASTINTVARIABLE(LuauTableTypeMaximumStringifierLength, 0)
|
||||||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauFreeTypesMustHaveBounds)
|
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "Luau/TypeArena.h"
|
#include "Luau/TypeArena.h"
|
||||||
|
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauFreezeArena);
|
LUAU_FASTFLAGVARIABLE(DebugLuauFreezeArena);
|
||||||
LUAU_FASTFLAG(LuauFreeTypesMustHaveBounds)
|
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
LUAU_FASTFLAG(LuauStoreCSTData2)
|
||||||
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
||||||
|
|
||||||
static char* allocateString(Luau::Allocator& allocator, std::string_view contents)
|
static char* allocateString(Luau::Allocator& allocator, std::string_view contents)
|
||||||
|
@ -307,7 +308,8 @@ public:
|
||||||
std::optional<AstArgumentName>* arg = &argNames.data[i++];
|
std::optional<AstArgumentName>* arg = &argNames.data[i++];
|
||||||
|
|
||||||
if (el)
|
if (el)
|
||||||
new (arg) std::optional<AstArgumentName>(AstArgumentName(AstName(el->name.c_str()), Location()));
|
new (arg)
|
||||||
|
std::optional<AstArgumentName>(AstArgumentName(AstName(el->name.c_str()), FFlag::LuauStoreCSTData2 ? Location() : el->location));
|
||||||
else
|
else
|
||||||
new (arg) std::optional<AstArgumentName>();
|
new (arg) std::optional<AstArgumentName>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ LUAU_FASTFLAG(DebugLuauMagicTypes)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauTypeCheckerAcceptNumberConcats)
|
LUAU_FASTFLAGVARIABLE(LuauTypeCheckerAcceptNumberConcats)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauTypeCheckerStricterIndexCheck)
|
LUAU_FASTFLAGVARIABLE(LuauTypeCheckerStricterIndexCheck)
|
||||||
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
||||||
|
LUAU_FASTFLAG(LuauEnableWriteOnlyProperties)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauReportSubtypingErrors)
|
LUAU_FASTFLAGVARIABLE(LuauReportSubtypingErrors)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauSkipMalformedTypeAliases)
|
LUAU_FASTFLAGVARIABLE(LuauSkipMalformedTypeAliases)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAGVARIABLE(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
@ -2983,12 +2984,24 @@ bool TypeChecker2::testPotentialLiteralIsSubtype(AstExpr* expr, TypeId expectedT
|
||||||
|
|
||||||
Set<std::optional<std::string> > missingKeys{{}};
|
Set<std::optional<std::string> > missingKeys{{}};
|
||||||
for (const auto& [name, prop] : expectedTableType->props)
|
for (const auto& [name, prop] : expectedTableType->props)
|
||||||
|
{
|
||||||
|
if (FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
{
|
||||||
|
if (prop.readTy)
|
||||||
|
{
|
||||||
|
if (!isOptional(*prop.readTy))
|
||||||
|
missingKeys.insert(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
LUAU_ASSERT(!prop.isWriteOnly());
|
LUAU_ASSERT(!prop.isWriteOnly());
|
||||||
|
|
||||||
auto readTy = *prop.readTy;
|
auto readTy = *prop.readTy;
|
||||||
if (!isOptional(readTy))
|
if (!isOptional(readTy))
|
||||||
missingKeys.insert(name);
|
missingKeys.insert(name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isArrayLike = false;
|
bool isArrayLike = false;
|
||||||
if (expectedTableType->indexer)
|
if (expectedTableType->indexer)
|
||||||
|
@ -3022,6 +3035,19 @@ bool TypeChecker2::testPotentialLiteralIsSubtype(AstExpr* expr, TypeId expectedT
|
||||||
// If there's not an indexer, then by width subtyping we can just do nothing :)
|
// If there's not an indexer, then by width subtyping we can just do nothing :)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
{
|
||||||
|
// If the type has a read type, then we have an expected type for it, otherwise, we actually don't
|
||||||
|
// care what's assigned to it because the only allowed behavior is writing to that property.
|
||||||
|
|
||||||
|
if (expectedIt->second.readTy)
|
||||||
|
{
|
||||||
|
module->astExpectedTypes[item.value] = *expectedIt->second.readTy;
|
||||||
|
isSubtype &= testPotentialLiteralIsSubtype(item.value, *expectedIt->second.readTy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// TODO: What do we do for write only props?
|
// TODO: What do we do for write only props?
|
||||||
LUAU_ASSERT(expectedIt->second.readTy);
|
LUAU_ASSERT(expectedIt->second.readTy);
|
||||||
|
@ -3030,6 +3056,7 @@ bool TypeChecker2::testPotentialLiteralIsSubtype(AstExpr* expr, TypeId expectedT
|
||||||
isSubtype &= testPotentialLiteralIsSubtype(item.value, *expectedIt->second.readTy);
|
isSubtype &= testPotentialLiteralIsSubtype(item.value, *expectedIt->second.readTy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (item.kind == AstExprTable::Item::List)
|
else if (item.kind == AstExprTable::Item::List)
|
||||||
{
|
{
|
||||||
if (!isArrayLike)
|
if (!isArrayLike)
|
||||||
|
|
|
@ -47,8 +47,8 @@ LUAU_DYNAMIC_FASTINTVARIABLE(LuauTypeFamilyApplicationCartesianProductLimit, 5'0
|
||||||
LUAU_DYNAMIC_FASTINTVARIABLE(LuauTypeFamilyUseGuesserDepth, -1);
|
LUAU_DYNAMIC_FASTINTVARIABLE(LuauTypeFamilyUseGuesserDepth, -1);
|
||||||
|
|
||||||
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauLogTypeFamilies)
|
LUAU_FASTFLAGVARIABLE(DebugLuauLogTypeFamilies)
|
||||||
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
||||||
|
@ -283,7 +283,7 @@ struct TypeFunctionReducer
|
||||||
}
|
}
|
||||||
else if (is<GenericType>(ty))
|
else if (is<GenericType>(ty))
|
||||||
{
|
{
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
return SkipTestResult::Generic;
|
return SkipTestResult::Generic;
|
||||||
else
|
else
|
||||||
return SkipTestResult::Irreducible;
|
return SkipTestResult::Irreducible;
|
||||||
|
@ -305,7 +305,7 @@ struct TypeFunctionReducer
|
||||||
}
|
}
|
||||||
else if (is<GenericTypePack>(ty))
|
else if (is<GenericTypePack>(ty))
|
||||||
{
|
{
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
return SkipTestResult::Generic;
|
return SkipTestResult::Generic;
|
||||||
else
|
else
|
||||||
return SkipTestResult::Irreducible;
|
return SkipTestResult::Irreducible;
|
||||||
|
@ -1101,7 +1101,7 @@ TypeFunctionReductionResult<TypeId> unmTypeFunction(
|
||||||
if (isPending(operandTy, ctx->solver))
|
if (isPending(operandTy, ctx->solver))
|
||||||
return {std::nullopt, Reduction::MaybeOk, {operandTy}, {}};
|
return {std::nullopt, Reduction::MaybeOk, {operandTy}, {}};
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
operandTy = follow(operandTy);
|
operandTy = follow(operandTy);
|
||||||
|
|
||||||
std::shared_ptr<const NormalizedType> normTy = ctx->normalizer->normalize(operandTy);
|
std::shared_ptr<const NormalizedType> normTy = ctx->normalizer->normalize(operandTy);
|
||||||
|
@ -1698,7 +1698,7 @@ TypeFunctionReductionResult<TypeId> orTypeFunction(
|
||||||
return {rhsTy, Reduction::MaybeOk, {}, {}};
|
return {rhsTy, Reduction::MaybeOk, {}, {}};
|
||||||
|
|
||||||
// check to see if both operand types are resolved enough, and wait to reduce if not
|
// check to see if both operand types are resolved enough, and wait to reduce if not
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (is<BlockedType, PendingExpansionType, TypeFunctionInstanceType>(lhsTy))
|
if (is<BlockedType, PendingExpansionType, TypeFunctionInstanceType>(lhsTy))
|
||||||
return {std::nullopt, Reduction::MaybeOk, {lhsTy}, {}};
|
return {std::nullopt, Reduction::MaybeOk, {lhsTy}, {}};
|
||||||
|
@ -1745,7 +1745,7 @@ static TypeFunctionReductionResult<TypeId> comparisonTypeFunction(
|
||||||
if (lhsTy == instance || rhsTy == instance)
|
if (lhsTy == instance || rhsTy == instance)
|
||||||
return {ctx->builtins->neverType, Reduction::MaybeOk, {}, {}};
|
return {ctx->builtins->neverType, Reduction::MaybeOk, {}, {}};
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (is<BlockedType, PendingExpansionType, TypeFunctionInstanceType>(lhsTy))
|
if (is<BlockedType, PendingExpansionType, TypeFunctionInstanceType>(lhsTy))
|
||||||
return {std::nullopt, Reduction::MaybeOk, {lhsTy}, {}};
|
return {std::nullopt, Reduction::MaybeOk, {lhsTy}, {}};
|
||||||
|
@ -2119,7 +2119,7 @@ TypeFunctionReductionResult<TypeId> refineTypeFunction(
|
||||||
for (size_t i = 1; i < typeParams.size(); i++)
|
for (size_t i = 1; i < typeParams.size(); i++)
|
||||||
discriminantTypes.push_back(follow(typeParams.at(i)));
|
discriminantTypes.push_back(follow(typeParams.at(i)));
|
||||||
|
|
||||||
const bool targetIsPending = FFlag::DebugLuauGreedyGeneralization
|
const bool targetIsPending = FFlag::LuauEagerGeneralization
|
||||||
? is<BlockedType, PendingExpansionType, TypeFunctionInstanceType>(targetTy)
|
? is<BlockedType, PendingExpansionType, TypeFunctionInstanceType>(targetTy)
|
||||||
: isPending(targetTy, ctx->solver);
|
: isPending(targetTy, ctx->solver);
|
||||||
|
|
||||||
|
@ -2206,7 +2206,7 @@ TypeFunctionReductionResult<TypeId> refineTypeFunction(
|
||||||
if (is<TableType>(target) || isSimpleDiscriminant(discriminant))
|
if (is<TableType>(target) || isSimpleDiscriminant(discriminant))
|
||||||
{
|
{
|
||||||
SimplifyResult result = simplifyIntersection(ctx->builtins, ctx->arena, target, discriminant);
|
SimplifyResult result = simplifyIntersection(ctx->builtins, ctx->arena, target, discriminant);
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// Simplification considers free and generic types to be
|
// Simplification considers free and generic types to be
|
||||||
// 'blocking', but that's not suitable for refine<>.
|
// 'blocking', but that's not suitable for refine<>.
|
||||||
|
@ -3335,7 +3335,7 @@ BuiltinTypeFunctions::BuiltinTypeFunctions()
|
||||||
, ltFunc{"lt", ltTypeFunction}
|
, ltFunc{"lt", ltTypeFunction}
|
||||||
, leFunc{"le", leTypeFunction}
|
, leFunc{"le", leTypeFunction}
|
||||||
, eqFunc{"eq", eqTypeFunction}
|
, eqFunc{"eq", eqTypeFunction}
|
||||||
, refineFunc{"refine", refineTypeFunction, /*canReduceGenerics*/ FFlag::DebugLuauGreedyGeneralization}
|
, refineFunc{"refine", refineTypeFunction, /*canReduceGenerics*/ FFlag::LuauEagerGeneralization}
|
||||||
, singletonFunc{"singleton", singletonTypeFunction}
|
, singletonFunc{"singleton", singletonTypeFunction}
|
||||||
, unionFunc{"union", unionTypeFunction}
|
, unionFunc{"union", unionTypeFunction}
|
||||||
, intersectFunc{"intersect", intersectTypeFunction}
|
, intersectFunc{"intersect", intersectTypeFunction}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2);
|
LUAU_FASTFLAG(LuauSolverV2);
|
||||||
LUAU_FASTFLAGVARIABLE(LuauDisableNewSolverAssertsInMixedMode)
|
|
||||||
|
|
||||||
// Maximum number of steps to follow when traversing a path. May not always
|
// Maximum number of steps to follow when traversing a path. May not always
|
||||||
// equate to the number of components in a path, depending on the traversal
|
// equate to the number of components in a path, depending on the traversal
|
||||||
|
@ -157,16 +156,12 @@ Path PathBuilder::build()
|
||||||
|
|
||||||
PathBuilder& PathBuilder::readProp(std::string name)
|
PathBuilder& PathBuilder::readProp(std::string name)
|
||||||
{
|
{
|
||||||
if (!FFlag::LuauDisableNewSolverAssertsInMixedMode)
|
|
||||||
LUAU_ASSERT(FFlag::LuauSolverV2);
|
|
||||||
components.push_back(Property{std::move(name), true});
|
components.push_back(Property{std::move(name), true});
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathBuilder& PathBuilder::writeProp(std::string name)
|
PathBuilder& PathBuilder::writeProp(std::string name)
|
||||||
{
|
{
|
||||||
if (!FFlag::LuauDisableNewSolverAssertsInMixedMode)
|
|
||||||
LUAU_ASSERT(FFlag::LuauSolverV2);
|
|
||||||
components.push_back(Property{std::move(name), false});
|
components.push_back(Property{std::move(name), false});
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauDisableNewSolverAssertsInMixedMode)
|
|
||||||
LUAU_FASTFLAGVARIABLE(LuauErrorSuppressionTypeFunctionArgs)
|
LUAU_FASTFLAGVARIABLE(LuauErrorSuppressionTypeFunctionArgs)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
|
@ -307,7 +306,7 @@ TypePack extendTypePack(
|
||||||
TypePack newPack;
|
TypePack newPack;
|
||||||
newPack.tail = arena.freshTypePack(ftp->scope, ftp->polarity);
|
newPack.tail = arena.freshTypePack(ftp->scope, ftp->polarity);
|
||||||
|
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
trackInteriorFreeTypePack(ftp->scope, *newPack.tail);
|
trackInteriorFreeTypePack(ftp->scope, *newPack.tail);
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2)
|
if (FFlag::LuauSolverV2)
|
||||||
|
@ -572,8 +571,6 @@ std::vector<TypeId> findBlockedArgTypesIn(AstExprCall* expr, NotNull<DenseHashMa
|
||||||
|
|
||||||
void trackInteriorFreeType(Scope* scope, TypeId ty)
|
void trackInteriorFreeType(Scope* scope, TypeId ty)
|
||||||
{
|
{
|
||||||
if (!FFlag::LuauDisableNewSolverAssertsInMixedMode)
|
|
||||||
LUAU_ASSERT(FFlag::LuauSolverV2);
|
|
||||||
for (; scope; scope = scope->parent.get())
|
for (; scope; scope = scope->parent.get())
|
||||||
{
|
{
|
||||||
if (scope->interiorFreeTypes)
|
if (scope->interiorFreeTypes)
|
||||||
|
@ -591,7 +588,7 @@ void trackInteriorFreeType(Scope* scope, TypeId ty)
|
||||||
void trackInteriorFreeTypePack(Scope* scope, TypePackId tp)
|
void trackInteriorFreeTypePack(Scope* scope, TypePackId tp)
|
||||||
{
|
{
|
||||||
LUAU_ASSERT(tp);
|
LUAU_ASSERT(tp);
|
||||||
if (!FFlag::LuauNonReentrantGeneralization3)
|
if (!FFlag::LuauEagerGeneralization)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (; scope; scope = scope->parent.get())
|
for (; scope; scope = scope->parent.get())
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEnableWriteOnlyProperties)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
|
@ -329,12 +329,12 @@ bool Unifier2::unify(TypeId subTy, const FunctionType* superFn)
|
||||||
|
|
||||||
for (TypePackId genericPack : subFn->genericPacks)
|
for (TypePackId genericPack : subFn->genericPacks)
|
||||||
{
|
{
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
genericPack = follow(genericPack);
|
genericPack = follow(genericPack);
|
||||||
|
|
||||||
// TODO: Clip this follow() with DebugLuauGreedyGeneralization
|
// TODO: Clip this follow() with LuauEagerGeneralization
|
||||||
const GenericTypePack* gen = get<GenericTypePack>(follow(genericPack));
|
const GenericTypePack* gen = get<GenericTypePack>(follow(genericPack));
|
||||||
if (gen)
|
if (gen)
|
||||||
genericPackSubstitutions[genericPack] = freshTypePack(scope, gen->polarity);
|
genericPackSubstitutions[genericPack] = freshTypePack(scope, gen->polarity);
|
||||||
|
@ -413,6 +413,16 @@ bool Unifier2::unify(TableType* subTable, const TableType* superTable)
|
||||||
{
|
{
|
||||||
const Property& superProp = superPropOpt->second;
|
const Property& superProp = superPropOpt->second;
|
||||||
|
|
||||||
|
if (FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
{
|
||||||
|
if (subProp.readTy && superProp.readTy)
|
||||||
|
result &= unify(*subProp.readTy, *superProp.readTy);
|
||||||
|
|
||||||
|
if (subProp.writeTy && superProp.writeTy)
|
||||||
|
result &= unify(*superProp.writeTy, *subProp.writeTy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (subProp.isReadOnly() && superProp.isReadOnly())
|
if (subProp.isReadOnly() && superProp.isReadOnly())
|
||||||
result &= unify(*subProp.readTy, *superPropOpt->second.readTy);
|
result &= unify(*subProp.readTy, *superPropOpt->second.readTy);
|
||||||
else if (subProp.isReadOnly())
|
else if (subProp.isReadOnly())
|
||||||
|
@ -426,6 +436,7 @@ bool Unifier2::unify(TableType* subTable, const TableType* superTable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto subTypeParamsIter = subTable->instantiatedTypeParams.begin();
|
auto subTypeParamsIter = subTable->instantiatedTypeParams.begin();
|
||||||
auto superTypeParamsIter = superTable->instantiatedTypeParams.begin();
|
auto superTypeParamsIter = superTable->instantiatedTypeParams.begin();
|
||||||
|
@ -454,7 +465,7 @@ bool Unifier2::unify(TableType* subTable, const TableType* superTable)
|
||||||
{
|
{
|
||||||
result &= unify(subTable->indexer->indexType, superTable->indexer->indexType);
|
result &= unify(subTable->indexer->indexType, superTable->indexer->indexType);
|
||||||
result &= unify(subTable->indexer->indexResultType, superTable->indexer->indexResultType);
|
result &= unify(subTable->indexer->indexResultType, superTable->indexer->indexResultType);
|
||||||
if (FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// FIXME: We can probably do something more efficient here.
|
// FIXME: We can probably do something more efficient here.
|
||||||
result &= unify(superTable->indexer->indexType, subTable->indexer->indexType);
|
result &= unify(superTable->indexer->indexType, subTable->indexer->indexType);
|
||||||
|
|
|
@ -245,6 +245,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
TableIndexerResult parseTableIndexer(AstTableAccess access, std::optional<Location> accessLocation, Lexeme begin);
|
TableIndexerResult parseTableIndexer(AstTableAccess access, std::optional<Location> accessLocation, Lexeme begin);
|
||||||
|
// Remove with FFlagLuauStoreCSTData2
|
||||||
|
AstTableIndexer* parseTableIndexer_DEPRECATED(AstTableAccess access, std::optional<Location> accessLocation, Lexeme begin);
|
||||||
|
|
||||||
AstTypeOrPack parseFunctionType(bool allowPack, const AstArray<AstAttr*>& attributes);
|
AstTypeOrPack parseFunctionType(bool allowPack, const AstArray<AstAttr*>& attributes);
|
||||||
AstType* parseFunctionTypeTail(
|
AstType* parseFunctionTypeTail(
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -121,6 +121,8 @@ void create(lua_State* L, SharedCodeGenContext* codeGenContext);
|
||||||
// Enable or disable native execution according to `enabled` argument
|
// Enable or disable native execution according to `enabled` argument
|
||||||
void setNativeExecutionEnabled(lua_State* L, bool enabled);
|
void setNativeExecutionEnabled(lua_State* L, bool enabled);
|
||||||
|
|
||||||
|
void disableNativeExecutionForFunction(lua_State* L, const int level) noexcept;
|
||||||
|
|
||||||
// Given a name, this function must return the index of the type which matches the type array used all CompilationOptions and AssemblyOptions
|
// Given a name, this function must return the index of the type which matches the type array used all CompilationOptions and AssemblyOptions
|
||||||
// If the type is unknown, 0xff has to be returned
|
// If the type is unknown, 0xff has to be returned
|
||||||
using UserdataRemapperCallback = uint8_t(void* context, const char* name, size_t nameLength);
|
using UserdataRemapperCallback = uint8_t(void* context, const char* name, size_t nameLength);
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
|
|
||||||
|
LUAU_DYNAMIC_FASTFLAG(AddReturnExectargetCheck);
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
namespace CodeGen
|
namespace CodeGen
|
||||||
|
@ -179,6 +181,14 @@ void emitReturn(AssemblyBuilderA64& build, ModuleHelpers& helpers)
|
||||||
|
|
||||||
build.ldr(x1, mem(rClosure, offsetof(Closure, l.p))); // cl->l.p aka proto
|
build.ldr(x1, mem(rClosure, offsetof(Closure, l.p))); // cl->l.p aka proto
|
||||||
|
|
||||||
|
if (DFFlag::AddReturnExectargetCheck)
|
||||||
|
{
|
||||||
|
// Get new instruction location
|
||||||
|
CODEGEN_ASSERT(offsetof(Proto, exectarget) == offsetof(Proto, execdata) + 8);
|
||||||
|
build.ldp(x3, x4, mem(x1, offsetof(Proto, execdata)));
|
||||||
|
build.cbz(x4, helpers.exitContinueVmClearNativeFlag);
|
||||||
|
}
|
||||||
|
|
||||||
CODEGEN_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
|
CODEGEN_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
|
||||||
build.ldp(rConstants, rCode, mem(x1, offsetof(Proto, k))); // proto->k, proto->code
|
build.ldp(rConstants, rCode, mem(x1, offsetof(Proto, k))); // proto->k, proto->code
|
||||||
|
|
||||||
|
@ -188,9 +198,12 @@ void emitReturn(AssemblyBuilderA64& build, ModuleHelpers& helpers)
|
||||||
build.ldr(x2, mem(x2, offsetof(CallInfo, savedpc))); // cip->savedpc
|
build.ldr(x2, mem(x2, offsetof(CallInfo, savedpc))); // cip->savedpc
|
||||||
build.sub(x2, x2, rCode);
|
build.sub(x2, x2, rCode);
|
||||||
|
|
||||||
|
if (!DFFlag::AddReturnExectargetCheck)
|
||||||
|
{
|
||||||
// Get new instruction location and jump to it
|
// Get new instruction location and jump to it
|
||||||
CODEGEN_ASSERT(offsetof(Proto, exectarget) == offsetof(Proto, execdata) + 8);
|
CODEGEN_ASSERT(offsetof(Proto, exectarget) == offsetof(Proto, execdata) + 8);
|
||||||
build.ldp(x3, x4, mem(x1, offsetof(Proto, execdata)));
|
build.ldp(x3, x4, mem(x1, offsetof(Proto, execdata)));
|
||||||
|
}
|
||||||
build.ldr(w2, mem(x3, x2));
|
build.ldr(w2, mem(x3, x2));
|
||||||
build.add(x4, x4, x2);
|
build.add(x4, x4, x2);
|
||||||
build.br(x4);
|
build.br(x4);
|
||||||
|
|
|
@ -671,6 +671,21 @@ void setNativeExecutionEnabled(lua_State* L, bool enabled)
|
||||||
L->global->ecb.enter = enabled ? onEnter : onEnterDisabled;
|
L->global->ecb.enter = enabled ? onEnter : onEnterDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disableNativeExecutionForFunction(lua_State* L, const int level) noexcept
|
||||||
|
{
|
||||||
|
CODEGEN_ASSERT(unsigned(level) < unsigned(L->ci - L->base_ci));
|
||||||
|
|
||||||
|
const CallInfo* ci = L->ci - level;
|
||||||
|
const TValue* o = ci->func;
|
||||||
|
CODEGEN_ASSERT(ttisfunction(o));
|
||||||
|
|
||||||
|
Proto* proto = clvalue(o)->l.p;
|
||||||
|
CODEGEN_ASSERT(proto);
|
||||||
|
|
||||||
|
CODEGEN_ASSERT(proto->codeentry != proto->code);
|
||||||
|
onDestroyFunction(L, proto);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t userdataRemapperWrap(lua_State* L, const char* str, size_t len)
|
static uint8_t userdataRemapperWrap(lua_State* L, const char* str, size_t len)
|
||||||
{
|
{
|
||||||
if (BaseCodeGenContext* codegenCtx = getCodeGenContext(L))
|
if (BaseCodeGenContext* codegenCtx = getCodeGenContext(L))
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
LUAU_DYNAMIC_FASTFLAGVARIABLE(AddReturnExectargetCheck, false);
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
{
|
{
|
||||||
namespace CodeGen
|
namespace CodeGen
|
||||||
|
@ -458,6 +461,7 @@ void emitReturn(AssemblyBuilderX64& build, ModuleHelpers& helpers)
|
||||||
// Registers alive: r9 (cip)
|
// Registers alive: r9 (cip)
|
||||||
RegisterX64 proto = rcx;
|
RegisterX64 proto = rcx;
|
||||||
RegisterX64 execdata = rbx;
|
RegisterX64 execdata = rbx;
|
||||||
|
RegisterX64 exectarget = r10;
|
||||||
|
|
||||||
// Change closure
|
// Change closure
|
||||||
build.mov(rax, qword[cip + offsetof(CallInfo, func)]);
|
build.mov(rax, qword[cip + offsetof(CallInfo, func)]);
|
||||||
|
@ -471,6 +475,13 @@ void emitReturn(AssemblyBuilderX64& build, ModuleHelpers& helpers)
|
||||||
build.test(byte[cip + offsetof(CallInfo, flags)], LUA_CALLINFO_NATIVE);
|
build.test(byte[cip + offsetof(CallInfo, flags)], LUA_CALLINFO_NATIVE);
|
||||||
build.jcc(ConditionX64::Zero, helpers.exitContinueVm); // Continue in interpreter if function has no native data
|
build.jcc(ConditionX64::Zero, helpers.exitContinueVm); // Continue in interpreter if function has no native data
|
||||||
|
|
||||||
|
if (DFFlag::AddReturnExectargetCheck)
|
||||||
|
{
|
||||||
|
build.mov(exectarget, qword[proto + offsetof(Proto, exectarget)]);
|
||||||
|
build.test(exectarget, exectarget);
|
||||||
|
build.jcc(ConditionX64::Zero, helpers.exitContinueVmClearNativeFlag);
|
||||||
|
}
|
||||||
|
|
||||||
// Change constants
|
// Change constants
|
||||||
build.mov(rConstants, qword[proto + offsetof(Proto, k)]);
|
build.mov(rConstants, qword[proto + offsetof(Proto, k)]);
|
||||||
|
|
||||||
|
@ -486,7 +497,15 @@ void emitReturn(AssemblyBuilderX64& build, ModuleHelpers& helpers)
|
||||||
|
|
||||||
// Get new instruction location and jump to it
|
// Get new instruction location and jump to it
|
||||||
build.mov(edx, dword[execdata + rax]);
|
build.mov(edx, dword[execdata + rax]);
|
||||||
|
|
||||||
|
if (DFFlag::AddReturnExectargetCheck)
|
||||||
|
{
|
||||||
|
build.add(rdx, exectarget);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
build.add(rdx, qword[proto + offsetof(Proto, exectarget)]);
|
build.add(rdx, qword[proto + offsetof(Proto, exectarget)]);
|
||||||
|
}
|
||||||
build.jmp(rdx);
|
build.jmp(rdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauCurrentLineBounds)
|
LUAU_FASTFLAG(LuauCurrentLineBounds)
|
||||||
|
LUAU_FASTFLAGVARIABLE(LuauHeapNameDetails)
|
||||||
|
|
||||||
static void validateobjref(global_State* g, GCObject* f, GCObject* t)
|
static void validateobjref(global_State* g, GCObject* f, GCObject* t)
|
||||||
{
|
{
|
||||||
|
@ -728,10 +729,20 @@ static void enumclosure(EnumContext* ctx, Closure* cl)
|
||||||
|
|
||||||
char buf[LUA_IDSIZE];
|
char buf[LUA_IDSIZE];
|
||||||
|
|
||||||
|
if (FFlag::LuauHeapNameDetails)
|
||||||
|
{
|
||||||
|
if (p->source)
|
||||||
|
snprintf(buf, sizeof(buf), "%s:%d %s", p->debugname ? getstr(p->debugname) : "unnamed", p->linedefined, getstr(p->source));
|
||||||
|
else
|
||||||
|
snprintf(buf, sizeof(buf), "%s:%d", p->debugname ? getstr(p->debugname) : "unnamed", p->linedefined);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (p->source)
|
if (p->source)
|
||||||
snprintf(buf, sizeof(buf), "%s:%d %s", p->debugname ? getstr(p->debugname) : "", p->linedefined, getstr(p->source));
|
snprintf(buf, sizeof(buf), "%s:%d %s", p->debugname ? getstr(p->debugname) : "", p->linedefined, getstr(p->source));
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), "%s:%d", p->debugname ? getstr(p->debugname) : "", p->linedefined);
|
snprintf(buf, sizeof(buf), "%s:%d", p->debugname ? getstr(p->debugname) : "", p->linedefined);
|
||||||
|
}
|
||||||
|
|
||||||
enumnode(ctx, obj2gco(cl), sizeLclosure(cl->nupvalues), buf);
|
enumnode(ctx, obj2gco(cl), sizeLclosure(cl->nupvalues), buf);
|
||||||
}
|
}
|
||||||
|
@ -799,10 +810,21 @@ static void enumthread(EnumContext* ctx, lua_State* th)
|
||||||
|
|
||||||
char buf[LUA_IDSIZE];
|
char buf[LUA_IDSIZE];
|
||||||
|
|
||||||
|
if (FFlag::LuauHeapNameDetails)
|
||||||
|
{
|
||||||
|
if (p->source)
|
||||||
|
snprintf(buf, sizeof(buf), "thread at %s:%d %s", p->debugname ? getstr(p->debugname) : "unnamed", p->linedefined, getstr(p->source));
|
||||||
|
else
|
||||||
|
snprintf(buf, sizeof(buf), "thread at %s:%d", p->debugname ? getstr(p->debugname) : "unnamed", p->linedefined);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
if (p->source)
|
if (p->source)
|
||||||
snprintf(buf, sizeof(buf), "%s:%d %s", p->debugname ? getstr(p->debugname) : "", p->linedefined, getstr(p->source));
|
snprintf(buf, sizeof(buf), "%s:%d %s", p->debugname ? getstr(p->debugname) : "", p->linedefined, getstr(p->source));
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), "%s:%d", p->debugname ? getstr(p->debugname) : "", p->linedefined);
|
snprintf(buf, sizeof(buf), "%s:%d", p->debugname ? getstr(p->debugname) : "", p->linedefined);
|
||||||
|
}
|
||||||
|
|
||||||
enumnode(ctx, obj2gco(th), size, buf);
|
enumnode(ctx, obj2gco(th), size, buf);
|
||||||
}
|
}
|
||||||
|
@ -835,7 +857,21 @@ static void enumproto(EnumContext* ctx, Proto* p)
|
||||||
ctx->edge(ctx->context, enumtopointer(obj2gco(p)), p->execdata, "[native]");
|
ctx->edge(ctx->context, enumtopointer(obj2gco(p)), p->execdata, "[native]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FFlag::LuauHeapNameDetails)
|
||||||
|
{
|
||||||
|
char buf[LUA_IDSIZE];
|
||||||
|
|
||||||
|
if (p->source)
|
||||||
|
snprintf(buf, sizeof(buf), "proto %s:%d %s", p->debugname ? getstr(p->debugname) : "unnamed", p->linedefined, getstr(p->source));
|
||||||
|
else
|
||||||
|
snprintf(buf, sizeof(buf), "proto %s:%d", p->debugname ? getstr(p->debugname) : "unnamed", p->linedefined);
|
||||||
|
|
||||||
|
enumnode(ctx, obj2gco(p), size, buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
enumnode(ctx, obj2gco(p), size, p->source ? getstr(p->source) : NULL);
|
enumnode(ctx, obj2gco(p), size, p->source ? getstr(p->source) : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (p->sizek)
|
if (p->sizek)
|
||||||
enumedges(ctx, obj2gco(p), p->k, p->sizek, "constants");
|
enumedges(ctx, obj2gco(p), p->k, p->sizek, "constants");
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
LUAU_FASTFLAG(LuauTraceTypesInNonstrictMode2)
|
LUAU_FASTFLAG(LuauTraceTypesInNonstrictMode2)
|
||||||
LUAU_FASTFLAG(LuauSetMetatableDoesNotTimeTravel)
|
LUAU_FASTFLAG(LuauSetMetatableDoesNotTimeTravel)
|
||||||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
|
@ -4454,9 +4454,9 @@ TEST_CASE_FIXTURE(ACExternTypeFixture, "ac_dont_overflow_on_recursive_union")
|
||||||
|
|
||||||
auto ac = autocomplete('1');
|
auto ac = autocomplete('1');
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2 && FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauSolverV2 && FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// This `if` statement is because `LuauNonReentrantGeneralization3`
|
// This `if` statement is because `LuauEagerGeneralization`
|
||||||
// sets some flags
|
// sets some flags
|
||||||
CHECK(ac.entryMap.count("BaseMethod") > 0);
|
CHECK(ac.entryMap.count("BaseMethod") > 0);
|
||||||
CHECK(ac.entryMap.count("Method") > 0);
|
CHECK(ac.entryMap.count("Method") > 0);
|
||||||
|
|
|
@ -40,6 +40,7 @@ LUAU_DYNAMIC_FASTFLAG(LuauStringFormatFixC)
|
||||||
LUAU_FASTFLAG(LuauYieldableContinuations)
|
LUAU_FASTFLAG(LuauYieldableContinuations)
|
||||||
LUAU_FASTFLAG(LuauCurrentLineBounds)
|
LUAU_FASTFLAG(LuauCurrentLineBounds)
|
||||||
LUAU_FASTFLAG(LuauLoadNoOomThrow)
|
LUAU_FASTFLAG(LuauLoadNoOomThrow)
|
||||||
|
LUAU_FASTFLAG(LuauHeapNameDetails)
|
||||||
|
|
||||||
static lua_CompileOptions defaultOptions()
|
static lua_CompileOptions defaultOptions()
|
||||||
{
|
{
|
||||||
|
@ -2280,6 +2281,8 @@ TEST_CASE("StringConversion")
|
||||||
|
|
||||||
TEST_CASE("GCDump")
|
TEST_CASE("GCDump")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag luauHeapNameDetails{FFlag::LuauHeapNameDetails, true};
|
||||||
|
|
||||||
// internal function, declared in lgc.h - not exposed via lua.h
|
// internal function, declared in lgc.h - not exposed via lua.h
|
||||||
extern void luaC_dump(lua_State * L, void* file, const char* (*categoryName)(lua_State* L, uint8_t memcat));
|
extern void luaC_dump(lua_State * L, void* file, const char* (*categoryName)(lua_State* L, uint8_t memcat));
|
||||||
extern void luaC_enumheap(
|
extern void luaC_enumheap(
|
||||||
|
@ -2320,7 +2323,19 @@ TEST_CASE("GCDump")
|
||||||
|
|
||||||
lua_State* CL = lua_newthread(L);
|
lua_State* CL = lua_newthread(L);
|
||||||
|
|
||||||
lua_pushstring(CL, "local x x = {} local function f() x[1] = math.abs(42) end function foo() coroutine.yield() end foo() return f");
|
lua_pushstring(CL, R"(
|
||||||
|
local x
|
||||||
|
x = {}
|
||||||
|
local function f()
|
||||||
|
x[1] = math.abs(42)
|
||||||
|
end
|
||||||
|
function foo()
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
foo()
|
||||||
|
return f
|
||||||
|
)");
|
||||||
|
lua_pushstring(CL, "=GCDump");
|
||||||
lua_loadstring(CL);
|
lua_loadstring(CL);
|
||||||
lua_resume(CL, nullptr, 0);
|
lua_resume(CL, nullptr, 0);
|
||||||
|
|
||||||
|
@ -2365,8 +2380,19 @@ TEST_CASE("GCDump")
|
||||||
{
|
{
|
||||||
EnumContext& context = *(EnumContext*)ctx;
|
EnumContext& context = *(EnumContext*)ctx;
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
std::string_view sv{name};
|
||||||
|
|
||||||
if (tt == LUA_TUSERDATA)
|
if (tt == LUA_TUSERDATA)
|
||||||
CHECK(strcmp(name, "u42") == 0);
|
CHECK(sv == "u42");
|
||||||
|
else if (tt == LUA_TPROTO)
|
||||||
|
CHECK((sv == "proto unnamed:1 =GCDump" || sv == "proto foo:7 =GCDump" || sv == "proto f:4 =GCDump"));
|
||||||
|
else if (tt == LUA_TFUNCTION)
|
||||||
|
CHECK((sv == "test" || sv == "unnamed:1 =GCDump" || sv == "foo:7 =GCDump" || sv == "f:4 =GCDump"));
|
||||||
|
else if (tt == LUA_TTHREAD)
|
||||||
|
CHECK(sv == "thread at unnamed:1 =GCDump");
|
||||||
|
}
|
||||||
|
|
||||||
context.nodes[gco] = {gco, tt, memcat, size, name ? name : ""};
|
context.nodes[gco] = {gco, tt, memcat, size, name ? name : ""};
|
||||||
},
|
},
|
||||||
|
|
|
@ -234,8 +234,6 @@ TEST_CASE_FIXTURE(DifferFixture, "right_cyclic_table_left_table_property_wrong")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(DifferFixture, "equal_table_two_cyclic_tables_are_not_different")
|
TEST_CASE_FIXTURE(DifferFixture, "equal_table_two_cyclic_tables_are_not_different")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local function id<a>(x: a): a
|
local function id<a>(x: a): a
|
||||||
return x
|
return x
|
||||||
|
@ -1473,8 +1471,6 @@ TEST_CASE_FIXTURE(DifferFixtureWithBuiltins, "equal_metatable")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(DifferFixtureWithBuiltins, "metatable_normal")
|
TEST_CASE_FIXTURE(DifferFixtureWithBuiltins, "metatable_normal")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local metaFoo = {
|
local metaFoo = {
|
||||||
metaBar = 5
|
metaBar = 5
|
||||||
|
|
|
@ -26,13 +26,6 @@ using namespace Luau;
|
||||||
LUAU_FASTINT(LuauParseErrorLimit)
|
LUAU_FASTINT(LuauParseErrorLimit)
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauBetterReverseDependencyTracking)
|
LUAU_FASTFLAG(LuauBetterReverseDependencyTracking)
|
||||||
LUAU_FASTFLAG(LuauAutocompleteUsesModuleForTypeCompatibility)
|
|
||||||
LUAU_FASTFLAG(LuauBetterCursorInCommentDetection)
|
|
||||||
LUAU_FASTFLAG(LuauAllFreeTypesHaveScopes)
|
|
||||||
LUAU_FASTFLAG(LuauClonedTableAndFunctionTypesMustHaveScopes)
|
|
||||||
LUAU_FASTFLAG(LuauDisableNewSolverAssertsInMixedMode)
|
|
||||||
LUAU_FASTFLAG(LuauCloneTypeAliasBindings)
|
|
||||||
LUAU_FASTFLAG(LuauDoNotClonePersistentBindings)
|
|
||||||
LUAU_FASTFLAG(LuauBetterScopeSelection)
|
LUAU_FASTFLAG(LuauBetterScopeSelection)
|
||||||
LUAU_FASTFLAG(LuauBlockDiffFragmentSelection)
|
LUAU_FASTFLAG(LuauBlockDiffFragmentSelection)
|
||||||
LUAU_FASTFLAG(LuauFragmentAcMemoryLeak)
|
LUAU_FASTFLAG(LuauFragmentAcMemoryLeak)
|
||||||
|
@ -67,14 +60,8 @@ struct FragmentAutocompleteFixtureImpl : BaseType
|
||||||
{
|
{
|
||||||
static_assert(std::is_base_of_v<Fixture, BaseType>, "BaseType must be a descendant of Fixture");
|
static_assert(std::is_base_of_v<Fixture, BaseType>, "BaseType must be a descendant of Fixture");
|
||||||
|
|
||||||
ScopedFastFlag luauAllFreeTypesHaveScopes{FFlag::LuauAllFreeTypesHaveScopes, true};
|
|
||||||
ScopedFastFlag luauClonedTableAndFunctionTypesMustHaveScopes{FFlag::LuauClonedTableAndFunctionTypesMustHaveScopes, true};
|
|
||||||
ScopedFastFlag luauDisableNewSolverAssertsInMixedMode{FFlag::LuauDisableNewSolverAssertsInMixedMode, true};
|
|
||||||
ScopedFastFlag luauCloneTypeAliasBindings{FFlag::LuauCloneTypeAliasBindings, true};
|
|
||||||
ScopedFastFlag luauDoNotClonePersistentBindings{FFlag::LuauDoNotClonePersistentBindings, true};
|
|
||||||
ScopedFastFlag luauBetterScopeSelection{FFlag::LuauBetterScopeSelection, true};
|
ScopedFastFlag luauBetterScopeSelection{FFlag::LuauBetterScopeSelection, true};
|
||||||
ScopedFastFlag luauBlockDiffFragmentSelection{FFlag::LuauBlockDiffFragmentSelection, true};
|
ScopedFastFlag luauBlockDiffFragmentSelection{FFlag::LuauBlockDiffFragmentSelection, true};
|
||||||
ScopedFastFlag luauAutocompleteUsesModuleForTypeCompatibility{FFlag::LuauAutocompleteUsesModuleForTypeCompatibility, true};
|
|
||||||
ScopedFastFlag luauFragmentAcMemoryLeak{FFlag::LuauFragmentAcMemoryLeak, true};
|
ScopedFastFlag luauFragmentAcMemoryLeak{FFlag::LuauFragmentAcMemoryLeak, true};
|
||||||
ScopedFastFlag luauGlobalVariableModuleIsolation{FFlag::LuauGlobalVariableModuleIsolation, true};
|
ScopedFastFlag luauGlobalVariableModuleIsolation{FFlag::LuauGlobalVariableModuleIsolation, true};
|
||||||
ScopedFastFlag luauFragmentAutocompleteIfRecommendations{FFlag::LuauFragmentAutocompleteIfRecommendations, true};
|
ScopedFastFlag luauFragmentAutocompleteIfRecommendations{FFlag::LuauFragmentAutocompleteIfRecommendations, true};
|
||||||
|
@ -2526,7 +2513,6 @@ l
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(FragmentAutocompleteFixture, "do_not_recommend_results_in_multiline_comment")
|
TEST_CASE_FIXTURE(FragmentAutocompleteFixture, "do_not_recommend_results_in_multiline_comment")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff = {FFlag::LuauBetterCursorInCommentDetection, true};
|
|
||||||
std::string source = R"(--[[
|
std::string source = R"(--[[
|
||||||
)";
|
)";
|
||||||
std::string dest = R"(--[[
|
std::string dest = R"(--[[
|
||||||
|
@ -2547,7 +2533,6 @@ a
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(FragmentAutocompleteFixture, "no_recs_for_comments_simple")
|
TEST_CASE_FIXTURE(FragmentAutocompleteFixture, "no_recs_for_comments_simple")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff = {FFlag::LuauBetterCursorInCommentDetection, true};
|
|
||||||
const std::string source = R"(
|
const std::string source = R"(
|
||||||
-- sel
|
-- sel
|
||||||
-- retur
|
-- retur
|
||||||
|
@ -2583,7 +2568,6 @@ bar
|
||||||
baz
|
baz
|
||||||
]]
|
]]
|
||||||
)";
|
)";
|
||||||
ScopedFastFlag sff{FFlag::LuauBetterCursorInCommentDetection, true};
|
|
||||||
autocompleteFragmentInBothSolvers(
|
autocompleteFragmentInBothSolvers(
|
||||||
source,
|
source,
|
||||||
source,
|
source,
|
||||||
|
@ -2628,7 +2612,6 @@ baz
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(FragmentAutocompleteFixture, "no_recs_for_comments")
|
TEST_CASE_FIXTURE(FragmentAutocompleteFixture, "no_recs_for_comments")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff = {FFlag::LuauBetterCursorInCommentDetection, true};
|
|
||||||
const std::string source = R"(
|
const std::string source = R"(
|
||||||
-- sel
|
-- sel
|
||||||
-- retur
|
-- retur
|
||||||
|
@ -2708,7 +2691,6 @@ if x == 5
|
||||||
local x = 5
|
local x = 5
|
||||||
if x == 5 then -- a comment
|
if x == 5 then -- a comment
|
||||||
)";
|
)";
|
||||||
ScopedFastFlag sff = {FFlag::LuauBetterCursorInCommentDetection, true};
|
|
||||||
autocompleteFragmentInBothSolvers(
|
autocompleteFragmentInBothSolvers(
|
||||||
source,
|
source,
|
||||||
updated,
|
updated,
|
||||||
|
@ -2964,7 +2946,6 @@ return module
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(FragmentAutocompleteBuiltinsFixture, "ice_caused_by_mixed_mode_use")
|
TEST_CASE_FIXTURE(FragmentAutocompleteBuiltinsFixture, "ice_caused_by_mixed_mode_use")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauAutocompleteUsesModuleForTypeCompatibility, true};
|
|
||||||
const std::string source =
|
const std::string source =
|
||||||
std::string("--[[\n\tPackage link auto-generated by Rotriever\n]]\nlocal PackageIndex = script.Parent._Index\n\nlocal Package = ") +
|
std::string("--[[\n\tPackage link auto-generated by Rotriever\n]]\nlocal PackageIndex = script.Parent._Index\n\nlocal Package = ") +
|
||||||
"require(PackageIndex[\"ReactOtter\"][\"ReactOtter\"])\n\nexport type Goal = Package.Goal\nexport type SpringOptions " +
|
"require(PackageIndex[\"ReactOtter\"][\"ReactOtter\"])\n\nexport type Goal = Package.Goal\nexport type SpringOptions " +
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(DebugLuauForbidInternalTypes)
|
LUAU_FASTFLAG(DebugLuauForbidInternalTypes)
|
||||||
LUAU_FASTFLAG(LuauTrackInferredFunctionTypeFromCall)
|
LUAU_FASTFLAG(LuauTrackInferredFunctionTypeFromCall)
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ TEST_CASE_FIXTURE(GeneralizationFixture, "('a) -> 'a")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(GeneralizationFixture, "(t1, (t1 <: 'b)) -> () where t1 = ('a <: (t1 <: 'b) & {number} & {number})")
|
TEST_CASE_FIXTURE(GeneralizationFixture, "(t1, (t1 <: 'b)) -> () where t1 = ('a <: (t1 <: 'b) & {number} & {number})")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauNonReentrantGeneralization3, true};
|
ScopedFastFlag sff{FFlag::LuauEagerGeneralization, true};
|
||||||
|
|
||||||
TableType tt;
|
TableType tt;
|
||||||
tt.indexer = TableIndexer{builtinTypes.numberType, builtinTypes.numberType};
|
tt.indexer = TableIndexer{builtinTypes.numberType, builtinTypes.numberType};
|
||||||
|
@ -260,7 +260,7 @@ TEST_CASE_FIXTURE(GeneralizationFixture, "(('a <: number | string)) -> string?")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(GeneralizationFixture, "(('a <: {'b})) -> ()")
|
TEST_CASE_FIXTURE(GeneralizationFixture, "(('a <: {'b})) -> ()")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauNonReentrantGeneralization3, true};
|
ScopedFastFlag sff{FFlag::LuauEagerGeneralization, true};
|
||||||
|
|
||||||
auto [aTy, aFree] = freshType();
|
auto [aTy, aFree] = freshType();
|
||||||
auto [bTy, bFree] = freshType();
|
auto [bTy, bFree] = freshType();
|
||||||
|
|
|
@ -8,13 +8,13 @@
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3);
|
LUAU_FASTFLAG(LuauEagerGeneralization);
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("InferPolarity");
|
TEST_SUITE_BEGIN("InferPolarity");
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "T where T = { m: <a>(a) -> T }")
|
TEST_CASE_FIXTURE(Fixture, "T where T = { m: <a>(a) -> T }")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauNonReentrantGeneralization3, true};
|
ScopedFastFlag sff{FFlag::LuauEagerGeneralization, true};
|
||||||
|
|
||||||
TypeArena arena;
|
TypeArena arena;
|
||||||
ScopePtr globalScope = std::make_shared<Scope>(builtinTypes->anyTypePack);
|
ScopePtr globalScope = std::make_shared<Scope>(builtinTypes->anyTypePack);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
LUAU_FASTFLAG(LuauSolverV2);
|
LUAU_FASTFLAG(LuauSolverV2);
|
||||||
LUAU_FASTFLAG(LintRedundantNativeAttribute);
|
LUAU_FASTFLAG(LintRedundantNativeAttribute);
|
||||||
LUAU_FASTFLAG(LuauDeprecatedAttribute);
|
LUAU_FASTFLAG(LuauDeprecatedAttribute);
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3);
|
LUAU_FASTFLAG(LuauEagerGeneralization);
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
|
@ -1942,7 +1942,7 @@ print(foo:bar(2.0))
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "TableOperations")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "TableOperations")
|
||||||
{
|
{
|
||||||
// FIXME: For now this flag causes a stack overflow on Windows.
|
// FIXME: For now this flag causes a stack overflow on Windows.
|
||||||
ScopedFastFlag _{FFlag::LuauNonReentrantGeneralization3, false};
|
ScopedFastFlag _{FFlag::LuauEagerGeneralization, false};
|
||||||
|
|
||||||
LintResult result = lint(R"(
|
LintResult result = lint(R"(
|
||||||
local t = {}
|
local t = {}
|
||||||
|
|
|
@ -280,8 +280,6 @@ TEST_CASE_FIXTURE(Fixture, "clone_class")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "clone_free_types")
|
TEST_CASE_FIXTURE(Fixture, "clone_free_types")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
TypeArena arena;
|
TypeArena arena;
|
||||||
TypeId freeTy = freshType(NotNull{&arena}, builtinTypes, nullptr);
|
TypeId freeTy = freshType(NotNull{&arena}, builtinTypes, nullptr);
|
||||||
TypePackVar freeTp(FreeTypePack{TypeLevel{}});
|
TypePackVar freeTp(FreeTypePack{TypeLevel{}});
|
||||||
|
|
|
@ -14,8 +14,7 @@ LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||||
LUAU_FASTINT(LuauNormalizeIntersectionLimit)
|
LUAU_FASTINT(LuauNormalizeIntersectionLimit)
|
||||||
LUAU_FASTINT(LuauNormalizeUnionLimit)
|
LUAU_FASTINT(LuauNormalizeUnionLimit)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
|
||||||
LUAU_FASTFLAG(LuauRefineWaitForBlockedTypesInTarget)
|
LUAU_FASTFLAG(LuauRefineWaitForBlockedTypesInTarget)
|
||||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
||||||
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
||||||
|
@ -1177,57 +1176,6 @@ end
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_limit_function_intersection_complexity")
|
|
||||||
{
|
|
||||||
ScopedFastInt luauTypeInferRecursionLimit{FInt::LuauTypeInferRecursionLimit, 80};
|
|
||||||
ScopedFastInt luauNormalizeIntersectionLimit{FInt::LuauNormalizeIntersectionLimit, 50};
|
|
||||||
ScopedFastInt luauNormalizeUnionLimit{FInt::LuauNormalizeUnionLimit, 20};
|
|
||||||
|
|
||||||
ScopedFastFlag _[] = {
|
|
||||||
{FFlag::LuauClipVariadicAnysFromArgsToGenericFuncs2, true},
|
|
||||||
{FFlag::DebugLuauGreedyGeneralization, true},
|
|
||||||
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
|
||||||
{FFlag::LuauNoMoreInjectiveTypeFunctions, true}
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
|
||||||
function _(_).readu32(l0)
|
|
||||||
return ({[_(_(_))]=_,[_(if _ then _)]=_,n0=_,})[_],nil
|
|
||||||
end
|
|
||||||
_(_)[_(n32)] %= _(_(_))
|
|
||||||
)");
|
|
||||||
|
|
||||||
LUAU_REQUIRE_ERRORS(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_propagate_normalization_failures")
|
|
||||||
{
|
|
||||||
ScopedFastInt luauNormalizeIntersectionLimit{FInt::LuauNormalizeIntersectionLimit, 50};
|
|
||||||
ScopedFastInt luauNormalizeUnionLimit{FInt::LuauNormalizeUnionLimit, 20};
|
|
||||||
|
|
||||||
ScopedFastFlag _[] = {
|
|
||||||
{FFlag::LuauSolverV2, true},
|
|
||||||
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
|
||||||
{FFlag::LuauClipVariadicAnysFromArgsToGenericFuncs2, true},
|
|
||||||
{FFlag::LuauSimplifyOutOfLine, true},
|
|
||||||
{FFlag::LuauNonReentrantGeneralization3, false},
|
|
||||||
{FFlag::DebugLuauGreedyGeneralization, true},
|
|
||||||
{FFlag::LuauNoMoreInjectiveTypeFunctions, true},
|
|
||||||
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
|
||||||
function _(_,"").readu32(l0)
|
|
||||||
return ({[_(_(_))]=_,[_(if _ then _,_())]=_,[""]=_,})[_],nil
|
|
||||||
end
|
|
||||||
_().readu32 %= _(_(_(_),_))
|
|
||||||
)");
|
|
||||||
|
|
||||||
LUAU_REQUIRE_ERRORS(result);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_flatten_type_pack_cycle")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_flatten_type_pack_cycle")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff[] = {{FFlag::LuauSolverV2, true}};
|
ScopedFastFlag sff[] = {{FFlag::LuauSolverV2, true}};
|
||||||
|
@ -1258,7 +1206,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_union_type_pack_cycle")
|
||||||
{FFlag::LuauNoMoreInjectiveTypeFunctions, true},
|
{FFlag::LuauNoMoreInjectiveTypeFunctions, true},
|
||||||
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
||||||
{FFlag::LuauClipVariadicAnysFromArgsToGenericFuncs2, true},
|
{FFlag::LuauClipVariadicAnysFromArgsToGenericFuncs2, true},
|
||||||
{FFlag::DebugLuauGreedyGeneralization, true}
|
{FFlag::LuauEagerGeneralization, true}
|
||||||
};
|
};
|
||||||
ScopedFastInt sfi{FInt::LuauTypeInferRecursionLimit, 0};
|
ScopedFastInt sfi{FInt::LuauTypeInferRecursionLimit, 0};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
||||||
LUAU_FASTFLAG(LuauParseStringIndexer)
|
LUAU_FASTFLAG(LuauParseStringIndexer)
|
||||||
LUAU_FASTFLAG(LuauDeclareExternType)
|
LUAU_FASTFLAG(LuauDeclareExternType)
|
||||||
|
LUAU_FASTFLAG(LuauStoreCSTData2)
|
||||||
LUAU_DYNAMIC_FASTFLAG(DebugLuauReportReturnTypeVariadicWithTypeSuffix)
|
LUAU_DYNAMIC_FASTFLAG(DebugLuauReportReturnTypeVariadicWithTypeSuffix)
|
||||||
|
|
||||||
// Clip with DebugLuauReportReturnTypeVariadicWithTypeSuffix
|
// Clip with DebugLuauReportReturnTypeVariadicWithTypeSuffix
|
||||||
|
@ -1260,8 +1261,6 @@ until false
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "parse_nesting_based_end_detection_local_function")
|
TEST_CASE_FIXTURE(Fixture, "parse_nesting_based_end_detection_local_function")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parse(R"(-- i am line 1
|
parse(R"(-- i am line 1
|
||||||
|
@ -1295,8 +1294,6 @@ end
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "parse_nesting_based_end_detection_failsafe_earlier")
|
TEST_CASE_FIXTURE(Fixture, "parse_nesting_based_end_detection_failsafe_earlier")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parse(R"(-- i am line 1
|
parse(R"(-- i am line 1
|
||||||
|
@ -2902,6 +2899,8 @@ TEST_CASE_FIXTURE(Fixture, "function_start_locations_are_before_attributes")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "for_loop_with_single_var_has_comma_positions_of_size_zero")
|
TEST_CASE_FIXTURE(Fixture, "for_loop_with_single_var_has_comma_positions_of_size_zero")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
|
|
||||||
ParseOptions parseOptions;
|
ParseOptions parseOptions;
|
||||||
parseOptions.storeCstData = true;
|
parseOptions.storeCstData = true;
|
||||||
|
|
||||||
|
@ -3364,8 +3363,6 @@ TEST_CASE_FIXTURE(Fixture, "AstName_comparison")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "generic_type_list_recovery")
|
TEST_CASE_FIXTURE(Fixture, "generic_type_list_recovery")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parse(R"(
|
parse(R"(
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauSubtypeGenericsAndNegations)
|
LUAU_FASTFLAG(LuauSubtypeGenericsAndNegations)
|
||||||
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
|
@ -1647,4 +1648,19 @@ TEST_CASE_FIXTURE(SubtypeFixture, "substitute_a_generic_for_a_negation")
|
||||||
CHECK(result.isSubtype);
|
CHECK(result.isSubtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(SubtypeFixture, "free_types_might_be_subtypes")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauEagerGeneralization, true};
|
||||||
|
|
||||||
|
TypeId argTy = arena.freshType(builtinTypes, moduleScope.get());
|
||||||
|
FreeType* freeArg = getMutable<FreeType>(argTy);
|
||||||
|
REQUIRE(freeArg);
|
||||||
|
freeArg->lowerBound = arena.addType(SingletonType{StringSingleton{"five"}});
|
||||||
|
freeArg->upperBound = builtinTypes->stringType;
|
||||||
|
|
||||||
|
SubtypingResult result = isSubtype(builtinTypes->stringType, argTy);
|
||||||
|
CHECK(result.isSubtype);
|
||||||
|
REQUIRE(1 == result.assumedConstraints.size());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
|
|
@ -322,8 +322,6 @@ n3 [label="TableType 3"];
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "free")
|
TEST_CASE_FIXTURE(Fixture, "free")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
Type type{TypeVariant{FreeType{TypeLevel{0, 0}, builtinTypes->neverType, builtinTypes->unknownType}}};
|
Type type{TypeVariant{FreeType{TypeLevel{0, 0}, builtinTypes->neverType, builtinTypes->unknownType}}};
|
||||||
ToDotOptions opts;
|
ToDotOptions opts;
|
||||||
opts.showPointers = false;
|
opts.showPointers = false;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "Fixture.h"
|
#include "Fixture.h"
|
||||||
|
|
||||||
#include "Luau/TypeChecker2.h"
|
#include "Luau/TypeChecker2.h"
|
||||||
|
#include "Luau/TypePack.h"
|
||||||
#include "ScopedFlags.h"
|
#include "ScopedFlags.h"
|
||||||
#include "doctest.h"
|
#include "doctest.h"
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ using namespace Luau;
|
||||||
LUAU_FASTFLAG(LuauRecursiveTypeParameterRestriction)
|
LUAU_FASTFLAG(LuauRecursiveTypeParameterRestriction)
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauAttributeSyntax)
|
LUAU_FASTFLAG(LuauAttributeSyntax)
|
||||||
|
LUAU_FASTFLAG(LuauFixEmptyTypePackStringification)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("ToString");
|
TEST_SUITE_BEGIN("ToString");
|
||||||
|
@ -492,6 +494,17 @@ TEST_CASE_FIXTURE(Fixture, "stringifying_array_uses_array_syntax")
|
||||||
CHECK_EQ("{string}", toString(Type{ttv}));
|
CHECK_EQ("{string}", toString(Type{ttv}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "the_empty_type_pack_should_be_parenthesized")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauFixEmptyTypePackStringification, true};
|
||||||
|
|
||||||
|
TypePackVar emptyTypePack{TypePack{}};
|
||||||
|
CHECK_EQ(toString(&emptyTypePack), "()");
|
||||||
|
|
||||||
|
auto unitToUnit = Type{FunctionType{&emptyTypePack, &emptyTypePack}};
|
||||||
|
CHECK_EQ(toString(&unitToUnit), "() -> ()");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "generic_packs_are_stringified_differently_from_generic_types")
|
TEST_CASE_FIXTURE(Fixture, "generic_packs_are_stringified_differently_from_generic_types")
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,8 +12,10 @@
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
|
LUAU_FASTFLAG(LuauStoreCSTData2)
|
||||||
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
LUAU_FASTFLAG(LuauStoreReturnTypesAsPackOnAst)
|
||||||
LUAU_FASTFLAG(LuauStoreLocalAnnotationColonPositions)
|
LUAU_FASTFLAG(LuauStoreLocalAnnotationColonPositions)
|
||||||
|
LUAU_FASTFLAG(LuauCSTForReturnTypeFunctionTail)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("TranspilerTests");
|
TEST_SUITE_BEGIN("TranspilerTests");
|
||||||
|
|
||||||
|
@ -47,6 +49,7 @@ TEST_CASE("string_literals_containing_utf8")
|
||||||
|
|
||||||
TEST_CASE("if_stmt_spaces_around_tokens")
|
TEST_CASE("if_stmt_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( if This then Once() end)";
|
const std::string one = R"( if This then Once() end)";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -95,15 +98,31 @@ TEST_CASE("elseif_chains_indent_sensibly")
|
||||||
TEST_CASE("strips_type_annotations")
|
TEST_CASE("strips_type_annotations")
|
||||||
{
|
{
|
||||||
const std::string code = R"( local s: string= 'hello there' )";
|
const std::string code = R"( local s: string= 'hello there' )";
|
||||||
|
if (FFlag::LuauStoreCSTData2)
|
||||||
|
{
|
||||||
const std::string expected = R"( local s = 'hello there' )";
|
const std::string expected = R"( local s = 'hello there' )";
|
||||||
CHECK_EQ(expected, transpile(code).code);
|
CHECK_EQ(expected, transpile(code).code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::string expected = R"( local s = 'hello there' )";
|
||||||
|
CHECK_EQ(expected, transpile(code).code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("strips_type_assertion_expressions")
|
TEST_CASE("strips_type_assertion_expressions")
|
||||||
{
|
{
|
||||||
const std::string code = R"( local s= some_function() :: any+ something_else() :: number )";
|
const std::string code = R"( local s= some_function() :: any+ something_else() :: number )";
|
||||||
|
if (FFlag::LuauStoreCSTData2)
|
||||||
|
{
|
||||||
const std::string expected = R"( local s= some_function() + something_else() )";
|
const std::string expected = R"( local s= some_function() + something_else() )";
|
||||||
CHECK_EQ(expected, transpile(code).code);
|
CHECK_EQ(expected, transpile(code).code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::string expected = R"( local s= some_function() + something_else() )";
|
||||||
|
CHECK_EQ(expected, transpile(code).code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_taking_ellipsis")
|
TEST_CASE("function_taking_ellipsis")
|
||||||
|
@ -130,6 +149,7 @@ TEST_CASE("for_loop")
|
||||||
|
|
||||||
TEST_CASE("for_loop_spaces_around_tokens")
|
TEST_CASE("for_loop_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( for index = 1, 10 do call(index) end )";
|
const std::string one = R"( for index = 1, 10 do call(index) end )";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -154,6 +174,7 @@ TEST_CASE("for_in_loop")
|
||||||
|
|
||||||
TEST_CASE("for_in_loop_spaces_around_tokens")
|
TEST_CASE("for_in_loop_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( for k, v in ipairs(x) do end )";
|
const std::string one = R"( for k, v in ipairs(x) do end )";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -172,6 +193,7 @@ TEST_CASE("for_in_loop_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE("for_in_single_variable")
|
TEST_CASE("for_in_single_variable")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( for key in pairs(x) do end )";
|
const std::string one = R"( for key in pairs(x) do end )";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
}
|
}
|
||||||
|
@ -184,6 +206,7 @@ TEST_CASE("while_loop")
|
||||||
|
|
||||||
TEST_CASE("while_loop_spaces_around_tokens")
|
TEST_CASE("while_loop_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( while f(x) do print() end )";
|
const std::string one = R"( while f(x) do print() end )";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -205,6 +228,7 @@ TEST_CASE("repeat_until_loop")
|
||||||
|
|
||||||
TEST_CASE("repeat_until_loop_condition_on_new_line")
|
TEST_CASE("repeat_until_loop_condition_on_new_line")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
repeat
|
repeat
|
||||||
print()
|
print()
|
||||||
|
@ -236,6 +260,7 @@ TEST_CASE("local_assignment")
|
||||||
|
|
||||||
TEST_CASE("local_assignment_spaces_around_tokens")
|
TEST_CASE("local_assignment_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( local x = 1 )";
|
const std::string one = R"( local x = 1 )";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -269,6 +294,7 @@ TEST_CASE("local_function")
|
||||||
|
|
||||||
TEST_CASE("local_function_spaces_around_tokens")
|
TEST_CASE("local_function_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( local function p(o, m, ...) end )";
|
const std::string one = R"( local function p(o, m, ...) end )";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -287,6 +313,7 @@ TEST_CASE("function")
|
||||||
|
|
||||||
TEST_CASE("function_spaces_around_tokens")
|
TEST_CASE("function_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string two = R"( function p(o, m, ...) end )";
|
const std::string two = R"( function p(o, m, ...) end )";
|
||||||
CHECK_EQ(two, transpile(two).code);
|
CHECK_EQ(two, transpile(two).code);
|
||||||
|
|
||||||
|
@ -315,6 +342,7 @@ TEST_CASE("function_spaces_around_tokens")
|
||||||
TEST_CASE("function_with_types_spaces_around_tokens")
|
TEST_CASE("function_with_types_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
||||||
{FFlag::LuauStoreLocalAnnotationColonPositions, true},
|
{FFlag::LuauStoreLocalAnnotationColonPositions, true},
|
||||||
};
|
};
|
||||||
|
@ -375,7 +403,7 @@ TEST_CASE("function_with_types_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE("returns_spaces_around_tokens")
|
TEST_CASE("returns_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string one = R"( return 1 )";
|
const std::string one = R"( return 1 )";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -388,7 +416,7 @@ TEST_CASE("returns_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "type_alias_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "type_alias_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( type Foo = string )";
|
std::string code = R"( type Foo = string )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -437,7 +465,7 @@ TEST_CASE_FIXTURE(Fixture, "type_alias_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "type_alias_with_defaults_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "type_alias_with_defaults_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( type Foo<X = string, Z... = ...any> = string )";
|
std::string code = R"( type Foo<X = string, Z... = ...any> = string )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -498,7 +526,7 @@ TEST_CASE("table_literal_closing_brace_at_correct_position")
|
||||||
|
|
||||||
TEST_CASE("table_literal_with_semicolon_separators")
|
TEST_CASE("table_literal_with_semicolon_separators")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
local t = { x = 1; y = 2 }
|
local t = { x = 1; y = 2 }
|
||||||
)";
|
)";
|
||||||
|
@ -508,7 +536,7 @@ TEST_CASE("table_literal_with_semicolon_separators")
|
||||||
|
|
||||||
TEST_CASE("table_literal_with_trailing_separators")
|
TEST_CASE("table_literal_with_trailing_separators")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
local t = { x = 1, y = 2, }
|
local t = { x = 1, y = 2, }
|
||||||
)";
|
)";
|
||||||
|
@ -518,7 +546,7 @@ TEST_CASE("table_literal_with_trailing_separators")
|
||||||
|
|
||||||
TEST_CASE("table_literal_with_spaces_around_separator")
|
TEST_CASE("table_literal_with_spaces_around_separator")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
local t = { x = 1 , y = 2 }
|
local t = { x = 1 , y = 2 }
|
||||||
)";
|
)";
|
||||||
|
@ -528,7 +556,7 @@ TEST_CASE("table_literal_with_spaces_around_separator")
|
||||||
|
|
||||||
TEST_CASE("table_literal_with_spaces_around_equals")
|
TEST_CASE("table_literal_with_spaces_around_equals")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
local t = { x = 1 }
|
local t = { x = 1 }
|
||||||
)";
|
)";
|
||||||
|
@ -538,7 +566,7 @@ TEST_CASE("table_literal_with_spaces_around_equals")
|
||||||
|
|
||||||
TEST_CASE("table_literal_multiline_with_indexers")
|
TEST_CASE("table_literal_multiline_with_indexers")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
local t = {
|
local t = {
|
||||||
["my first value"] = "x";
|
["my first value"] = "x";
|
||||||
|
@ -566,7 +594,15 @@ TEST_CASE("spaces_between_keywords_even_if_it_pushes_the_line_estimation_off")
|
||||||
// Luau::Parser doesn't exactly preserve the string representation of numbers in Lua, so we can find ourselves
|
// Luau::Parser doesn't exactly preserve the string representation of numbers in Lua, so we can find ourselves
|
||||||
// falling out of sync with the original code. We need to push keywords out so that there's at least one space between them.
|
// falling out of sync with the original code. We need to push keywords out so that there's at least one space between them.
|
||||||
const std::string code = R"( if math.abs(raySlope) < .01 then return 0 end )";
|
const std::string code = R"( if math.abs(raySlope) < .01 then return 0 end )";
|
||||||
|
if (FFlag::LuauStoreCSTData2)
|
||||||
|
{
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::string expected = R"( if math.abs(raySlope) < 0.01 then return 0 end)";
|
||||||
|
CHECK_EQ(expected, transpile(code).code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("numbers")
|
TEST_CASE("numbers")
|
||||||
|
@ -578,26 +614,34 @@ TEST_CASE("numbers")
|
||||||
TEST_CASE("infinity")
|
TEST_CASE("infinity")
|
||||||
{
|
{
|
||||||
const std::string code = R"( local a = 1e500 local b = 1e400 )";
|
const std::string code = R"( local a = 1e500 local b = 1e400 )";
|
||||||
|
if (FFlag::LuauStoreCSTData2)
|
||||||
|
{
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::string expected = R"( local a = 1e500 local b = 1e500 )";
|
||||||
|
CHECK_EQ(expected, transpile(code).code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("numbers_with_separators")
|
TEST_CASE("numbers_with_separators")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local a = 123_456_789 )";
|
const std::string code = R"( local a = 123_456_789 )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("hexadecimal_numbers")
|
TEST_CASE("hexadecimal_numbers")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local a = 0xFFFF )";
|
const std::string code = R"( local a = 0xFFFF )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("binary_numbers")
|
TEST_CASE("binary_numbers")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local a = 0b0101 )";
|
const std::string code = R"( local a = 0b0101 )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
@ -610,28 +654,28 @@ TEST_CASE("single_quoted_strings")
|
||||||
|
|
||||||
TEST_CASE("double_quoted_strings")
|
TEST_CASE("double_quoted_strings")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local a = "hello world" )";
|
const std::string code = R"( local a = "hello world" )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("simple_interp_string")
|
TEST_CASE("simple_interp_string")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local a = `hello world` )";
|
const std::string code = R"( local a = `hello world` )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("raw_strings")
|
TEST_CASE("raw_strings")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local a = [[ hello world ]] )";
|
const std::string code = R"( local a = [[ hello world ]] )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("raw_strings_with_blocks")
|
TEST_CASE("raw_strings_with_blocks")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local a = [==[ hello world ]==] )";
|
const std::string code = R"( local a = [==[ hello world ]==] )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
@ -650,7 +694,7 @@ TEST_CASE("escaped_strings_2")
|
||||||
|
|
||||||
TEST_CASE("escaped_strings_newline")
|
TEST_CASE("escaped_strings_newline")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
print("foo \
|
print("foo \
|
||||||
bar")
|
bar")
|
||||||
|
@ -660,14 +704,14 @@ TEST_CASE("escaped_strings_newline")
|
||||||
|
|
||||||
TEST_CASE("escaped_strings_raw")
|
TEST_CASE("escaped_strings_raw")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( local x = [=[\v<((do|load)file|require)\s*\(?['"]\zs[^'"]+\ze['"]]=] )";
|
const std::string code = R"( local x = [=[\v<((do|load)file|require)\s*\(?['"]\zs[^'"]+\ze['"]]=] )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("position_correctly_updated_when_writing_multiline_string")
|
TEST_CASE("position_correctly_updated_when_writing_multiline_string")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
call([[
|
call([[
|
||||||
testing
|
testing
|
||||||
|
@ -713,56 +757,56 @@ TEST_CASE("function_call_parentheses_multiple_args_no_space")
|
||||||
|
|
||||||
TEST_CASE("function_call_parentheses_multiple_args_space_before_commas")
|
TEST_CASE("function_call_parentheses_multiple_args_space_before_commas")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call(arg1 ,arg3 ,arg3) )";
|
const std::string code = R"( call(arg1 ,arg3 ,arg3) )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_call_spaces_before_parentheses")
|
TEST_CASE("function_call_spaces_before_parentheses")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call () )";
|
const std::string code = R"( call () )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_call_spaces_within_parentheses")
|
TEST_CASE("function_call_spaces_within_parentheses")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call( ) )";
|
const std::string code = R"( call( ) )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_call_string_double_quotes")
|
TEST_CASE("function_call_string_double_quotes")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call "string" )";
|
const std::string code = R"( call "string" )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_call_string_single_quotes")
|
TEST_CASE("function_call_string_single_quotes")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call 'string' )";
|
const std::string code = R"( call 'string' )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_call_string_no_space")
|
TEST_CASE("function_call_string_no_space")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call'string' )";
|
const std::string code = R"( call'string' )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_call_table_literal")
|
TEST_CASE("function_call_table_literal")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call { x = 1 } )";
|
const std::string code = R"( call { x = 1 } )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("function_call_table_literal_no_space")
|
TEST_CASE("function_call_table_literal_no_space")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( call{x=1} )";
|
const std::string code = R"( call{x=1} )";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
}
|
}
|
||||||
|
@ -807,7 +851,7 @@ TEST_CASE("emit_a_do_block_in_cases_of_potentially_ambiguous_syntax")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "parentheses_multiline")
|
TEST_CASE_FIXTURE(Fixture, "parentheses_multiline")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
local test = (
|
local test = (
|
||||||
x
|
x
|
||||||
|
@ -819,6 +863,9 @@ local test = (
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "stmt_semicolon")
|
TEST_CASE_FIXTURE(Fixture, "stmt_semicolon")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"( local test = 1; )";
|
std::string code = R"( local test = 1; )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -828,6 +875,7 @@ TEST_CASE_FIXTURE(Fixture, "stmt_semicolon")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "do_block_ending_with_semicolon")
|
TEST_CASE_FIXTURE(Fixture, "do_block_ending_with_semicolon")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
do
|
do
|
||||||
return;
|
return;
|
||||||
|
@ -838,6 +886,9 @@ TEST_CASE_FIXTURE(Fixture, "do_block_ending_with_semicolon")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon")
|
TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
if init then
|
if init then
|
||||||
x = string.sub(x, utf8.offset(x, init));
|
x = string.sub(x, utf8.offset(x, init));
|
||||||
|
@ -848,6 +899,9 @@ TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon_2")
|
TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon_2")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
if (t < 1) then return c/2*t*t + b end;
|
if (t < 1) then return c/2*t*t + b end;
|
||||||
)";
|
)";
|
||||||
|
@ -856,6 +910,9 @@ TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon_2")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "for_loop_stmt_semicolon")
|
TEST_CASE_FIXTURE(Fixture, "for_loop_stmt_semicolon")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
for i,v in ... do
|
for i,v in ... do
|
||||||
end;
|
end;
|
||||||
|
@ -865,6 +922,9 @@ TEST_CASE_FIXTURE(Fixture, "for_loop_stmt_semicolon")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "while_do_semicolon")
|
TEST_CASE_FIXTURE(Fixture, "while_do_semicolon")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
while true do
|
while true do
|
||||||
end;
|
end;
|
||||||
|
@ -874,6 +934,9 @@ TEST_CASE_FIXTURE(Fixture, "while_do_semicolon")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "function_definition_semicolon")
|
TEST_CASE_FIXTURE(Fixture, "function_definition_semicolon")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
function foo()
|
function foo()
|
||||||
end;
|
end;
|
||||||
|
@ -951,7 +1014,16 @@ TEST_CASE("a_table_key_can_be_the_empty_string")
|
||||||
TEST_CASE("always_emit_a_space_after_local_keyword")
|
TEST_CASE("always_emit_a_space_after_local_keyword")
|
||||||
{
|
{
|
||||||
std::string code = "do local aZZZZ = Workspace.P1.Shape local bZZZZ = Enum.PartType.Cylinder end";
|
std::string code = "do local aZZZZ = Workspace.P1.Shape local bZZZZ = Enum.PartType.Cylinder end";
|
||||||
|
|
||||||
|
if (FFlag::LuauStoreCSTData2)
|
||||||
|
{
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string expected = "do local aZZZZ = Workspace.P1 .Shape local bZZZZ= Enum.PartType.Cylinder end";
|
||||||
|
CHECK_EQ(expected, transpile(code).code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "types_should_not_be_considered_cyclic_if_they_are_not_recursive")
|
TEST_CASE_FIXTURE(Fixture, "types_should_not_be_considered_cyclic_if_they_are_not_recursive")
|
||||||
|
@ -988,13 +1060,23 @@ TEST_CASE_FIXTURE(Fixture, "type_lists_should_be_emitted_correctly")
|
||||||
end
|
end
|
||||||
)";
|
)";
|
||||||
|
|
||||||
std::string expected = R"(
|
std::string expected = FFlag::LuauStoreCSTData2 ? R"(
|
||||||
local a:(a:string,b:number,...string)->(string,...number)=function(a:string,b:number,...:string): (string,...number)
|
local a:(a:string,b:number,...string)->(string,...number)=function(a:string,b:number,...:string): (string,...number)
|
||||||
end
|
end
|
||||||
|
|
||||||
local b:(...string)->(...number)=function(...:string): ...number
|
local b:(...string)->(...number)=function(...:string): ...number
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local c:()->()=function(): ()
|
||||||
|
end
|
||||||
|
)"
|
||||||
|
: R"(
|
||||||
|
local a:(string,number,...string)->(string,...number)=function(a:string,b:number,...:string): (string,...number)
|
||||||
|
end
|
||||||
|
|
||||||
|
local b:(...string)->(...number)=function(...:string): ...number
|
||||||
|
end
|
||||||
|
|
||||||
local c:()->()=function(): ()
|
local c:()->()=function(): ()
|
||||||
end
|
end
|
||||||
)";
|
)";
|
||||||
|
@ -1034,7 +1116,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_type_assertion")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "type_assertion_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "type_assertion_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = "local a = 5 :: number";
|
std::string code = "local a = 5 :: number";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1051,7 +1133,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_if_then_else")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_if_then_else_multiple_conditions")
|
TEST_CASE_FIXTURE(Fixture, "transpile_if_then_else_multiple_conditions")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = "local a = if 1 then 2 elseif 3 then 4 else 5";
|
std::string code = "local a = if 1 then 2 elseif 3 then 4 else 5";
|
||||||
|
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
|
@ -1059,7 +1141,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_if_then_else_multiple_conditions")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_if_then_else_multiple_conditions_2")
|
TEST_CASE_FIXTURE(Fixture, "transpile_if_then_else_multiple_conditions_2")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
local x = if yes
|
local x = if yes
|
||||||
then nil
|
then nil
|
||||||
|
@ -1075,7 +1157,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_if_then_else_multiple_conditions_2")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "if_then_else_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "if_then_else_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = "local a = if 1 then 2 else 3";
|
std::string code = "local a = if 1 then 2 else 3";
|
||||||
CHECK_EQ(code, transpile(code).code);
|
CHECK_EQ(code, transpile(code).code);
|
||||||
|
|
||||||
|
@ -1112,7 +1194,7 @@ TEST_CASE_FIXTURE(Fixture, "if_then_else_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "if_then_else_spaces_between_else_if")
|
TEST_CASE_FIXTURE(Fixture, "if_then_else_spaces_between_else_if")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
return
|
return
|
||||||
if a then "was a" else
|
if a then "was a" else
|
||||||
|
@ -1140,7 +1222,7 @@ local a: Import.Type
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_type_reference_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_type_reference_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( local _: Foo.Type )";
|
std::string code = R"( local _: Foo.Type )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1169,6 +1251,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_type_reference_spaces_around_tokens")
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_type_annotation_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_type_annotation_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreLocalAnnotationColonPositions, true},
|
{FFlag::LuauStoreLocalAnnotationColonPositions, true},
|
||||||
};
|
};
|
||||||
std::string code = R"( local _: Type )";
|
std::string code = R"( local _: Type )";
|
||||||
|
@ -1190,6 +1273,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_type_annotation_spaces_around_tokens")
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_for_loop_annotation_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_for_loop_annotation_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreLocalAnnotationColonPositions, true},
|
{FFlag::LuauStoreLocalAnnotationColonPositions, true},
|
||||||
};
|
};
|
||||||
std::string code = R"( for i: number = 1, 10 do end )";
|
std::string code = R"( for i: number = 1, 10 do end )";
|
||||||
|
@ -1230,7 +1314,7 @@ local b: Packed<(number, string)>
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "type_packs_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "type_packs_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( type _ = Packed< T...> )";
|
std::string code = R"( type _ = Packed< T...> )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1288,7 +1372,11 @@ TEST_CASE_FIXTURE(Fixture, "transpile_union_type_nested_2")
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_union_type_nested_3")
|
TEST_CASE_FIXTURE(Fixture, "transpile_union_type_nested_3")
|
||||||
{
|
{
|
||||||
std::string code = "local a: nil | (string & number)";
|
std::string code = "local a: nil | (string & number)";
|
||||||
|
|
||||||
|
if (FFlag::LuauStoreCSTData2)
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
else
|
||||||
|
CHECK_EQ("local a: (string & number)?", transpile(code, {}, true).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_intersection_type_nested")
|
TEST_CASE_FIXTURE(Fixture, "transpile_intersection_type_nested")
|
||||||
|
@ -1308,6 +1396,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_intersection_type_nested_2")
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_intersection_type_with_function")
|
TEST_CASE_FIXTURE(Fixture, "transpile_intersection_type_with_function")
|
||||||
{
|
{
|
||||||
ScopedFastFlag flags[] = {
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
||||||
};
|
};
|
||||||
std::string code = "type FnB<U...> = () -> U... & T";
|
std::string code = "type FnB<U...> = () -> U... & T";
|
||||||
|
@ -1317,6 +1406,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_intersection_type_with_function")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_leading_union_pipe")
|
TEST_CASE_FIXTURE(Fixture, "transpile_leading_union_pipe")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = "local a: | string | number";
|
std::string code = "local a: | string | number";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1326,6 +1418,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_leading_union_pipe")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_union_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_union_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = "local a: string | number";
|
std::string code = "local a: string | number";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1335,6 +1430,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_union_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_leading_intersection_ampersand")
|
TEST_CASE_FIXTURE(Fixture, "transpile_leading_intersection_ampersand")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = "local a: & string & number";
|
std::string code = "local a: & string & number";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1344,6 +1442,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_leading_intersection_ampersand")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_intersection_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_intersection_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = "local a: string & number";
|
std::string code = "local a: string & number";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1353,6 +1454,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_intersection_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_mixed_union_intersection")
|
TEST_CASE_FIXTURE(Fixture, "transpile_mixed_union_intersection")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = "local a: string | (Foo & Bar)";
|
std::string code = "local a: string | (Foo & Bar)";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1377,6 +1481,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_mixed_union_intersection")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_preserve_union_optional_style")
|
TEST_CASE_FIXTURE(Fixture, "transpile_preserve_union_optional_style")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = "local a: string | nil";
|
std::string code = "local a: string | nil";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1408,7 +1515,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_varargs")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "index_name_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "index_name_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string one = "local _ = a.name";
|
std::string one = "local _ = a.name";
|
||||||
CHECK_EQ(one, transpile(one, {}, true).code);
|
CHECK_EQ(one, transpile(one, {}, true).code);
|
||||||
|
|
||||||
|
@ -1421,7 +1528,7 @@ TEST_CASE_FIXTURE(Fixture, "index_name_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "index_name_ends_with_digit")
|
TEST_CASE_FIXTURE(Fixture, "index_name_ends_with_digit")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = "sparkles.Color = Color3.new()";
|
std::string code = "sparkles.Color = Color3.new()";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
}
|
}
|
||||||
|
@ -1435,7 +1542,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_index_expr")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "index_expr_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "index_expr_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string one = "local _ = a[2]";
|
std::string one = "local _ = a[2]";
|
||||||
CHECK_EQ(one, transpile(one, {}, true).code);
|
CHECK_EQ(one, transpile(one, {}, true).code);
|
||||||
|
|
||||||
|
@ -1479,7 +1586,7 @@ local _ = # e
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "binary_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "binary_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
local _ = 1+1
|
local _ = 1+1
|
||||||
local _ = 1 +1
|
local _ = 1 +1
|
||||||
|
@ -1521,7 +1628,7 @@ a ..= ' - result'
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "compound_assignment_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "compound_assignment_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string one = R"( a += 1 )";
|
std::string one = R"( a += 1 )";
|
||||||
CHECK_EQ(one, transpile(one, {}, true).code);
|
CHECK_EQ(one, transpile(one, {}, true).code);
|
||||||
|
|
||||||
|
@ -1538,7 +1645,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_assign_multiple")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_assign_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_assign_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string one = "a = 1";
|
std::string one = "a = 1";
|
||||||
CHECK_EQ(one, transpile(one).code);
|
CHECK_EQ(one, transpile(one).code);
|
||||||
|
|
||||||
|
@ -1574,7 +1681,11 @@ local f: <T,S...>(T, S...)->(number) = foo
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_union_reverse")
|
TEST_CASE_FIXTURE(Fixture, "transpile_union_reverse")
|
||||||
{
|
{
|
||||||
std::string code = "local a: nil | number";
|
std::string code = "local a: nil | number";
|
||||||
|
|
||||||
|
if (FFlag::LuauStoreCSTData2)
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
else
|
||||||
|
CHECK_EQ("local a: number?", transpile(code, {}, true).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_for_in_multiple")
|
TEST_CASE_FIXTURE(Fixture, "transpile_for_in_multiple")
|
||||||
|
@ -1689,6 +1800,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_for_in_multiple_types")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp")
|
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag fflags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"( local _ = `hello {name}` )";
|
std::string code = R"( local _ = `hello {name}` )";
|
||||||
|
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
@ -1696,6 +1810,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_string_interp")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_multiline")
|
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_multiline")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag fflags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"( local _ = `hello {
|
std::string code = R"( local _ = `hello {
|
||||||
name
|
name
|
||||||
}!` )";
|
}!` )";
|
||||||
|
@ -1705,6 +1822,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_multiline")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_on_new_line")
|
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_on_new_line")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag fflags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
error(
|
error(
|
||||||
`a {b} c`
|
`a {b} c`
|
||||||
|
@ -1716,6 +1836,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_on_new_line")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_multiline_escape")
|
TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_multiline_escape")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( local _ = `hello \
|
std::string code = R"( local _ = `hello \
|
||||||
world!` )";
|
world!` )";
|
||||||
|
|
||||||
|
@ -1724,6 +1845,9 @@ TEST_CASE_FIXTURE(Fixture, "transpile_string_interp_multiline_escape")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_string_literal_escape")
|
TEST_CASE_FIXTURE(Fixture, "transpile_string_literal_escape")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag fflags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
std::string code = R"( local _ = ` bracket = \{, backtick = \` = {'ok'} ` )";
|
std::string code = R"( local _ = ` bracket = \{, backtick = \` = {'ok'} ` )";
|
||||||
|
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
@ -1738,6 +1862,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_type_functions")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_type_functions_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_type_functions_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( type function foo() end )";
|
std::string code = R"( type function foo() end )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1753,6 +1878,7 @@ TEST_CASE_FIXTURE(Fixture, "transpile_type_functions_spaces_around_tokens")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "transpile_typeof_spaces_around_tokens")
|
TEST_CASE_FIXTURE(Fixture, "transpile_typeof_spaces_around_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( type X = typeof(x) )";
|
std::string code = R"( type X = typeof(x) )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1777,14 +1903,14 @@ TEST_CASE("transpile_single_quoted_string_types")
|
||||||
|
|
||||||
TEST_CASE("transpile_double_quoted_string_types")
|
TEST_CASE("transpile_double_quoted_string_types")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( type a = "hello world" )";
|
const std::string code = R"( type a = "hello world" )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("transpile_raw_string_types")
|
TEST_CASE("transpile_raw_string_types")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( type a = [[ hello world ]] )";
|
std::string code = R"( type a = [[ hello world ]] )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1794,14 +1920,14 @@ TEST_CASE("transpile_raw_string_types")
|
||||||
|
|
||||||
TEST_CASE("transpile_escaped_string_types")
|
TEST_CASE("transpile_escaped_string_types")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"( type a = "\\b\\t\\n\\\\" )";
|
const std::string code = R"( type a = "\\b\\t\\n\\\\" )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("transpile_type_table_semicolon_separators")
|
TEST_CASE("transpile_type_table_semicolon_separators")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
const std::string code = R"(
|
const std::string code = R"(
|
||||||
type Foo = {
|
type Foo = {
|
||||||
bar: number;
|
bar: number;
|
||||||
|
@ -1813,7 +1939,7 @@ TEST_CASE("transpile_type_table_semicolon_separators")
|
||||||
|
|
||||||
TEST_CASE("transpile_type_table_access_modifiers")
|
TEST_CASE("transpile_type_table_access_modifiers")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
type Foo = {
|
type Foo = {
|
||||||
read bar: number,
|
read bar: number,
|
||||||
|
@ -1834,7 +1960,7 @@ TEST_CASE("transpile_type_table_access_modifiers")
|
||||||
|
|
||||||
TEST_CASE("transpile_type_table_spaces_between_tokens")
|
TEST_CASE("transpile_type_table_spaces_between_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"( type Foo = { bar: number, } )";
|
std::string code = R"( type Foo = { bar: number, } )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
@ -1877,7 +2003,7 @@ TEST_CASE("transpile_type_table_spaces_between_tokens")
|
||||||
|
|
||||||
TEST_CASE("transpile_type_table_preserve_original_indexer_style")
|
TEST_CASE("transpile_type_table_preserve_original_indexer_style")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
type Foo = {
|
type Foo = {
|
||||||
[number]: string
|
[number]: string
|
||||||
|
@ -1893,7 +2019,7 @@ TEST_CASE("transpile_type_table_preserve_original_indexer_style")
|
||||||
|
|
||||||
TEST_CASE("transpile_type_table_preserve_indexer_location")
|
TEST_CASE("transpile_type_table_preserve_indexer_location")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
type Foo = {
|
type Foo = {
|
||||||
[number]: string,
|
[number]: string,
|
||||||
|
@ -1922,7 +2048,7 @@ TEST_CASE("transpile_type_table_preserve_indexer_location")
|
||||||
|
|
||||||
TEST_CASE("transpile_type_table_preserve_property_definition_style")
|
TEST_CASE("transpile_type_table_preserve_property_definition_style")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
type Foo = {
|
type Foo = {
|
||||||
["$$typeof1"]: string,
|
["$$typeof1"]: string,
|
||||||
|
@ -1934,7 +2060,7 @@ TEST_CASE("transpile_type_table_preserve_property_definition_style")
|
||||||
|
|
||||||
TEST_CASE("transpile_type_table_string_properties_spaces_between_tokens")
|
TEST_CASE("transpile_type_table_string_properties_spaces_between_tokens")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
type Foo = {
|
type Foo = {
|
||||||
[ "$$typeof1"]: string,
|
[ "$$typeof1"]: string,
|
||||||
|
@ -1946,6 +2072,9 @@ TEST_CASE("transpile_type_table_string_properties_spaces_between_tokens")
|
||||||
|
|
||||||
TEST_CASE("transpile_types_preserve_parentheses_style")
|
TEST_CASE("transpile_types_preserve_parentheses_style")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
};
|
||||||
|
|
||||||
std::string code = R"( type Foo = number )";
|
std::string code = R"( type Foo = number )";
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
@ -1985,6 +2114,7 @@ end
|
||||||
TEST_CASE("transpile_type_function_unnamed_arguments")
|
TEST_CASE("transpile_type_function_unnamed_arguments")
|
||||||
{
|
{
|
||||||
ScopedFastFlag flags[] = {
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
||||||
};
|
};
|
||||||
std::string code = R"( type Foo = () -> () )";
|
std::string code = R"( type Foo = () -> () )";
|
||||||
|
@ -2021,6 +2151,7 @@ TEST_CASE("transpile_type_function_unnamed_arguments")
|
||||||
TEST_CASE("transpile_type_function_named_arguments")
|
TEST_CASE("transpile_type_function_named_arguments")
|
||||||
{
|
{
|
||||||
ScopedFastFlag flags[] = {
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
||||||
};
|
};
|
||||||
std::string code = R"( type Foo = (x: string) -> () )";
|
std::string code = R"( type Foo = (x: string) -> () )";
|
||||||
|
@ -2051,6 +2182,7 @@ TEST_CASE("transpile_type_function_named_arguments")
|
||||||
TEST_CASE("transpile_type_function_generics")
|
TEST_CASE("transpile_type_function_generics")
|
||||||
{
|
{
|
||||||
ScopedFastFlag flags[] = {
|
ScopedFastFlag flags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
||||||
};
|
};
|
||||||
std::string code = R"( type Foo = <X, Y, Z...>() -> () )";
|
std::string code = R"( type Foo = <X, Y, Z...>() -> () )";
|
||||||
|
@ -2087,6 +2219,7 @@ TEST_CASE("transpile_type_function_generics")
|
||||||
TEST_CASE("transpile_type_function_return_types")
|
TEST_CASE("transpile_type_function_return_types")
|
||||||
{
|
{
|
||||||
ScopedFastFlag fflags[] = {
|
ScopedFastFlag fflags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
||||||
};
|
};
|
||||||
std::string code = R"( type Foo = () -> () )";
|
std::string code = R"( type Foo = () -> () )";
|
||||||
|
@ -2132,6 +2265,23 @@ TEST_CASE("transpile_type_function_return_types")
|
||||||
CHECK_EQ(code, transpile(code, {}, true).code);
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("transpile_chained_function_types")
|
||||||
|
{
|
||||||
|
ScopedFastFlag fflags[] = {
|
||||||
|
{FFlag::LuauStoreCSTData2, true},
|
||||||
|
{FFlag::LuauStoreReturnTypesAsPackOnAst, true},
|
||||||
|
{FFlag::LuauCSTForReturnTypeFunctionTail, true},
|
||||||
|
};
|
||||||
|
std::string code = R"( type Foo = () -> () -> () )";
|
||||||
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
code = R"( type Foo = () -> () -> () )";
|
||||||
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
|
||||||
|
code = R"( type Foo = () -> () -> () )";
|
||||||
|
CHECK_EQ(code, transpile(code, {}, true).code);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("fuzzer_nil_optional")
|
TEST_CASE("fuzzer_nil_optional")
|
||||||
{
|
{
|
||||||
const std::string code = R"( local x: nil? )";
|
const std::string code = R"( local x: nil? )";
|
||||||
|
@ -2140,7 +2290,7 @@ TEST_CASE("fuzzer_nil_optional")
|
||||||
|
|
||||||
TEST_CASE("transpile_function_attributes")
|
TEST_CASE("transpile_function_attributes")
|
||||||
{
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauStoreCSTData2, true};
|
||||||
std::string code = R"(
|
std::string code = R"(
|
||||||
@native
|
@native
|
||||||
function foo()
|
function foo()
|
||||||
|
|
|
@ -14,7 +14,7 @@ using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_DYNAMIC_FASTINT(LuauTypeFamilyApplicationCartesianProductLimit)
|
LUAU_DYNAMIC_FASTINT(LuauTypeFamilyApplicationCartesianProductLimit)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauHasPropProperBlock)
|
LUAU_FASTFLAG(LuauHasPropProperBlock)
|
||||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
@ -1725,7 +1725,7 @@ struct TFFixture
|
||||||
TypeFunctionRuntime runtime{NotNull{&ice}, NotNull{&limits}};
|
TypeFunctionRuntime runtime{NotNull{&ice}, NotNull{&limits}};
|
||||||
|
|
||||||
const ScopedFastFlag sff[1] = {
|
const ScopedFastFlag sff[1] = {
|
||||||
{FFlag::DebugLuauGreedyGeneralization, true},
|
{FFlag::LuauEagerGeneralization, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
BuiltinTypeFunctions builtinTypeFunctions;
|
BuiltinTypeFunctions builtinTypeFunctions;
|
||||||
|
|
|
@ -9,6 +9,7 @@ using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
||||||
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("UserDefinedTypeFunctionTests");
|
TEST_SUITE_BEGIN("UserDefinedTypeFunctionTests");
|
||||||
|
@ -1986,13 +1987,20 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "udtf_singleton_equality_bool")
|
||||||
{
|
{
|
||||||
ScopedFastFlag newSolver{FFlag::LuauSolverV2, true};
|
ScopedFastFlag newSolver{FFlag::LuauSolverV2, true};
|
||||||
|
|
||||||
|
if (FFlag::LuauEagerGeneralization)
|
||||||
|
{
|
||||||
|
// FIXME: CLI-151985
|
||||||
|
// This test breaks because we can't see that eq<type?, b> is already fully reduced.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
type function compare(arg)
|
type function compare(arg)
|
||||||
return types.singleton(types.singleton(false) == arg)
|
return types.singleton(types.singleton(false) == arg)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ok(idx: compare<false>): true return idx end
|
local function ok1(idx: compare<false>): true return idx end
|
||||||
local function ok(idx: compare<true>): false return idx end
|
local function ok2(idx: compare<true>): false return idx end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
@ -2002,6 +2010,13 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "udtf_singleton_equality_string")
|
||||||
{
|
{
|
||||||
ScopedFastFlag newSolver{FFlag::LuauSolverV2, true};
|
ScopedFastFlag newSolver{FFlag::LuauSolverV2, true};
|
||||||
|
|
||||||
|
if (FFlag::LuauEagerGeneralization)
|
||||||
|
{
|
||||||
|
// FIXME: CLI-151985
|
||||||
|
// This test breaks because we can't see that eq<type?, b> is already fully reduced.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
type function compare(arg)
|
type function compare(arg)
|
||||||
return types.singleton(types.singleton("") == arg)
|
return types.singleton(types.singleton("") == arg)
|
||||||
|
|
|
@ -12,7 +12,7 @@ using namespace Luau;
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauRetainDefinitionAliasLocations)
|
LUAU_FASTFLAG(LuauRetainDefinitionAliasLocations)
|
||||||
LUAU_FASTFLAG(LuauNewNonStrictVisitTypes2)
|
LUAU_FASTFLAG(LuauNewNonStrictVisitTypes2)
|
||||||
LUAU_FASTFLAG(LuauGuardAgainstMalformedTypeAliasExpansion)
|
LUAU_FASTFLAG(LuauGuardAgainstMalformedTypeAliasExpansion2)
|
||||||
LUAU_FASTFLAG(LuauSkipMalformedTypeAliases)
|
LUAU_FASTFLAG(LuauSkipMalformedTypeAliases)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
|
||||||
|
@ -355,8 +355,6 @@ TEST_CASE_FIXTURE(Fixture, "stringify_type_alias_of_recursive_template_table_typ
|
||||||
// Check that recursive intersection type doesn't generate an OOM
|
// Check that recursive intersection type doesn't generate an OOM
|
||||||
TEST_CASE_FIXTURE(Fixture, "cli_38393_recursive_intersection_oom")
|
TEST_CASE_FIXTURE(Fixture, "cli_38393_recursive_intersection_oom")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
function _(l0:(t0)&((t0)&(((t0)&((t0)->()))->(typeof(_),typeof(# _)))),l39,...):any
|
function _(l0:(t0)&((t0)&(((t0)&((t0)->()))->(typeof(_),typeof(# _)))),l39,...):any
|
||||||
end
|
end
|
||||||
|
@ -970,9 +968,6 @@ TEST_CASE_FIXTURE(Fixture, "type_alias_locations")
|
||||||
*/
|
*/
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "dont_lose_track_of_PendingExpansionTypes_after_substitution")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "dont_lose_track_of_PendingExpansionTypes_after_substitution")
|
||||||
{
|
{
|
||||||
// CLI-114134 - We need egraphs to properly simplify these types.
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
fileResolver.source["game/ReactCurrentDispatcher"] = R"(
|
fileResolver.source["game/ReactCurrentDispatcher"] = R"(
|
||||||
export type BasicStateAction<S> = ((S) -> S) | S
|
export type BasicStateAction<S> = ((S) -> S) | S
|
||||||
export type Dispatch<A> = (A) -> ()
|
export type Dispatch<A> = (A) -> ()
|
||||||
|
@ -1258,7 +1253,7 @@ TEST_CASE_FIXTURE(Fixture, "exported_type_function_location_is_accessible_on_mod
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "fuzzer_cursed_type_aliases")
|
TEST_CASE_FIXTURE(Fixture, "fuzzer_cursed_type_aliases")
|
||||||
{
|
{
|
||||||
ScopedFastFlag _{FFlag::LuauGuardAgainstMalformedTypeAliasExpansion, true};
|
ScopedFastFlag _{FFlag::LuauGuardAgainstMalformedTypeAliasExpansion2, true};
|
||||||
|
|
||||||
// This used to crash under the new solver: we would like this to continue
|
// This used to crash under the new solver: we would like this to continue
|
||||||
// to not crash.
|
// to not crash.
|
||||||
|
@ -1298,5 +1293,16 @@ TEST_CASE_FIXTURE(Fixture, "type_alias_dont_crash_on_duplicate_with_typeof")
|
||||||
CHECK(get<DuplicateTypeDefinition>(result.errors[0]));
|
CHECK(get<DuplicateTypeDefinition>(result.errors[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "fuzzer_more_cursed_aliases")
|
||||||
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauGuardAgainstMalformedTypeAliasExpansion2, true};
|
||||||
|
|
||||||
|
LUAU_REQUIRE_ERRORS(check(R"(
|
||||||
|
export type t138 = t0<t138>
|
||||||
|
export type t0<t0,t10,t10,t109> = t0
|
||||||
|
)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
|
|
@ -11,7 +11,7 @@ using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauTableCloneClonesType3)
|
LUAU_FASTFLAG(LuauTableCloneClonesType3)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauArityMismatchOnUndersaturatedUnknownArguments)
|
LUAU_FASTFLAG(LuauArityMismatchOnUndersaturatedUnknownArguments)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("BuiltinTests");
|
TEST_SUITE_BEGIN("BuiltinTests");
|
||||||
|
@ -460,7 +460,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "table_pack_reduce")
|
||||||
)");
|
)");
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
if (FFlag::LuauSolverV2 && FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauSolverV2 && FFlag::LuauEagerGeneralization)
|
||||||
CHECK("{ [number]: string | string | string, n: number }" == toString(requireType("t")));
|
CHECK("{ [number]: string | string | string, n: number }" == toString(requireType("t")));
|
||||||
else if (FFlag::LuauSolverV2)
|
else if (FFlag::LuauSolverV2)
|
||||||
CHECK_EQ("{ [number]: string, n: number }", toString(requireType("t")));
|
CHECK_EQ("{ [number]: string, n: number }", toString(requireType("t")));
|
||||||
|
|
|
@ -129,8 +129,6 @@ TEST_CASE_FIXTURE(ExternTypeFixture, "we_can_infer_that_a_parameter_must_be_a_pa
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(ExternTypeFixture, "we_can_report_when_someone_is_trying_to_use_a_table_rather_than_a_class")
|
TEST_CASE_FIXTURE(ExternTypeFixture, "we_can_report_when_someone_is_trying_to_use_a_table_rather_than_a_class")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
function makeClone(o)
|
function makeClone(o)
|
||||||
return BaseClass.Clone(o)
|
return BaseClass.Clone(o)
|
||||||
|
@ -472,9 +470,6 @@ Type 'number' could not be converted into 'string')";
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(ExternTypeFixture, "class_type_mismatch_with_name_conflict")
|
TEST_CASE_FIXTURE(ExternTypeFixture, "class_type_mismatch_with_name_conflict")
|
||||||
{
|
{
|
||||||
// CLI-116433
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local i = ChildClass.New()
|
local i = ChildClass.New()
|
||||||
type ChildClass = { x: number }
|
type ChildClass = { x: number }
|
||||||
|
|
|
@ -22,7 +22,7 @@ LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTINT(LuauTarjanChildLimit)
|
LUAU_FASTINT(LuauTarjanChildLimit)
|
||||||
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauArityMismatchOnUndersaturatedUnknownArguments)
|
LUAU_FASTFLAG(LuauArityMismatchOnUndersaturatedUnknownArguments)
|
||||||
LUAU_FASTFLAG(LuauHasPropProperBlock)
|
LUAU_FASTFLAG(LuauHasPropProperBlock)
|
||||||
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
||||||
|
@ -1038,9 +1038,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "calling_function_with_anytypepack_doesnt_lea
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "too_many_return_values")
|
TEST_CASE_FIXTURE(Fixture, "too_many_return_values")
|
||||||
{
|
{
|
||||||
// FIXME: CLI-116157 variadic and generic type packs seem to be interacting incorrectly.
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!strict
|
--!strict
|
||||||
|
|
||||||
|
@ -1472,9 +1469,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "variadic_any_is_compatible_with_a_generic_Ty
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "infer_anonymous_function_arguments_outside_call")
|
TEST_CASE_FIXTURE(Fixture, "infer_anonymous_function_arguments_outside_call")
|
||||||
{
|
{
|
||||||
// FIXME: CLI-116133 bidirectional type inference needs to push expected types in for higher-order function calls
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
type Table = { x: number, y: number }
|
type Table = { x: number, y: number }
|
||||||
local f: (Table) -> number = function(t) return t.x + t.y end
|
local f: (Table) -> number = function(t) return t.x + t.y end
|
||||||
|
@ -1694,7 +1688,7 @@ t.f = function(x)
|
||||||
end
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization && FFlag::LuauSolverV2)
|
if (FFlag::LuauEagerGeneralization && FFlag::LuauSolverV2)
|
||||||
{
|
{
|
||||||
// FIXME CLI-151985
|
// FIXME CLI-151985
|
||||||
LUAU_CHECK_ERROR_COUNT(3, result);
|
LUAU_CHECK_ERROR_COUNT(3, result);
|
||||||
|
@ -1779,7 +1773,7 @@ t.f = function(x)
|
||||||
end
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization && FFlag::LuauSolverV2)
|
if (FFlag::LuauEagerGeneralization && FFlag::LuauSolverV2)
|
||||||
{
|
{
|
||||||
// FIXME CLI-151985
|
// FIXME CLI-151985
|
||||||
LUAU_CHECK_ERROR_COUNT(2, result);
|
LUAU_CHECK_ERROR_COUNT(2, result);
|
||||||
|
@ -1981,10 +1975,15 @@ TEST_CASE_FIXTURE(Fixture, "dont_infer_parameter_types_for_functions_from_their_
|
||||||
|
|
||||||
CHECK_EQ("<a>(a) -> a", toString(requireType("f")));
|
CHECK_EQ("<a>(a) -> a", toString(requireType("f")));
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2)
|
if (FFlag::LuauEagerGeneralization && FFlag::LuauSolverV2)
|
||||||
|
{
|
||||||
|
LUAU_CHECK_NO_ERRORS(result);
|
||||||
|
CHECK("<a>({ read p: { read q: a } }) -> (a & ~(false?))?" == toString(requireType("g")));
|
||||||
|
}
|
||||||
|
else if (FFlag::LuauSolverV2)
|
||||||
{
|
{
|
||||||
// FIXME CLI-143852: Depends on interleaving generalization and type function reduction.
|
// FIXME CLI-143852: Depends on interleaving generalization and type function reduction.
|
||||||
LUAU_REQUIRE_ERRORS(result);
|
LUAU_CHECK_ERRORS(result);
|
||||||
CHECK_EQ("({ read p: unknown }) -> (*error-type* | ~(false?))?", toString(requireType("g")));
|
CHECK_EQ("({ read p: unknown }) -> (*error-type* | ~(false?))?", toString(requireType("g")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2941,7 +2940,7 @@ TEST_CASE_FIXTURE(Fixture, "unifier_should_not_bind_free_types")
|
||||||
{
|
{
|
||||||
// The new solver should ideally be able to do better here, but this is no worse than the old solver.
|
// The new solver should ideally be able to do better here, but this is no worse than the old solver.
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
LUAU_REQUIRE_ERROR_COUNT(2, result);
|
LUAU_REQUIRE_ERROR_COUNT(2, result);
|
||||||
auto tm1 = get<TypeMismatch>(result.errors[0]);
|
auto tm1 = get<TypeMismatch>(result.errors[0]);
|
||||||
|
|
|
@ -334,9 +334,6 @@ TEST_CASE_FIXTURE(Fixture, "table_intersection_write_sealed")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "table_intersection_write_sealed_indirect")
|
TEST_CASE_FIXTURE(Fixture, "table_intersection_write_sealed_indirect")
|
||||||
{
|
{
|
||||||
// CLI-116476 Subtyping between type alias and an equivalent but not named type isn't working.
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
type X = { x: (number) -> number }
|
type X = { x: (number) -> number }
|
||||||
type Y = { y: (string) -> string }
|
type Y = { y: (string) -> string }
|
||||||
|
|
|
@ -325,9 +325,6 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_on_error")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "for_in_loop_on_non_function")
|
TEST_CASE_FIXTURE(Fixture, "for_in_loop_on_non_function")
|
||||||
{
|
{
|
||||||
// We report a spuriouus duplicate error here.
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local bad_iter = 5
|
local bad_iter = 5
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
||||||
LUAU_FASTFLAG(LuauClipVariadicAnysFromArgsToGenericFuncs2)
|
LUAU_FASTFLAG(LuauClipVariadicAnysFromArgsToGenericFuncs2)
|
||||||
|
|
||||||
|
@ -787,7 +787,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "leaky_generics")
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
CHECK_EQ("(unknown) -> unknown", toString(requireTypeAtPosition({13, 23})));
|
CHECK_EQ("(unknown) -> unknown", toString(requireTypeAtPosition({13, 23})));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("TypeInferOperators");
|
TEST_SUITE_BEGIN("TypeInferOperators");
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ TEST_CASE_FIXTURE(Fixture, "or_joins_types")
|
||||||
)");
|
)");
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// FIXME: Regression
|
// FIXME: Regression
|
||||||
CHECK("(string & ~(false?)) | number" == toString(*requireType("s")));
|
CHECK("(string & ~(false?)) | number" == toString(*requireType("s")));
|
||||||
|
@ -51,7 +51,7 @@ TEST_CASE_FIXTURE(Fixture, "or_joins_types_with_no_extras")
|
||||||
)");
|
)");
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// FIXME: Regression.
|
// FIXME: Regression.
|
||||||
CHECK("(string & ~(false?)) | number" == toString(*requireType("s")));
|
CHECK("(string & ~(false?)) | number" == toString(*requireType("s")));
|
||||||
|
@ -72,7 +72,7 @@ TEST_CASE_FIXTURE(Fixture, "or_joins_types_with_no_superfluous_union")
|
||||||
)");
|
)");
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
// FIXME: Regression
|
// FIXME: Regression
|
||||||
CHECK("(string & ~(false?)) | string" == toString(requireType("s")));
|
CHECK("(string & ~(false?)) | string" == toString(requireType("s")));
|
||||||
|
@ -634,7 +634,20 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "typecheck_unary_minus_error")
|
||||||
local a = -foo
|
local a = -foo
|
||||||
)");
|
)");
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2)
|
if (FFlag::LuauEagerGeneralization && FFlag::LuauSolverV2)
|
||||||
|
{
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
|
|
||||||
|
CHECK("string" == toString(requireType("a")));
|
||||||
|
|
||||||
|
TypeMismatch* tm = get<TypeMismatch>(result.errors[0]);
|
||||||
|
REQUIRE(tm);
|
||||||
|
|
||||||
|
// FIXME: This error is a bit weird.
|
||||||
|
CHECK("({ @metatable { __unm: (boolean) -> string }, { value: number } }) -> string" == toString(tm->wantedType, {true}));
|
||||||
|
CHECK("(boolean) -> string" == toString(tm->givenType));
|
||||||
|
}
|
||||||
|
else if (FFlag::LuauSolverV2)
|
||||||
{
|
{
|
||||||
LUAU_REQUIRE_ERROR_COUNT(2, result);
|
LUAU_REQUIRE_ERROR_COUNT(2, result);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
||||||
|
LUAU_FASTFLAG(LuauStoreCSTData2)
|
||||||
LUAU_FASTINT(LuauNormalizeCacheLimit)
|
LUAU_FASTINT(LuauNormalizeCacheLimit)
|
||||||
LUAU_FASTINT(LuauTarjanChildLimit)
|
LUAU_FASTINT(LuauTarjanChildLimit)
|
||||||
LUAU_FASTINT(LuauTypeInferIterationLimit)
|
LUAU_FASTINT(LuauTypeInferIterationLimit)
|
||||||
|
@ -48,7 +49,7 @@ TEST_CASE_FIXTURE(Fixture, "typeguard_inference_incomplete")
|
||||||
end
|
end
|
||||||
)";
|
)";
|
||||||
|
|
||||||
const std::string expected = R"(
|
const std::string expected = FFlag::LuauStoreCSTData2 ? R"(
|
||||||
function f(a:{fn:()->(a,b...)}): ()
|
function f(a:{fn:()->(a,b...)}): ()
|
||||||
if type(a) == 'boolean' then
|
if type(a) == 'boolean' then
|
||||||
local a1:boolean=a
|
local a1:boolean=a
|
||||||
|
@ -56,9 +57,18 @@ TEST_CASE_FIXTURE(Fixture, "typeguard_inference_incomplete")
|
||||||
local a2:{fn:()->(a,b...)}=a
|
local a2:{fn:()->(a,b...)}=a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
)"
|
||||||
|
: R"(
|
||||||
|
function f(a:{fn:()->(a,b...)}): ()
|
||||||
|
if type(a) == 'boolean'then
|
||||||
|
local a1:boolean=a
|
||||||
|
elseif a.fn()then
|
||||||
|
local a2:{fn:()->(a,b...)}=a
|
||||||
|
end
|
||||||
|
end
|
||||||
)";
|
)";
|
||||||
|
|
||||||
const std::string expectedWithNewSolver = R"(
|
const std::string expectedWithNewSolver = FFlag::LuauStoreCSTData2 ? R"(
|
||||||
function f(a:{fn:()->(unknown,...unknown)}): ()
|
function f(a:{fn:()->(unknown,...unknown)}): ()
|
||||||
if type(a) == 'boolean' then
|
if type(a) == 'boolean' then
|
||||||
local a1:{fn:()->(unknown,...unknown)}&boolean=a
|
local a1:{fn:()->(unknown,...unknown)}&boolean=a
|
||||||
|
@ -66,9 +76,18 @@ TEST_CASE_FIXTURE(Fixture, "typeguard_inference_incomplete")
|
||||||
local a2:{fn:()->(unknown,...unknown)}&(class|function|nil|number|string|thread|buffer|table)=a
|
local a2:{fn:()->(unknown,...unknown)}&(class|function|nil|number|string|thread|buffer|table)=a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
)"
|
||||||
|
: R"(
|
||||||
|
function f(a:{fn:()->(unknown,...unknown)}): ()
|
||||||
|
if type(a) == 'boolean'then
|
||||||
|
local a1:{fn:()->(unknown,...unknown)}&boolean=a
|
||||||
|
elseif a.fn()then
|
||||||
|
local a2:{fn:()->(unknown,...unknown)}&(class|function|nil|number|string|thread|buffer|table)=a
|
||||||
|
end
|
||||||
|
end
|
||||||
)";
|
)";
|
||||||
|
|
||||||
const std::string expectedWithEqSat = R"(
|
const std::string expectedWithEqSat = FFlag::LuauStoreCSTData2 ? R"(
|
||||||
function f(a:{fn:()->(unknown,...unknown)}): ()
|
function f(a:{fn:()->(unknown,...unknown)}): ()
|
||||||
if type(a) == 'boolean' then
|
if type(a) == 'boolean' then
|
||||||
local a1:{fn:()->(unknown,...unknown)}&boolean=a
|
local a1:{fn:()->(unknown,...unknown)}&boolean=a
|
||||||
|
@ -76,6 +95,15 @@ TEST_CASE_FIXTURE(Fixture, "typeguard_inference_incomplete")
|
||||||
local a2:{fn:()->(unknown,...unknown)}&negate<boolean>=a
|
local a2:{fn:()->(unknown,...unknown)}&negate<boolean>=a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
)"
|
||||||
|
: R"(
|
||||||
|
function f(a:{fn:()->(unknown,...unknown)}): ()
|
||||||
|
if type(a) == 'boolean'then
|
||||||
|
local a1:{fn:()->(unknown,...unknown)}&boolean=a
|
||||||
|
elseif a.fn()then
|
||||||
|
local a2:{fn:()->(unknown,...unknown)}&negate<boolean>=a
|
||||||
|
end
|
||||||
|
end
|
||||||
)";
|
)";
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2 && !FFlag::DebugLuauEqSatSimplification)
|
if (FFlag::LuauSolverV2 && !FFlag::DebugLuauEqSatSimplification)
|
||||||
|
|
|
@ -10,11 +10,13 @@
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
LUAU_FASTFLAG(DebugLuauEqSatSimplification)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauFunctionCallsAreNotNilable)
|
LUAU_FASTFLAG(LuauFunctionCallsAreNotNilable)
|
||||||
LUAU_FASTFLAG(LuauWeakNilRefinementType)
|
LUAU_FASTFLAG(LuauWeakNilRefinementType)
|
||||||
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
LUAU_FASTFLAG(LuauAddCallConstraintForIterableFunctions)
|
||||||
LUAU_FASTFLAG(LuauSimplificationTableExternType)
|
LUAU_FASTFLAG(LuauSimplificationTableExternType)
|
||||||
|
LUAU_FASTFLAG(LuauBetterCannotCallFunctionPrimitive)
|
||||||
|
LUAU_FASTFLAG(LuauTypeCheckerStricterIndexCheck)
|
||||||
LUAU_FASTFLAG(LuauAvoidDoubleNegation)
|
LUAU_FASTFLAG(LuauAvoidDoubleNegation)
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
@ -108,6 +110,13 @@ struct RefinementExternTypeFixture : BuiltinsFixture
|
||||||
{"IsA", Property{isA}},
|
{"IsA", Property{isA}},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TypeId scriptConnection = arena.addType(ExternType("ExternScriptConnection", {}, inst, std::nullopt, {}, nullptr, "Test", {}));
|
||||||
|
TypePackId disconnectArgs = arena.addTypePack({scriptConnection});
|
||||||
|
TypeId disconnect = arena.addType(FunctionType{disconnectArgs, builtinTypes->emptyTypePack});
|
||||||
|
getMutable<ExternType>(scriptConnection)->props = {
|
||||||
|
{"Disconnect", Property{disconnect}},
|
||||||
|
};
|
||||||
|
|
||||||
TypeId folder = frontend.globals.globalTypes.addType(ExternType{"Folder", {}, inst, std::nullopt, {}, nullptr, "Test", {}});
|
TypeId folder = frontend.globals.globalTypes.addType(ExternType{"Folder", {}, inst, std::nullopt, {}, nullptr, "Test", {}});
|
||||||
TypeId part = frontend.globals.globalTypes.addType(ExternType{"Part", {}, inst, std::nullopt, {}, nullptr, "Test", {}});
|
TypeId part = frontend.globals.globalTypes.addType(ExternType{"Part", {}, inst, std::nullopt, {}, nullptr, "Test", {}});
|
||||||
getMutable<ExternType>(part)->props = {
|
getMutable<ExternType>(part)->props = {
|
||||||
|
@ -123,6 +132,7 @@ struct RefinementExternTypeFixture : BuiltinsFixture
|
||||||
|
|
||||||
frontend.globals.globalScope->exportedTypeBindings["Vector3"] = TypeFun{{}, vec3};
|
frontend.globals.globalScope->exportedTypeBindings["Vector3"] = TypeFun{{}, vec3};
|
||||||
frontend.globals.globalScope->exportedTypeBindings["Instance"] = TypeFun{{}, inst};
|
frontend.globals.globalScope->exportedTypeBindings["Instance"] = TypeFun{{}, inst};
|
||||||
|
frontend.globals.globalScope->exportedTypeBindings["ExternScriptConnection"] = TypeFun{{}, scriptConnection};
|
||||||
frontend.globals.globalScope->exportedTypeBindings["Folder"] = TypeFun{{}, folder};
|
frontend.globals.globalScope->exportedTypeBindings["Folder"] = TypeFun{{}, folder};
|
||||||
frontend.globals.globalScope->exportedTypeBindings["Part"] = TypeFun{{}, part};
|
frontend.globals.globalScope->exportedTypeBindings["Part"] = TypeFun{{}, part};
|
||||||
frontend.globals.globalScope->exportedTypeBindings["WeldConstraint"] = TypeFun{{}, weldConstraint};
|
frontend.globals.globalScope->exportedTypeBindings["WeldConstraint"] = TypeFun{{}, weldConstraint};
|
||||||
|
@ -760,7 +770,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "nonoptional_type_can_narrow_to_nil_if_sense_
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
CHECK("nil & string & unknown & unknown" == toString(requireTypeAtPosition({4, 24}))); // type(v) == "nil"
|
CHECK("nil & string & unknown & unknown" == toString(requireTypeAtPosition({4, 24}))); // type(v) == "nil"
|
||||||
CHECK("string & unknown & unknown & ~nil" == toString(requireTypeAtPosition({6, 24}))); // type(v) ~= "nil"
|
CHECK("string & unknown & unknown & ~nil" == toString(requireTypeAtPosition({6, 24}))); // type(v) ~= "nil"
|
||||||
|
@ -2504,7 +2514,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "remove_recursive_upper_bound_when_generalizi
|
||||||
end
|
end
|
||||||
)"));
|
)"));
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
CHECK_EQ("nil & string & unknown", toString(requireTypeAtPosition({4, 24})));
|
CHECK_EQ("nil & string & unknown", toString(requireTypeAtPosition({4, 24})));
|
||||||
else
|
else
|
||||||
CHECK_EQ("nil", toString(requireTypeAtPosition({4, 24})));
|
CHECK_EQ("nil", toString(requireTypeAtPosition({4, 24})));
|
||||||
|
@ -2648,5 +2658,77 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "oss_1451")
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(RefinementExternTypeFixture, "cannot_call_a_function")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
type Disconnectable = {
|
||||||
|
Disconnect: (self: Disconnectable) -> (...any);
|
||||||
|
} | {
|
||||||
|
disconnect: (self: Disconnectable) -> (...any)
|
||||||
|
} | ExternScriptConnection
|
||||||
|
|
||||||
|
local x: Disconnectable = workspace.ChildAdded:Connect(function()
|
||||||
|
print("child added")
|
||||||
|
end)
|
||||||
|
|
||||||
|
if type(x.Disconnect) == "function" then
|
||||||
|
x:Disconnect()
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
if (FFlag::LuauTypeCheckerStricterIndexCheck)
|
||||||
|
{
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(2, result);
|
||||||
|
|
||||||
|
CHECK_EQ(toString(result.errors[0]), "Key 'Disconnect' is missing from 't2 where t1 = ExternScriptConnection | t2 | { Disconnect: (t1) -> (...any) } ; t2 = { disconnect: (t1) -> (...any) }' in the type 't1 where t1 = ExternScriptConnection | { Disconnect: (t1) -> (...any) } | { disconnect: (t1) -> (...any) }'");
|
||||||
|
|
||||||
|
if (FFlag::LuauBetterCannotCallFunctionPrimitive)
|
||||||
|
CHECK_EQ(toString(result.errors[1]), "The type function is not precise enough for us to determine the appropriate result type of this call.");
|
||||||
|
else
|
||||||
|
CHECK_EQ(toString(result.errors[1]), "Cannot call a value of type function");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
|
|
||||||
|
if (FFlag::LuauBetterCannotCallFunctionPrimitive)
|
||||||
|
CHECK_EQ(toString(result.errors[0]), "The type function is not precise enough for us to determine the appropriate result type of this call.");
|
||||||
|
else
|
||||||
|
CHECK_EQ(toString(result.errors[0]), "Cannot call a value of type function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(BuiltinsFixture, "oss_1835")
|
||||||
|
{
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||||
|
--!strict
|
||||||
|
local t: {name: string}? = nil
|
||||||
|
|
||||||
|
function f()
|
||||||
|
local name = if t then t.name else "name"
|
||||||
|
end
|
||||||
|
)"));
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(check(R"(
|
||||||
|
--!strict
|
||||||
|
local t: {name: string}? = nil
|
||||||
|
|
||||||
|
function f()
|
||||||
|
if t then end
|
||||||
|
local name = if t then t.name else "name"
|
||||||
|
end
|
||||||
|
)"));
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
local t: {name: string}? = nil
|
||||||
|
if t then end
|
||||||
|
print(t.name)
|
||||||
|
local name = if t then t.name else "name"
|
||||||
|
)");
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
|
CHECK(get<OptionalValueAccess>(result.errors[0]));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
|
|
@ -21,8 +21,8 @@ LUAU_FASTFLAG(LuauSolverV2)
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||||
LUAU_FASTFLAG(LuauFixIndexerSubtypingOrdering)
|
LUAU_FASTFLAG(LuauFixIndexerSubtypingOrdering)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(DebugLuauAssertOnForcedConstraint)
|
LUAU_FASTFLAG(DebugLuauAssertOnForcedConstraint)
|
||||||
LUAU_FASTFLAG(LuauBidirectionalInferenceElideAssert)
|
LUAU_FASTFLAG(LuauBidirectionalInferenceElideAssert)
|
||||||
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
||||||
|
@ -30,6 +30,11 @@ LUAU_FASTFLAG(LuauTypeCheckerStricterIndexCheck)
|
||||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
LUAU_FASTFLAG(LuauEnableWriteOnlyProperties)
|
||||||
|
LUAU_FASTFLAG(LuauDisablePrimitiveInferenceInLargeTables)
|
||||||
|
LUAU_FASTINT(LuauPrimitiveInferenceInTableLimit)
|
||||||
|
LUAU_FASTFLAG(LuauSubtypeGenericsAndNegations)
|
||||||
|
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("TableTests");
|
TEST_SUITE_BEGIN("TableTests");
|
||||||
|
|
||||||
|
@ -594,9 +599,6 @@ TEST_CASE_FIXTURE(Fixture, "okay_to_add_property_to_unsealed_tables_by_assignmen
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "okay_to_add_property_to_unsealed_tables_by_function_call")
|
TEST_CASE_FIXTURE(Fixture, "okay_to_add_property_to_unsealed_tables_by_function_call")
|
||||||
{
|
{
|
||||||
// CLI-114873
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!strict
|
--!strict
|
||||||
function get(x) return x.opts["MYOPT"] end
|
function get(x) return x.opts["MYOPT"] end
|
||||||
|
@ -700,7 +702,7 @@ TEST_CASE_FIXTURE(Fixture, "indexers_get_quantified_too")
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2 && FFlag::LuauNonReentrantGeneralization3)
|
if (FFlag::LuauSolverV2 && FFlag::LuauEagerGeneralization)
|
||||||
CHECK("<a>({a}) -> ()" == toString(requireType("swap")));
|
CHECK("<a>({a}) -> ()" == toString(requireType("swap")));
|
||||||
else if (FFlag::LuauSolverV2)
|
else if (FFlag::LuauSolverV2)
|
||||||
CHECK("({unknown}) -> ()" == toString(requireType("swap")));
|
CHECK("({unknown}) -> ()" == toString(requireType("swap")));
|
||||||
|
@ -1153,8 +1155,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "meta_add_inferred")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "meta_add_both_ways")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "meta_add_both_ways")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
type VectorMt = { __add: (Vector, number) -> Vector }
|
type VectorMt = { __add: (Vector, number) -> Vector }
|
||||||
local vectorMt: VectorMt
|
local vectorMt: VectorMt
|
||||||
|
@ -2210,7 +2210,6 @@ local Test: {Table} = {
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "common_table_element_general")
|
TEST_CASE_FIXTURE(Fixture, "common_table_element_general")
|
||||||
{
|
{
|
||||||
// CLI-115275 - Bidirectional inference does not always propagate indexer types into the expression
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
|
@ -2380,7 +2379,7 @@ TEST_CASE_FIXTURE(Fixture, "invariant_table_properties_means_instantiating_table
|
||||||
local c : string = t.m("hi")
|
local c : string = t.m("hi")
|
||||||
)");
|
)");
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization && FFlag::LuauSolverV2)
|
if (FFlag::LuauEagerGeneralization && FFlag::LuauSolverV2)
|
||||||
{
|
{
|
||||||
// FIXME CLI-151985
|
// FIXME CLI-151985
|
||||||
LUAU_CHECK_ERROR_COUNT(2, result);
|
LUAU_CHECK_ERROR_COUNT(2, result);
|
||||||
|
@ -2651,7 +2650,6 @@ Type 'number' could not be converted into 'string' in an invariant context)";
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "explicitly_typed_table")
|
TEST_CASE_FIXTURE(Fixture, "explicitly_typed_table")
|
||||||
{
|
{
|
||||||
// Table properties like HasSuper.p must be invariant. The new solver rightly rejects this program.
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
|
@ -2702,9 +2700,6 @@ Table type '{ x: number, y: number }' not compatible with type 'Super' because t
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "explicitly_typed_table_with_indexer")
|
TEST_CASE_FIXTURE(Fixture, "explicitly_typed_table_with_indexer")
|
||||||
{
|
{
|
||||||
// CLI-114791 Bidirectional inference should be able to cause the inference engine to forget that a table literal has some property
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
--!strict
|
--!strict
|
||||||
type Super = { x : number }
|
type Super = { x : number }
|
||||||
|
@ -3752,7 +3747,12 @@ TEST_CASE_FIXTURE(Fixture, "scalar_is_a_subtype_of_a_compatible_polymorphic_shap
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "scalar_is_not_a_subtype_of_a_compatible_polymorphic_shape_type")
|
TEST_CASE_FIXTURE(Fixture, "scalar_is_not_a_subtype_of_a_compatible_polymorphic_shape_type")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {{FFlag::LuauNonReentrantGeneralization3, true}, {FFlag::LuauReportSubtypingErrors, true}};
|
ScopedFastFlag sff[] = {
|
||||||
|
{FFlag::LuauReportSubtypingErrors, true},
|
||||||
|
{FFlag::LuauEagerGeneralization, true},
|
||||||
|
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
||||||
|
{FFlag::LuauNoMoreInjectiveTypeFunctions, true}
|
||||||
|
};
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local function f(s)
|
local function f(s)
|
||||||
|
@ -4412,7 +4412,7 @@ TEST_CASE_FIXTURE(Fixture, "read_and_write_only_table_properties_are_unsupported
|
||||||
CHECK(Location{{5, 18}, {5, 23}} == result.errors[3].location);
|
CHECK(Location{{5, 18}, {5, 23}} == result.errors[3].location);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "read_ond_write_only_indexers_are_unsupported")
|
TEST_CASE_FIXTURE(Fixture, "read_and_write_only_indexers_are_unsupported")
|
||||||
{
|
{
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
type T = {read [string]: number}
|
type T = {read [string]: number}
|
||||||
|
@ -4442,6 +4442,22 @@ TEST_CASE_FIXTURE(Fixture, "infer_write_property")
|
||||||
CHECK("({ y: number }) -> ()" == toString(requireType("f")));
|
CHECK("({ y: number }) -> ()" == toString(requireType("f")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "new_solver_supports_read_write_properties")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
||||||
|
ScopedFastFlag sff2{FFlag::LuauEnableWriteOnlyProperties, true};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
type W = {read x: number}
|
||||||
|
type X = {write x: boolean}
|
||||||
|
|
||||||
|
type Y = {read ["prop"]: boolean}
|
||||||
|
type Z = {write ["prop"]: string}
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "table_subtyping_error_suppression")
|
TEST_CASE_FIXTURE(Fixture, "table_subtyping_error_suppression")
|
||||||
{
|
{
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
|
@ -4495,6 +4511,59 @@ TEST_CASE_FIXTURE(Fixture, "write_to_read_only_property")
|
||||||
CHECK(PropertyAccessViolation::CannotWrite == pav->context);
|
CHECK(PropertyAccessViolation::CannotWrite == pav->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "write_to_write_only_property")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
||||||
|
ScopedFastFlag writeOnly{FFlag::LuauEnableWriteOnlyProperties, true};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
function f(t: {write x: number})
|
||||||
|
t.x = 5
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "bidirectional_typechecking_with_write_only_property")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
||||||
|
ScopedFastFlag writeOnly{FFlag::LuauEnableWriteOnlyProperties, true};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
function f(t: {write x: number})
|
||||||
|
t.x = 5
|
||||||
|
end
|
||||||
|
|
||||||
|
f({ x = 2 })
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "read_from_write_only_property")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
||||||
|
ScopedFastFlag writeOnly{FFlag::LuauEnableWriteOnlyProperties, true};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
function f(t: {write x: number})
|
||||||
|
local foo = t.x
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
|
|
||||||
|
CHECK("Property x of table '{ write x: number }' is write-only" == toString(result.errors[0]));
|
||||||
|
|
||||||
|
PropertyAccessViolation* pav = get<PropertyAccessViolation>(result.errors[0]);
|
||||||
|
REQUIRE(pav);
|
||||||
|
|
||||||
|
CHECK("{ write x: number }" == toString(pav->table, {true}));
|
||||||
|
CHECK("x" == pav->key);
|
||||||
|
CHECK(PropertyAccessViolation::CannotRead == pav->context);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "write_to_unusually_named_read_only_property")
|
TEST_CASE_FIXTURE(Fixture, "write_to_unusually_named_read_only_property")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
||||||
|
@ -4510,7 +4579,7 @@ TEST_CASE_FIXTURE(Fixture, "write_to_unusually_named_read_only_property")
|
||||||
CHECK("Property \"hello world\" of table '{ read [\"hello world\"]: number }' is read-only" == toString(result.errors[0]));
|
CHECK("Property \"hello world\" of table '{ read [\"hello world\"]: number }' is read-only" == toString(result.errors[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "write_annotations_are_unsupported_even_with_the_new_solver")
|
TEST_CASE_FIXTURE(Fixture, "write_annotations_are_supported_with_the_new_solver")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
ScopedFastFlag sff{FFlag::LuauSolverV2, true};
|
||||||
|
|
||||||
|
@ -4519,10 +4588,15 @@ TEST_CASE_FIXTURE(Fixture, "write_annotations_are_unsupported_even_with_the_new_
|
||||||
end
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
|
if (FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
else
|
||||||
|
{
|
||||||
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
|
|
||||||
CHECK("write keyword is illegal here" == toString(result.errors[0]));
|
CHECK("write keyword is illegal here" == toString(result.errors[0]));
|
||||||
CHECK(Location{{1, 23}, {1, 28}} == result.errors[0].location);
|
CHECK(Location{{1, 23}, {1, 28}} == result.errors[0].location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "read_and_write_only_table_properties_are_unsupported")
|
TEST_CASE_FIXTURE(Fixture, "read_and_write_only_table_properties_are_unsupported")
|
||||||
|
@ -4549,10 +4623,8 @@ TEST_CASE_FIXTURE(Fixture, "read_and_write_only_table_properties_are_unsupported
|
||||||
CHECK(Location{{5, 18}, {5, 23}} == result.errors[3].location);
|
CHECK(Location{{5, 18}, {5, 23}} == result.errors[3].location);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "read_ond_write_only_indexers_are_unsupported")
|
TEST_CASE_FIXTURE(Fixture, "read_and_write_only_indexers_are_unsupported")
|
||||||
{
|
{
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
type T = {read [string]: number}
|
type T = {read [string]: number}
|
||||||
type U = {write [string]: boolean}
|
type U = {write [string]: boolean}
|
||||||
|
@ -4571,7 +4643,11 @@ TEST_CASE_FIXTURE(Fixture, "table_writes_introduce_write_properties")
|
||||||
if (!FFlag::LuauSolverV2)
|
if (!FFlag::LuauSolverV2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ScopedFastFlag sff[] = {{FFlag::LuauNonReentrantGeneralization3, true}};
|
ScopedFastFlag sff[] = {
|
||||||
|
{FFlag::LuauEagerGeneralization, true},
|
||||||
|
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
||||||
|
{FFlag::LuauNoMoreInjectiveTypeFunctions, true}
|
||||||
|
};
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
function oc(player, speaker)
|
function oc(player, speaker)
|
||||||
|
@ -4622,7 +4698,7 @@ TEST_CASE_FIXTURE(Fixture, "refined_thing_can_be_an_array")
|
||||||
end
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
if (FFlag::LuauSolverV2 && !FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauSolverV2 && !FFlag::LuauEagerGeneralization)
|
||||||
{
|
{
|
||||||
LUAU_CHECK_ERROR_COUNT(1, result);
|
LUAU_CHECK_ERROR_COUNT(1, result);
|
||||||
LUAU_CHECK_ERROR(result, NotATable);
|
LUAU_CHECK_ERROR(result, NotATable);
|
||||||
|
@ -4670,7 +4746,7 @@ TEST_CASE_FIXTURE(Fixture, "parameter_was_set_an_indexer_and_bounded_by_another_
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
// FIXME CLI-114134. We need to simplify types more consistently.
|
// FIXME CLI-114134. We need to simplify types more consistently.
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
CHECK("({number} & {number}, unknown) -> ()" == toString(requireType("f")));
|
CHECK("({number} & {number}, unknown) -> ()" == toString(requireType("f")));
|
||||||
else
|
else
|
||||||
CHECK_EQ("(unknown & {number} & {number}, unknown) -> ()", toString(requireType("f")));
|
CHECK_EQ("(unknown & {number} & {number}, unknown) -> ()", toString(requireType("f")));
|
||||||
|
@ -5212,8 +5288,13 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "write_only_table_field_duplicate")
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
|
||||||
LUAU_CHECK_ERROR_COUNT(1, result);
|
if (FFlag::LuauEnableWriteOnlyProperties)
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
CHECK_EQ("write keyword is illegal here", toString(result.errors[0]));
|
CHECK_EQ("write keyword is illegal here", toString(result.errors[0]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "table_freeze_musnt_assert")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "table_freeze_musnt_assert")
|
||||||
|
@ -5661,5 +5742,81 @@ TEST_CASE_FIXTURE(Fixture, "narrow_table_literal_check_assignment")
|
||||||
CHECK_EQ("boolean", toString(tm->wantedType));
|
CHECK_EQ("boolean", toString(tm->wantedType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "disable_singleton_inference_on_large_tables")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauSolverV2, true},
|
||||||
|
{FFlag::LuauTableLiteralSubtypeSpecificCheck, true},
|
||||||
|
{FFlag::LuauDisablePrimitiveInferenceInLargeTables, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
ScopedFastInt _{FInt::LuauPrimitiveInferenceInTableLimit, 2};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
type Word = "foo" | "bar"
|
||||||
|
local words: { Word } = { "foo", "bar", "foo" }
|
||||||
|
)");
|
||||||
|
// We expect this to have errors now, as we've set the limit for inference
|
||||||
|
// in tables so low.
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "disable_singleton_inference_on_large_nested_tables")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauSolverV2, true},
|
||||||
|
{FFlag::LuauTableLiteralSubtypeSpecificCheck, true},
|
||||||
|
{FFlag::LuauDisablePrimitiveInferenceInLargeTables, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
ScopedFastInt _{FInt::LuauPrimitiveInferenceInTableLimit, 2};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
type Word = "foo" | "bar"
|
||||||
|
local words: {{ Word }} = {{ "foo", "bar", "foo" }}
|
||||||
|
)");
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "large_table_inference_does_not_bleed")
|
||||||
|
{
|
||||||
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauSolverV2, true},
|
||||||
|
{FFlag::LuauTableLiteralSubtypeSpecificCheck, true},
|
||||||
|
{FFlag::LuauDisablePrimitiveInferenceInLargeTables, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
ScopedFastInt _{FInt::LuauPrimitiveInferenceInTableLimit, 2};
|
||||||
|
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
type Word = "foo" | "bar"
|
||||||
|
local words: { Word } = { "foo", "bar", "foo" }
|
||||||
|
local otherWords: { Word } = {"foo"}
|
||||||
|
)");
|
||||||
|
LUAU_REQUIRE_ERROR_COUNT(3, result);
|
||||||
|
for (const auto& err: result.errors)
|
||||||
|
// Check that all of the errors are localized to `words`, not `otherWords`
|
||||||
|
CHECK(err.location.begin.line == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "extremely_large_table" * doctest::timeout(2.0))
|
||||||
|
{
|
||||||
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauSolverV2, true},
|
||||||
|
{FFlag::LuauDisablePrimitiveInferenceInLargeTables, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::string source =
|
||||||
|
"local res = {\n" +
|
||||||
|
rep("\"foo\",\n", 100'000) +
|
||||||
|
"}";
|
||||||
|
LUAU_REQUIRE_NO_ERRORS(check(source));
|
||||||
|
CHECK_EQ("{string}", toString(requireType("res"), {true}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
|
|
@ -28,7 +28,7 @@ LUAU_FASTFLAG(LuauTypeCheckerAcceptNumberConcats)
|
||||||
LUAU_FASTFLAG(LuauPreprocessTypestatedArgument)
|
LUAU_FASTFLAG(LuauPreprocessTypestatedArgument)
|
||||||
LUAU_FASTFLAG(LuauMagicFreezeCheckBlocked2)
|
LUAU_FASTFLAG(LuauMagicFreezeCheckBlocked2)
|
||||||
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions)
|
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
LUAU_FASTFLAG(LuauOptimizeFalsyAndTruthyIntersect)
|
||||||
LUAU_FASTFLAG(LuauHasPropProperBlock)
|
LUAU_FASTFLAG(LuauHasPropProperBlock)
|
||||||
LUAU_FASTFLAG(LuauStringPartLengthLimit)
|
LUAU_FASTFLAG(LuauStringPartLengthLimit)
|
||||||
|
@ -37,6 +37,8 @@ LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||||
LUAU_FASTFLAG(LuauAvoidDoubleNegation)
|
LUAU_FASTFLAG(LuauAvoidDoubleNegation)
|
||||||
LUAU_FASTFLAG(LuauInsertErrorTypesIntoIndexerResult)
|
LUAU_FASTFLAG(LuauInsertErrorTypesIntoIndexerResult)
|
||||||
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
LUAU_FASTFLAG(LuauSimplifyOutOfLine)
|
||||||
|
LUAU_FASTFLAG(LuauSubtypeGenericsAndNegations)
|
||||||
|
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions)
|
||||||
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
@ -445,7 +447,7 @@ TEST_CASE_FIXTURE(Fixture, "check_expr_recursion_limit")
|
||||||
#endif
|
#endif
|
||||||
ScopedFastInt luauRecursionLimit{FInt::LuauRecursionLimit, limit + 100};
|
ScopedFastInt luauRecursionLimit{FInt::LuauRecursionLimit, limit + 100};
|
||||||
ScopedFastInt luauCheckRecursionLimit{FInt::LuauCheckRecursionLimit, limit - 100};
|
ScopedFastInt luauCheckRecursionLimit{FInt::LuauCheckRecursionLimit, limit - 100};
|
||||||
ScopedFastFlag _{FFlag::LuauNonReentrantGeneralization3, false};
|
ScopedFastFlag _{FFlag::LuauEagerGeneralization, false};
|
||||||
|
|
||||||
CheckResult result = check(R"(("foo"))" + rep(":lower()", limit));
|
CheckResult result = check(R"(("foo"))" + rep(":lower()", limit));
|
||||||
|
|
||||||
|
@ -1258,9 +1260,6 @@ TEST_CASE_FIXTURE(Fixture, "type_infer_cache_limit_normalizer")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "follow_on_new_types_in_substitution")
|
TEST_CASE_FIXTURE(Fixture, "follow_on_new_types_in_substitution")
|
||||||
{
|
{
|
||||||
// CLI-114134
|
|
||||||
DOES_NOT_PASS_NEW_SOLVER_GUARD();
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local obj = {}
|
local obj = {}
|
||||||
|
|
||||||
|
@ -2042,8 +2041,10 @@ TEST_CASE_FIXTURE(Fixture, "fuzz_generalize_one_remove_type_assert")
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag sffs[] = {
|
||||||
{FFlag::LuauSolverV2, true},
|
{FFlag::LuauSolverV2, true},
|
||||||
{FFlag::LuauHasPropProperBlock, true},
|
{FFlag::LuauHasPropProperBlock, true},
|
||||||
{FFlag::LuauNonReentrantGeneralization3, true},
|
{FFlag::LuauEagerGeneralization, true},
|
||||||
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true}
|
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
||||||
|
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
||||||
|
{FFlag::LuauNoMoreInjectiveTypeFunctions, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
auto result = check(R"(
|
auto result = check(R"(
|
||||||
|
@ -2078,8 +2079,10 @@ TEST_CASE_FIXTURE(Fixture, "fuzz_generalize_one_remove_type_assert_2")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag sffs[] = {
|
||||||
{FFlag::LuauSolverV2, true},
|
{FFlag::LuauSolverV2, true},
|
||||||
{FFlag::LuauNonReentrantGeneralization3, true},
|
{FFlag::LuauEagerGeneralization, true},
|
||||||
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
||||||
|
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
||||||
|
{FFlag::LuauNoMoreInjectiveTypeFunctions, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
|
@ -2106,15 +2109,19 @@ TEST_CASE_FIXTURE(Fixture, "fuzz_generalize_one_remove_type_assert_2")
|
||||||
LUAU_REQUIRE_NO_ERROR(result, ConstraintSolvingIncompleteError);
|
LUAU_REQUIRE_NO_ERROR(result, ConstraintSolvingIncompleteError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_simplify_combinatorial_explosion")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_simplify_combinatorial_explosion")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag sffs[] = {
|
||||||
{FFlag::LuauSolverV2, true},
|
{FFlag::LuauSolverV2, true},
|
||||||
{FFlag::LuauHasPropProperBlock, true},
|
{FFlag::LuauHasPropProperBlock, true},
|
||||||
{FFlag::LuauNonReentrantGeneralization3, true},
|
{FFlag::LuauEagerGeneralization, true},
|
||||||
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
{FFlag::LuauOptimizeFalsyAndTruthyIntersect, true},
|
||||||
{FFlag::LuauStringPartLengthLimit, true},
|
{FFlag::LuauStringPartLengthLimit, true},
|
||||||
{FFlag::LuauSimplificationRecheckAssumption, true},
|
{FFlag::LuauSimplificationRecheckAssumption, true},
|
||||||
|
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
||||||
|
{FFlag::LuauNoMoreInjectiveTypeFunctions, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
LUAU_REQUIRE_ERRORS(check(R"(
|
LUAU_REQUIRE_ERRORS(check(R"(
|
||||||
|
@ -2128,6 +2135,8 @@ local _
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_missing_follow_table_freeze")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzz_missing_follow_table_freeze")
|
||||||
{
|
{
|
||||||
ScopedFastFlag _{FFlag::LuauMagicFreezeCheckBlocked2, true};
|
ScopedFastFlag _{FFlag::LuauMagicFreezeCheckBlocked2, true};
|
||||||
|
|
|
@ -12,10 +12,11 @@ using namespace Luau;
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||||
LUAU_FASTFLAG(LuauTrackInferredFunctionTypeFromCall)
|
LUAU_FASTFLAG(LuauTrackInferredFunctionTypeFromCall)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
LUAU_FASTFLAG(LuauFixEmptyTypePackStringification)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("TypePackTests");
|
TEST_SUITE_BEGIN("TypePackTests");
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ TEST_CASE_FIXTURE(Fixture, "higher_order_function")
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
CHECK_EQ("<a, b..., c...>((c...) -> (b...), (a) -> (c...), a) -> (b...)", toString(requireType("apply")));
|
CHECK_EQ("<a, b..., c...>((c...) -> (b...), (a) -> (c...), a) -> (b...)", toString(requireType("apply")));
|
||||||
else
|
else
|
||||||
CHECK_EQ("<a, b..., c...>((b...) -> (c...), (a) -> (b...), a) -> (c...)", toString(requireType("apply")));
|
CHECK_EQ("<a, b..., c...>((b...) -> (c...), (a) -> (b...), a) -> (c...)", toString(requireType("apply")));
|
||||||
|
@ -339,6 +340,9 @@ local c: Packed<string, number, boolean>
|
||||||
REQUIRE(ttvA->instantiatedTypeParams.size() == 1);
|
REQUIRE(ttvA->instantiatedTypeParams.size() == 1);
|
||||||
REQUIRE(ttvA->instantiatedTypePackParams.size() == 1);
|
REQUIRE(ttvA->instantiatedTypePackParams.size() == 1);
|
||||||
CHECK_EQ(toString(ttvA->instantiatedTypeParams[0], {true}), "number");
|
CHECK_EQ(toString(ttvA->instantiatedTypeParams[0], {true}), "number");
|
||||||
|
if (FFlag::LuauFixEmptyTypePackStringification)
|
||||||
|
CHECK_EQ(toString(ttvA->instantiatedTypePackParams[0], {true}), "()");
|
||||||
|
else
|
||||||
CHECK_EQ(toString(ttvA->instantiatedTypePackParams[0], {true}), "");
|
CHECK_EQ(toString(ttvA->instantiatedTypePackParams[0], {true}), "");
|
||||||
|
|
||||||
auto ttvB = get<TableType>(requireType("b"));
|
auto ttvB = get<TableType>(requireType("b"));
|
||||||
|
|
|
@ -8,11 +8,12 @@ LUAU_FASTFLAG(LuauRefineWaitForBlockedTypesInTarget)
|
||||||
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
LUAU_FASTFLAG(LuauDoNotAddUpvalueTypesToLocalType)
|
||||||
LUAU_FASTFLAG(LuauDfgIfBlocksShouldRespectControlFlow)
|
LUAU_FASTFLAG(LuauDfgIfBlocksShouldRespectControlFlow)
|
||||||
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
LUAU_FASTFLAG(LuauReportSubtypingErrors)
|
||||||
LUAU_FASTFLAG(LuauNonReentrantGeneralization3)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauDfgMatchCGScopes)
|
|
||||||
LUAU_FASTFLAG(LuauPreprocessTypestatedArgument)
|
LUAU_FASTFLAG(LuauPreprocessTypestatedArgument)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
LUAU_FASTFLAG(LuauDfgAllowUpdatesInLoops)
|
||||||
|
LUAU_FASTFLAG(LuauSubtypeGenericsAndNegations)
|
||||||
|
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions)
|
||||||
|
|
||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
|
@ -414,7 +415,13 @@ TEST_CASE_FIXTURE(TypeStateFixture, "prototyped_recursive_functions")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "prototyped_recursive_functions_but_has_future_assignments")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "prototyped_recursive_functions_but_has_future_assignments")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {{FFlag::LuauSolverV2, true}, {FFlag::LuauReportSubtypingErrors, true}, {FFlag::LuauNonReentrantGeneralization3, true}};
|
ScopedFastFlag sffs[] = {
|
||||||
|
{FFlag::LuauSolverV2, true},
|
||||||
|
{FFlag::LuauReportSubtypingErrors, true},
|
||||||
|
{FFlag::LuauEagerGeneralization, true},
|
||||||
|
{FFlag::LuauSubtypeGenericsAndNegations, true},
|
||||||
|
{FFlag::LuauNoMoreInjectiveTypeFunctions, true},
|
||||||
|
};
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local f
|
local f
|
||||||
|
@ -851,24 +858,22 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "assign_in_an_if_branch_without_else")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzzer_table_freeze_in_binary_expr")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzzer_table_freeze_in_binary_expr")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||||
{FFlag::LuauPreprocessTypestatedArgument, true},
|
// CLI-154237: This currently throws an exception due to a mismatch between
|
||||||
{FFlag::LuauDfgMatchCGScopes, true},
|
// the scopes created in the data flow graph versus the constraint generator.
|
||||||
};
|
CHECK_THROWS_AS(
|
||||||
|
check(R"(
|
||||||
// Previously this would ICE due to mismatched scopes between the
|
|
||||||
// constraint generator and the data flow graph.
|
|
||||||
LUAU_REQUIRE_ERRORS(check(R"(
|
|
||||||
local _
|
local _
|
||||||
if _ or table.freeze(_,_) or table.freeze(_,_) then
|
if _ or table.freeze(_,_) or table.freeze(_,_) then
|
||||||
end
|
end
|
||||||
)"));
|
)"),
|
||||||
|
Luau::InternalCompilerError
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "table_freeze_in_conditional")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "table_freeze_in_conditional")
|
||||||
{
|
{
|
||||||
ScopedFastFlag _{FFlag::LuauDfgMatchCGScopes, true};
|
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||||
|
|
||||||
// NOTE: This _probably_ should be disallowed, but it is representing that
|
// NOTE: This _probably_ should be disallowed, but it is representing that
|
||||||
// type stating functions in short circuiting binary expressions do not
|
// type stating functions in short circuiting binary expressions do not
|
||||||
// reflect their type states.
|
// reflect their type states.
|
||||||
|
@ -883,21 +888,19 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "table_freeze_in_conditional")
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzzer_table_freeze_in_conditional_expr")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "fuzzer_table_freeze_in_conditional_expr")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sffs[] = {
|
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||||
{FFlag::LuauPreprocessTypestatedArgument, true},
|
// CLI-154237: This currently throws an exception due to a mismatch between
|
||||||
{FFlag::LuauDfgMatchCGScopes, true},
|
// the scopes created in the data flow graph versus the constraint generator.
|
||||||
};
|
CHECK_THROWS_AS(
|
||||||
|
check(R"(
|
||||||
// Previously this would ICE due to mismatched scopes between the
|
|
||||||
// constraint generator and the data flow graph.
|
|
||||||
LUAU_REQUIRE_ERRORS(check(R"(
|
|
||||||
--!strict
|
|
||||||
local _
|
local _
|
||||||
if
|
if
|
||||||
if table.freeze(_,_) then _ else _
|
if table.freeze(_,_) then _ else _
|
||||||
then
|
then
|
||||||
end
|
end
|
||||||
)"));
|
)"),
|
||||||
|
Luau::InternalCompilerError
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
|
|
|
@ -10,7 +10,7 @@ using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2)
|
LUAU_FASTFLAG(LuauSolverV2)
|
||||||
|
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization)
|
LUAU_FASTFLAG(LuauEagerGeneralization)
|
||||||
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck)
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("UnionTypes");
|
TEST_SUITE_BEGIN("UnionTypes");
|
||||||
|
@ -902,7 +902,7 @@ TEST_CASE_FIXTURE(Fixture, "less_greedy_unification_with_union_types")
|
||||||
|
|
||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
|
|
||||||
if (FFlag::DebugLuauGreedyGeneralization)
|
if (FFlag::LuauEagerGeneralization)
|
||||||
CHECK_EQ(
|
CHECK_EQ(
|
||||||
"<a>(({ read x: a } & { x: number }) | ({ read x: a } & { x: string })) -> { x: number } | { x: string }", toString(requireType("f"))
|
"<a>(({ read x: a } & { x: number }) | ({ read x: a } & { x: string })) -> { x: number } | { x: string }", toString(requireType("f"))
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,7 +8,6 @@ using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2);
|
LUAU_FASTFLAG(LuauSolverV2);
|
||||||
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions);
|
LUAU_FASTFLAG(LuauNoMoreInjectiveTypeFunctions);
|
||||||
LUAU_FASTFLAG(DebugLuauGreedyGeneralization);
|
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("TypeInferUnknownNever");
|
TEST_SUITE_BEGIN("TypeInferUnknownNever");
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ using namespace Luau::TypePath;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2);
|
LUAU_FASTFLAG(LuauSolverV2);
|
||||||
LUAU_DYNAMIC_FASTINT(LuauTypePathMaximumTraverseSteps);
|
LUAU_DYNAMIC_FASTINT(LuauTypePathMaximumTraverseSteps);
|
||||||
LUAU_FASTFLAG(LuauFreeTypesMustHaveBounds);
|
|
||||||
|
|
||||||
struct TypePathFixture : Fixture
|
struct TypePathFixture : Fixture
|
||||||
{
|
{
|
||||||
|
|
|
@ -103,6 +103,12 @@ def main():
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"path", action="store", help="Path to the Luau.UnitTest executable"
|
"path", action="store", help="Path to the Luau.UnitTest executable"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--fflags",
|
||||||
|
dest="flags",
|
||||||
|
action="store",
|
||||||
|
help="Set extra FFlags",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--dump",
|
"--dump",
|
||||||
dest="dump",
|
dest="dump",
|
||||||
|
@ -136,9 +142,11 @@ def main():
|
||||||
|
|
||||||
failList = loadFailList()
|
failList = loadFailList()
|
||||||
|
|
||||||
flags = ["true", "LuauSolverV2"]
|
flags = "true,LuauSolverV2"
|
||||||
|
if args.flags:
|
||||||
|
flags += "," + args.flags
|
||||||
|
|
||||||
commandLine = [args.path, "--reporters=xml", "--fflags=" + ",".join(flags)]
|
commandLine = [args.path, "--reporters=xml", "--fflags=" + flags]
|
||||||
|
|
||||||
if args.random_seed:
|
if args.random_seed:
|
||||||
commandLine.append("--random-seed=" + str(args.random_seed))
|
commandLine.append("--random-seed=" + str(args.random_seed))
|
||||||
|
|
Loading…
Add table
Reference in a new issue