Sync to upstream/release/527 (#481)

This commit is contained in:
Arseny Kapoulkine 2022-05-13 12:36:37 -07:00 committed by GitHub
parent 87fe15ac51
commit a36b1eb29b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 511 additions and 416 deletions

View File

@ -329,7 +329,7 @@ struct TableTypeVar
// We need to know which is which when we stringify types. // We need to know which is which when we stringify types.
std::optional<std::string> syntheticName; std::optional<std::string> syntheticName;
std::map<Name, Location> methodDefinitionLocations; std::map<Name, Location> methodDefinitionLocations; // TODO: Remove with FFlag::LuauNoMethodLocations
std::vector<TypeId> instantiatedTypeParams; std::vector<TypeId> instantiatedTypeParams;
std::vector<TypePackId> instantiatedTypePackParams; std::vector<TypePackId> instantiatedTypePackParams;
ModuleName definitionModuleName; ModuleName definitionModuleName;

View File

@ -11,6 +11,7 @@ LUAU_FASTFLAG(DebugLuauCopyBeforeNormalizing)
LUAU_FASTINTVARIABLE(LuauTypeCloneRecursionLimit, 300) LUAU_FASTINTVARIABLE(LuauTypeCloneRecursionLimit, 300)
LUAU_FASTFLAG(LuauTypecheckOptPass) LUAU_FASTFLAG(LuauTypecheckOptPass)
LUAU_FASTFLAGVARIABLE(LuauLosslessClone, false) LUAU_FASTFLAGVARIABLE(LuauLosslessClone, false)
LUAU_FASTFLAG(LuauNoMethodLocations)
namespace Luau namespace Luau
{ {
@ -277,7 +278,8 @@ void TypeCloner::operator()(const TableTypeVar& t)
} }
ttv->definitionModuleName = t.definitionModuleName; ttv->definitionModuleName = t.definitionModuleName;
ttv->methodDefinitionLocations = t.methodDefinitionLocations; if (!FFlag::LuauNoMethodLocations)
ttv->methodDefinitionLocations = t.methodDefinitionLocations;
ttv->tags = t.tags; ttv->tags = t.tags;
} }

View File

@ -14,7 +14,6 @@ LUAU_FASTFLAGVARIABLE(DebugLuauCopyBeforeNormalizing, false)
// This could theoretically be 2000 on amd64, but x86 requires this. // This could theoretically be 2000 on amd64, but x86 requires this.
LUAU_FASTINTVARIABLE(LuauNormalizeIterationLimit, 1200); LUAU_FASTINTVARIABLE(LuauNormalizeIterationLimit, 1200);
LUAU_FASTFLAGVARIABLE(LuauNormalizeCombineTableFix, false); LUAU_FASTFLAGVARIABLE(LuauNormalizeCombineTableFix, false);
LUAU_FASTFLAGVARIABLE(LuauNormalizeCombineIntersectionFix, false);
namespace Luau namespace Luau
{ {
@ -863,7 +862,7 @@ struct Normalize final : TypeVarVisitor
TypeId theTable = result->parts.back(); TypeId theTable = result->parts.back();
if (!get<TableTypeVar>(FFlag::LuauNormalizeCombineIntersectionFix ? follow(theTable) : theTable)) if (!get<TableTypeVar>(follow(theTable)))
{ {
result->parts.push_back(arena.addType(TableTypeVar{TableState::Sealed, TypeLevel{}})); result->parts.push_back(arena.addType(TableTypeVar{TableState::Sealed, TypeLevel{}}));
theTable = result->parts.back(); theTable = result->parts.back();

View File

@ -12,6 +12,7 @@ LUAU_FASTINTVARIABLE(LuauTarjanChildLimit, 10000)
LUAU_FASTFLAG(LuauTypecheckOptPass) LUAU_FASTFLAG(LuauTypecheckOptPass)
LUAU_FASTFLAGVARIABLE(LuauSubstituteFollowNewTypes, false) LUAU_FASTFLAGVARIABLE(LuauSubstituteFollowNewTypes, false)
LUAU_FASTFLAGVARIABLE(LuauSubstituteFollowPossibleMutations, false) LUAU_FASTFLAGVARIABLE(LuauSubstituteFollowPossibleMutations, false)
LUAU_FASTFLAG(LuauNoMethodLocations)
namespace Luau namespace Luau
{ {
@ -408,7 +409,8 @@ TypeId Substitution::clone(TypeId ty)
{ {
LUAU_ASSERT(!ttv->boundTo); LUAU_ASSERT(!ttv->boundTo);
TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, ttv->state}; TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, ttv->state};
clone.methodDefinitionLocations = ttv->methodDefinitionLocations; if (!FFlag::LuauNoMethodLocations)
clone.methodDefinitionLocations = ttv->methodDefinitionLocations;
clone.definitionModuleName = ttv->definitionModuleName; clone.definitionModuleName = ttv->definitionModuleName;
clone.name = ttv->name; clone.name = ttv->name;
clone.syntheticName = ttv->syntheticName; clone.syntheticName = ttv->syntheticName;

View File

@ -248,6 +248,13 @@ struct StringifierState
result.name += s; result.name += s;
} }
void emit(TypeLevel level)
{
emit(std::to_string(level.level));
emit("-");
emit(std::to_string(level.subLevel));
}
void emit(const char* s) void emit(const char* s)
{ {
if (opts.maxTypeLength > 0 && result.name.length() > opts.maxTypeLength) if (opts.maxTypeLength > 0 && result.name.length() > opts.maxTypeLength)
@ -379,7 +386,7 @@ struct TypeVarStringifier
if (FFlag::DebugLuauVerboseTypeNames) if (FFlag::DebugLuauVerboseTypeNames)
{ {
state.emit("-"); state.emit("-");
state.emit(std::to_string(ftv.level.level)); state.emit(ftv.level);
} }
} }
@ -403,7 +410,10 @@ struct TypeVarStringifier
{ {
state.result.invalid = true; state.result.invalid = true;
state.emit("[["); state.emit("[");
if (FFlag::DebugLuauVerboseTypeNames)
state.emit(ctv.level);
state.emit("[");
bool first = true; bool first = true;
for (TypeId ty : ctv.parts) for (TypeId ty : ctv.parts)
@ -947,7 +957,7 @@ struct TypePackStringifier
if (FFlag::DebugLuauVerboseTypeNames) if (FFlag::DebugLuauVerboseTypeNames)
{ {
state.emit("-"); state.emit("-");
state.emit(std::to_string(pack.level.level)); state.emit(pack.level);
} }
state.emit("..."); state.emit("...");

View File

@ -36,13 +36,11 @@ LUAU_FASTFLAGVARIABLE(LuauEqConstraint, false)
LUAU_FASTFLAGVARIABLE(LuauWeakEqConstraint, false) // Eventually removed as false. LUAU_FASTFLAGVARIABLE(LuauWeakEqConstraint, false) // Eventually removed as false.
LUAU_FASTFLAGVARIABLE(LuauLowerBoundsCalculation, false) LUAU_FASTFLAGVARIABLE(LuauLowerBoundsCalculation, false)
LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false) LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false)
LUAU_FASTFLAGVARIABLE(LuauInferStatFunction, false)
LUAU_FASTFLAGVARIABLE(LuauInstantiateFollows, false) LUAU_FASTFLAGVARIABLE(LuauInstantiateFollows, false)
LUAU_FASTFLAGVARIABLE(LuauSelfCallAutocompleteFix, false) LUAU_FASTFLAGVARIABLE(LuauSelfCallAutocompleteFix, false)
LUAU_FASTFLAGVARIABLE(LuauDiscriminableUnions2, false) LUAU_FASTFLAGVARIABLE(LuauDiscriminableUnions2, false)
LUAU_FASTFLAGVARIABLE(LuauReduceUnionRecursion, false) LUAU_FASTFLAGVARIABLE(LuauReduceUnionRecursion, false)
LUAU_FASTFLAGVARIABLE(LuauOnlyMutateInstantiatedTables, false) LUAU_FASTFLAGVARIABLE(LuauOnlyMutateInstantiatedTables, false)
LUAU_FASTFLAGVARIABLE(LuauStatFunctionSimplify4, false)
LUAU_FASTFLAGVARIABLE(LuauTypecheckOptPass, false) LUAU_FASTFLAGVARIABLE(LuauTypecheckOptPass, false)
LUAU_FASTFLAGVARIABLE(LuauUnsealedTableLiteral, false) LUAU_FASTFLAGVARIABLE(LuauUnsealedTableLiteral, false)
LUAU_FASTFLAGVARIABLE(LuauTwoPassAliasDefinitionFix, false) LUAU_FASTFLAGVARIABLE(LuauTwoPassAliasDefinitionFix, false)
@ -53,12 +51,13 @@ LUAU_FASTFLAGVARIABLE(LuauDoNotTryToReduce, false)
LUAU_FASTFLAGVARIABLE(LuauDoNotAccidentallyDependOnPointerOrdering, false) LUAU_FASTFLAGVARIABLE(LuauDoNotAccidentallyDependOnPointerOrdering, false)
LUAU_FASTFLAGVARIABLE(LuauCheckImplicitNumbericKeys, false) LUAU_FASTFLAGVARIABLE(LuauCheckImplicitNumbericKeys, false)
LUAU_FASTFLAG(LuauAnyInIsOptionalIsOptional) LUAU_FASTFLAG(LuauAnyInIsOptionalIsOptional)
LUAU_FASTFLAGVARIABLE(LuauDecoupleOperatorInferenceFromUnifiedTypeInference, false)
LUAU_FASTFLAGVARIABLE(LuauTableUseCounterInstead, false) LUAU_FASTFLAGVARIABLE(LuauTableUseCounterInstead, false)
LUAU_FASTFLAGVARIABLE(LuauReturnTypeInferenceInNonstrict, false) LUAU_FASTFLAGVARIABLE(LuauReturnTypeInferenceInNonstrict, false)
LUAU_FASTFLAGVARIABLE(LuauRecursionLimitException, false); LUAU_FASTFLAGVARIABLE(LuauRecursionLimitException, false);
LUAU_FASTFLAG(LuauLosslessClone) LUAU_FASTFLAG(LuauLosslessClone)
LUAU_FASTFLAGVARIABLE(LuauTypecheckIter, false); LUAU_FASTFLAGVARIABLE(LuauTypecheckIter, false);
LUAU_FASTFLAGVARIABLE(LuauSuccessTypingForEqualityOperations, false)
LUAU_FASTFLAGVARIABLE(LuauNoMethodLocations, false);
namespace Luau namespace Luau
{ {
@ -587,7 +586,7 @@ void TypeChecker::checkBlockWithoutRecursionCheck(const ScopePtr& scope, const A
{ {
std::optional<TypeId> expectedType; std::optional<TypeId> expectedType;
if (FFlag::LuauInferStatFunction && !fun->func->self) if (!fun->func->self)
{ {
if (auto name = fun->name->as<AstExprIndexName>()) if (auto name = fun->name->as<AstExprIndexName>())
{ {
@ -1307,7 +1306,7 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco
scope->bindings[name->local] = {anyIfNonstrict(quantify(funScope, ty, name->local->location)), name->local->location}; scope->bindings[name->local] = {anyIfNonstrict(quantify(funScope, ty, name->local->location)), name->local->location};
return; return;
} }
else if (auto name = function.name->as<AstExprIndexName>(); name && FFlag::LuauStatFunctionSimplify4) else if (auto name = function.name->as<AstExprIndexName>())
{ {
TypeId exprTy = checkExpr(scope, *name->expr).type; TypeId exprTy = checkExpr(scope, *name->expr).type;
TableTypeVar* ttv = getMutableTableType(exprTy); TableTypeVar* ttv = getMutableTableType(exprTy);
@ -1341,7 +1340,7 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco
if (ttv && ttv->state != TableState::Sealed) if (ttv && ttv->state != TableState::Sealed)
ttv->props[name->index.value] = {follow(quantify(funScope, ty, name->indexLocation)), /* deprecated */ false, {}, name->indexLocation}; ttv->props[name->index.value] = {follow(quantify(funScope, ty, name->indexLocation)), /* deprecated */ false, {}, name->indexLocation};
} }
else if (FFlag::LuauStatFunctionSimplify4) else
{ {
LUAU_ASSERT(function.name->is<AstExprError>()); LUAU_ASSERT(function.name->is<AstExprError>());
@ -1349,71 +1348,6 @@ void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funSco
checkFunctionBody(funScope, ty, *function.func); checkFunctionBody(funScope, ty, *function.func);
} }
else if (function.func->self)
{
LUAU_ASSERT(!FFlag::LuauStatFunctionSimplify4);
AstExprIndexName* indexName = function.name->as<AstExprIndexName>();
if (!indexName)
ice("member function declaration has malformed name expression");
TypeId selfTy = checkExpr(scope, *indexName->expr).type;
TableTypeVar* tableSelf = getMutableTableType(selfTy);
if (!tableSelf)
{
if (isTableIntersection(selfTy))
reportError(TypeError{function.location, CannotExtendTable{selfTy, CannotExtendTable::Property, indexName->index.value}});
else if (!get<ErrorTypeVar>(selfTy) && !get<AnyTypeVar>(selfTy))
reportError(TypeError{function.location, OnlyTablesCanHaveMethods{selfTy}});
}
else if (tableSelf->state == TableState::Sealed)
reportError(TypeError{function.location, CannotExtendTable{selfTy, CannotExtendTable::Property, indexName->index.value}});
const bool tableIsExtendable = tableSelf && tableSelf->state != TableState::Sealed;
ty = follow(ty);
if (tableIsExtendable)
tableSelf->props[indexName->index.value] = {ty, /* deprecated */ false, {}, indexName->indexLocation};
const FunctionTypeVar* funTy = get<FunctionTypeVar>(ty);
if (!funTy)
ice("Methods should be functions");
std::optional<TypeId> arg0 = first(funTy->argTypes);
if (!arg0)
ice("Methods should always have at least 1 argument (self)");
checkFunctionBody(funScope, ty, *function.func);
if (tableIsExtendable)
tableSelf->props[indexName->index.value] = {
follow(quantify(funScope, ty, indexName->indexLocation)), /* deprecated */ false, {}, indexName->indexLocation};
}
else
{
LUAU_ASSERT(!FFlag::LuauStatFunctionSimplify4);
TypeId leftType = checkLValueBinding(scope, *function.name);
checkFunctionBody(funScope, ty, *function.func);
unify(ty, leftType, function.location);
LUAU_ASSERT(function.name->is<AstExprIndexName>() || function.name->is<AstExprError>());
if (auto exprIndexName = function.name->as<AstExprIndexName>())
{
if (auto typeIt = currentModule->astTypes.find(exprIndexName->expr))
{
if (auto ttv = getMutableTableType(*typeIt))
{
if (auto it = ttv->props.find(exprIndexName->index.value); it != ttv->props.end())
it->second.type = follow(quantify(funScope, leftType, function.name->location));
}
}
}
}
} }
void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funScope, const AstStatLocalFunction& function) void TypeChecker::check(const ScopePtr& scope, TypeId ty, const ScopePtr& funScope, const AstStatLocalFunction& function)
@ -1523,7 +1457,8 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatTypeAlias& typealias
// This is a shallow clone, original recursive links to self are not updated // This is a shallow clone, original recursive links to self are not updated
TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, ttv->state}; TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, ttv->state};
clone.methodDefinitionLocations = ttv->methodDefinitionLocations; if (!FFlag::LuauNoMethodLocations)
clone.methodDefinitionLocations = ttv->methodDefinitionLocations;
clone.definitionModuleName = ttv->definitionModuleName; clone.definitionModuleName = ttv->definitionModuleName;
clone.name = name; clone.name = name;
@ -2652,13 +2587,58 @@ TypeId TypeChecker::checkRelationalOperation(
std::optional<TypeId> leftMetatable = isString(lhsType) ? std::nullopt : getMetatable(follow(lhsType)); std::optional<TypeId> leftMetatable = isString(lhsType) ? std::nullopt : getMetatable(follow(lhsType));
std::optional<TypeId> rightMetatable = isString(rhsType) ? std::nullopt : getMetatable(follow(rhsType)); std::optional<TypeId> rightMetatable = isString(rhsType) ? std::nullopt : getMetatable(follow(rhsType));
// TODO: this check seems odd, the second part is redundant if (FFlag::LuauSuccessTypingForEqualityOperations)
// is it meant to be if (leftMetatable && rightMetatable && leftMetatable != rightMetatable)
if (bool(leftMetatable) != bool(rightMetatable) && leftMetatable != rightMetatable)
{ {
reportError(expr.location, GenericError{format("Types %s and %s cannot be compared with %s because they do not have the same metatable", if (leftMetatable != rightMetatable)
toString(lhsType).c_str(), toString(rhsType).c_str(), toString(expr.op).c_str())}); {
return errorRecoveryType(booleanType); bool matches = false;
if (isEquality)
{
if (const UnionTypeVar* utv = get<UnionTypeVar>(leftType); utv && rightMetatable)
{
for (TypeId leftOption : utv)
{
if (getMetatable(follow(leftOption)) == rightMetatable)
{
matches = true;
break;
}
}
}
if (!matches)
{
if (const UnionTypeVar* utv = get<UnionTypeVar>(rhsType); utv && leftMetatable)
{
for (TypeId rightOption : utv)
{
if (getMetatable(follow(rightOption)) == leftMetatable)
{
matches = true;
break;
}
}
}
}
}
if (!matches)
{
reportError(expr.location, GenericError{format("Types %s and %s cannot be compared with %s because they do not have the same metatable",
toString(lhsType).c_str(), toString(rhsType).c_str(), toString(expr.op).c_str())});
return errorRecoveryType(booleanType);
}
}
}
else
{
if (bool(leftMetatable) != bool(rightMetatable) && leftMetatable != rightMetatable)
{
reportError(expr.location, GenericError{format("Types %s and %s cannot be compared with %s because they do not have the same metatable",
toString(lhsType).c_str(), toString(rhsType).c_str(), toString(expr.op).c_str())});
return errorRecoveryType(booleanType);
}
} }
if (leftMetatable) if (leftMetatable)
@ -2754,22 +2734,11 @@ TypeId TypeChecker::checkBinaryOperation(
lhsType = follow(lhsType); lhsType = follow(lhsType);
rhsType = follow(rhsType); rhsType = follow(rhsType);
if (FFlag::LuauDecoupleOperatorInferenceFromUnifiedTypeInference) if (!isNonstrictMode() && get<FreeTypeVar>(lhsType))
{ {
if (!isNonstrictMode() && get<FreeTypeVar>(lhsType)) auto name = getIdentifierOfBaseVar(expr.left);
{ reportError(expr.location, CannotInferBinaryOperation{expr.op, name, CannotInferBinaryOperation::Operation});
auto name = getIdentifierOfBaseVar(expr.left); // We will fall-through to the `return anyType` check below.
reportError(expr.location, CannotInferBinaryOperation{expr.op, name, CannotInferBinaryOperation::Operation});
// We will fall-through to the `return anyType` check below.
}
}
else
{
if (!isNonstrictMode() && get<FreeTypeVar>(lhsType))
{
auto name = getIdentifierOfBaseVar(expr.left);
reportError(expr.location, CannotInferBinaryOperation{expr.op, name, CannotInferBinaryOperation::Operation});
}
} }
// If we know nothing at all about the lhs type, we can usually say nothing about the result. // If we know nothing at all about the lhs type, we can usually say nothing about the result.
@ -3231,43 +3200,27 @@ TypeId TypeChecker::checkFunctionName(const ScopePtr& scope, AstExpr& funName, T
else if (auto indexName = funName.as<AstExprIndexName>()) else if (auto indexName = funName.as<AstExprIndexName>())
{ {
TypeId lhsType = checkExpr(scope, *indexName->expr).type; TypeId lhsType = checkExpr(scope, *indexName->expr).type;
if (!FFlag::LuauStatFunctionSimplify4 && (get<ErrorTypeVar>(lhsType) || get<AnyTypeVar>(lhsType)))
return lhsType;
TableTypeVar* ttv = getMutableTableType(lhsType); TableTypeVar* ttv = getMutableTableType(lhsType);
if (FFlag::LuauStatFunctionSimplify4) if (!ttv || ttv->state == TableState::Sealed)
{ {
if (!ttv || ttv->state == TableState::Sealed) if (auto ty = getIndexTypeFromType(scope, lhsType, indexName->index.value, indexName->indexLocation, false))
{ return *ty;
if (auto ty = getIndexTypeFromType(scope, lhsType, indexName->index.value, indexName->indexLocation, false))
return *ty;
return errorRecoveryType(scope); return errorRecoveryType(scope);
}
}
else
{
if (!ttv || lhsType->persistent || ttv->state == TableState::Sealed)
return errorRecoveryType(scope);
} }
Name name = indexName->index.value; Name name = indexName->index.value;
if (ttv->props.count(name)) if (ttv->props.count(name))
{ return ttv->props[name].type;
if (FFlag::LuauStatFunctionSimplify4)
return ttv->props[name].type;
else
return errorRecoveryType(scope);
}
Property& property = ttv->props[name]; Property& property = ttv->props[name];
property.type = freshTy(); property.type = freshTy();
property.location = indexName->indexLocation; property.location = indexName->indexLocation;
ttv->methodDefinitionLocations[name] = funName.location; if (!FFlag::LuauNoMethodLocations)
ttv->methodDefinitionLocations[name] = funName.location;
return property.type; return property.type;
} }
else if (funName.is<AstExprError>()) else if (funName.is<AstExprError>())
@ -4669,7 +4622,8 @@ TypeId ReplaceGenerics::clean(TypeId ty)
if (const TableTypeVar* ttv = log->getMutable<TableTypeVar>(ty)) if (const TableTypeVar* ttv = log->getMutable<TableTypeVar>(ty))
{ {
TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, level, TableState::Free}; TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, level, TableState::Free};
clone.methodDefinitionLocations = ttv->methodDefinitionLocations; if (!FFlag::LuauNoMethodLocations)
clone.methodDefinitionLocations = ttv->methodDefinitionLocations;
clone.definitionModuleName = ttv->definitionModuleName; clone.definitionModuleName = ttv->definitionModuleName;
return addType(std::move(clone)); return addType(std::move(clone));
} }
@ -4715,7 +4669,8 @@ TypeId Anyification::clean(TypeId ty)
if (const TableTypeVar* ttv = log->getMutable<TableTypeVar>(ty)) if (const TableTypeVar* ttv = log->getMutable<TableTypeVar>(ty))
{ {
TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, TableState::Sealed}; TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, TableState::Sealed};
clone.methodDefinitionLocations = ttv->methodDefinitionLocations; if (!FFlag::LuauNoMethodLocations)
clone.methodDefinitionLocations = ttv->methodDefinitionLocations;
clone.definitionModuleName = ttv->definitionModuleName; clone.definitionModuleName = ttv->definitionModuleName;
clone.name = ttv->name; clone.name = ttv->name;
clone.syntheticName = ttv->syntheticName; clone.syntheticName = ttv->syntheticName;

View File

@ -10,7 +10,6 @@
// See docs/SyntaxChanges.md for an explanation. // See docs/SyntaxChanges.md for an explanation.
LUAU_FASTINTVARIABLE(LuauRecursionLimit, 1000) LUAU_FASTINTVARIABLE(LuauRecursionLimit, 1000)
LUAU_FASTINTVARIABLE(LuauParseErrorLimit, 100) LUAU_FASTINTVARIABLE(LuauParseErrorLimit, 100)
LUAU_FASTFLAGVARIABLE(LuauParseLocationIgnoreCommentSkipInCapture, false)
namespace Luau namespace Luau
{ {
@ -2821,7 +2820,7 @@ void Parser::nextLexeme()
hotcomments.push_back({hotcommentHeader, lexeme.location, std::string(text + 1, text + end)}); hotcomments.push_back({hotcommentHeader, lexeme.location, std::string(text + 1, text + end)});
} }
type = lexer.next(/* skipComments= */ false, !FFlag::LuauParseLocationIgnoreCommentSkipInCapture).type; type = lexer.next(/* skipComments= */ false, /* updatePrevLocation= */ false).type;
} }
} }
else else

View File

@ -110,6 +110,12 @@ if (MSVC AND MSVC_VERSION GREATER_EQUAL 1924)
set_source_files_properties(VM/src/lvmexecute.cpp PROPERTIES COMPILE_FLAGS /d2ssa-pre-) set_source_files_properties(VM/src/lvmexecute.cpp PROPERTIES COMPILE_FLAGS /d2ssa-pre-)
endif() endif()
if(MSVC AND LUAU_BUILD_CLI)
# the default stack size that MSVC linker uses is 1 MB; we need more stack space in Debug because stack frames are larger
set_target_properties(Luau.Analyze.CLI PROPERTIES LINK_FLAGS_DEBUG /STACK:2097152)
set_target_properties(Luau.Repl.CLI PROPERTIES LINK_FLAGS_DEBUG /STACK:2097152)
endif()
# embed .natvis inside the library debug information # embed .natvis inside the library debug information
if(MSVC) if(MSVC)
target_link_options(Luau.Ast INTERFACE /NATVIS:${CMAKE_CURRENT_SOURCE_DIR}/tools/natvis/Ast.natvis) target_link_options(Luau.Ast INTERFACE /NATVIS:${CMAKE_CURRENT_SOURCE_DIR}/tools/natvis/Ast.natvis)

View File

@ -628,7 +628,12 @@ struct Compiler
return; return;
if (fi && !fi->canInline) if (fi && !fi->canInline)
bytecode.addDebugRemark("inlining failed: complex constructs in function body"); {
if (func->vararg)
bytecode.addDebugRemark("inlining failed: function is variadic");
else
bytecode.addDebugRemark("inlining failed: complex constructs in function body");
}
} }
RegScope rs(this); RegScope rs(this);
@ -2342,17 +2347,28 @@ struct Compiler
RegScope rs(this); RegScope rs(this);
uint8_t temp = 0; uint8_t temp = 0;
bool consecutive = false;
bool multRet = false; bool multRet = false;
// Optimization: return local value directly instead of copying it into a temporary // Optimization: return locals directly instead of copying them into a temporary
if (stat->list.size == 1 && isExprLocalReg(stat->list.data[0])) // this is very important for a single return value and occasionally effective for multiple values
if (stat->list.size > 0 && isExprLocalReg(stat->list.data[0]))
{ {
AstExprLocal* le = stat->list.data[0]->as<AstExprLocal>(); temp = getLocal(stat->list.data[0]->as<AstExprLocal>()->local);
LUAU_ASSERT(le); consecutive = true;
temp = getLocal(le->local); for (size_t i = 1; i < stat->list.size; ++i)
{
AstExpr* v = stat->list.data[i];
if (!isExprLocalReg(v) || getLocal(v->as<AstExprLocal>()->local) != temp + i)
{
consecutive = false;
break;
}
}
} }
else if (stat->list.size > 0)
if (!consecutive && stat->list.size > 0)
{ {
temp = allocReg(stat, unsigned(stat->list.size)); temp = allocReg(stat, unsigned(stat->list.size));

View File

@ -195,12 +195,16 @@ struct ConstantVisitor : AstVisitor
DenseHashMap<AstLocal*, Variable>& variables; DenseHashMap<AstLocal*, Variable>& variables;
DenseHashMap<AstLocal*, Constant>& locals; DenseHashMap<AstLocal*, Constant>& locals;
bool wasEmpty = false;
ConstantVisitor( ConstantVisitor(
DenseHashMap<AstExpr*, Constant>& constants, DenseHashMap<AstLocal*, Variable>& variables, DenseHashMap<AstLocal*, Constant>& locals) DenseHashMap<AstExpr*, Constant>& constants, DenseHashMap<AstLocal*, Variable>& variables, DenseHashMap<AstLocal*, Constant>& locals)
: constants(constants) : constants(constants)
, variables(variables) , variables(variables)
, locals(locals) , locals(locals)
{ {
// since we do a single pass over the tree, if the initial state was empty we don't need to clear out old entries
wasEmpty = constants.empty() && locals.empty();
} }
Constant analyze(AstExpr* node) Constant analyze(AstExpr* node)
@ -326,7 +330,7 @@ struct ConstantVisitor : AstVisitor
{ {
if (value.type != Constant::Type_Unknown) if (value.type != Constant::Type_Unknown)
map[key] = value; map[key] = value;
else if (!FFlag::LuauCompileSupportInlining) else if (!FFlag::LuauCompileSupportInlining || wasEmpty)
; ;
else if (Constant* old = map.find(key)) else if (Constant* old = map.find(key))
old->type = Constant::Type_Unknown; old->type = Constant::Type_Unknown;

View File

@ -187,7 +187,7 @@ struct CostVisitor : AstVisitor
if (node->is<AstStatIf>()) if (node->is<AstStatIf>())
result += 2; result += 2;
else if (node->is<AstStatWhile>() || node->is<AstStatRepeat>() || node->is<AstStatFor>() || node->is<AstStatForIn>()) else if (node->is<AstStatWhile>() || node->is<AstStatRepeat>() || node->is<AstStatFor>() || node->is<AstStatForIn>())
result += 2; result += 5;
else if (node->is<AstStatBreak>() || node->is<AstStatContinue>()) else if (node->is<AstStatBreak>() || node->is<AstStatContinue>())
result += 1; result += 1;

View File

@ -575,6 +575,7 @@ ic_private const char* parse_tag_value( tag_t* tag, char* idbuf, const char* s,
} }
// limit name and attr to 128 bytes // limit name and attr to 128 bytes
char valbuf[128]; char valbuf[128];
valbuf[0] = 0; // fixes gcc uninitialized warning
ic_strncpy( idbuf, 128, id, idend - id); ic_strncpy( idbuf, 128, id, idend - id);
ic_strncpy( valbuf, 128, val, valend - val); ic_strncpy( valbuf, 128, val, valend - val);
ic_str_tolower(idbuf); ic_str_tolower(idbuf);

View File

@ -7,7 +7,7 @@
using namespace Luau; using namespace Luau;
struct DocumentationSymbolFixture : Fixture struct DocumentationSymbolFixture : BuiltinsFixture
{ {
std::optional<DocumentationSymbol> getDocSymbol(const std::string& source, Position position) std::optional<DocumentationSymbol> getDocSymbol(const std::string& source, Position position)
{ {

View File

@ -27,7 +27,7 @@ template<class BaseType>
struct ACFixtureImpl : BaseType struct ACFixtureImpl : BaseType
{ {
ACFixtureImpl() ACFixtureImpl()
: Fixture(true, true) : BaseType(true, true)
{ {
} }
@ -111,6 +111,18 @@ struct ACFixtureImpl : BaseType
}; };
struct ACFixture : ACFixtureImpl<Fixture> struct ACFixture : ACFixtureImpl<Fixture>
{
ACFixture()
: ACFixtureImpl<Fixture>()
{
addGlobalBinding(frontend.typeChecker, "table", Binding{typeChecker.anyType});
addGlobalBinding(frontend.typeChecker, "math", Binding{typeChecker.anyType});
addGlobalBinding(frontend.typeCheckerForAutocomplete, "table", Binding{typeChecker.anyType});
addGlobalBinding(frontend.typeCheckerForAutocomplete, "math", Binding{typeChecker.anyType});
}
};
struct ACBuiltinsFixture : ACFixtureImpl<BuiltinsFixture>
{ {
}; };
@ -277,7 +289,7 @@ TEST_CASE_FIXTURE(ACFixture, "function_parameters")
CHECK(ac.entryMap.count("test")); CHECK(ac.entryMap.count("test"));
} }
TEST_CASE_FIXTURE(ACFixture, "get_member_completions") TEST_CASE_FIXTURE(ACBuiltinsFixture, "get_member_completions")
{ {
check(R"( check(R"(
local a = table.@1 local a = table.@1
@ -376,7 +388,7 @@ TEST_CASE_FIXTURE(ACFixture, "table_intersection")
CHECK(ac.entryMap.count("c3")); CHECK(ac.entryMap.count("c3"));
} }
TEST_CASE_FIXTURE(ACFixture, "get_string_completions") TEST_CASE_FIXTURE(ACBuiltinsFixture, "get_string_completions")
{ {
check(R"( check(R"(
local a = ("foo"):@1 local a = ("foo"):@1
@ -427,7 +439,7 @@ TEST_CASE_FIXTURE(ACFixture, "method_call_inside_function_body")
CHECK(!ac.entryMap.count("math")); CHECK(!ac.entryMap.count("math"));
} }
TEST_CASE_FIXTURE(ACFixture, "method_call_inside_if_conditional") TEST_CASE_FIXTURE(ACBuiltinsFixture, "method_call_inside_if_conditional")
{ {
check(R"( check(R"(
if table: @1 if table: @1
@ -1884,7 +1896,7 @@ ex.b(function(x:
CHECK(!ac.entryMap.count("(done) -> number")); CHECK(!ac.entryMap.count("(done) -> number"));
} }
TEST_CASE_FIXTURE(ACFixture, "suggest_external_module_type") TEST_CASE_FIXTURE(ACBuiltinsFixture, "suggest_external_module_type")
{ {
fileResolver.source["Module/A"] = R"( fileResolver.source["Module/A"] = R"(
export type done = { x: number, y: number } export type done = { x: number, y: number }
@ -2235,7 +2247,7 @@ local a: aaa.do
CHECK(ac.entryMap.count("other")); CHECK(ac.entryMap.count("other"));
} }
TEST_CASE_FIXTURE(ACFixture, "autocompleteSource") TEST_CASE_FIXTURE(ACBuiltinsFixture, "autocompleteSource")
{ {
std::string_view source = R"( std::string_view source = R"(
local a = table. -- Line 1 local a = table. -- Line 1
@ -2269,7 +2281,7 @@ TEST_CASE_FIXTURE(ACFixture, "autocompleteSource_comments")
CHECK_EQ(0, ac.entryMap.size()); CHECK_EQ(0, ac.entryMap.size());
} }
TEST_CASE_FIXTURE(ACFixture, "autocompleteProp_index_function_metamethod_is_variadic") TEST_CASE_FIXTURE(ACBuiltinsFixture, "autocompleteProp_index_function_metamethod_is_variadic")
{ {
std::string_view source = R"( std::string_view source = R"(
type Foo = {x: number} type Foo = {x: number}
@ -2720,7 +2732,7 @@ type A<T... = ...@1> = () -> T
CHECK(ac.entryMap.count("string")); CHECK(ac.entryMap.count("string"));
} }
TEST_CASE_FIXTURE(ACFixture, "autocomplete_oop_implicit_self") TEST_CASE_FIXTURE(ACBuiltinsFixture, "autocomplete_oop_implicit_self")
{ {
check(R"( check(R"(
--!strict --!strict
@ -2728,15 +2740,15 @@ local Class = {}
Class.__index = Class Class.__index = Class
type Class = typeof(setmetatable({} :: { x: number }, Class)) type Class = typeof(setmetatable({} :: { x: number }, Class))
function Class.new(x: number): Class function Class.new(x: number): Class
return setmetatable({x = x}, Class) return setmetatable({x = x}, Class)
end end
function Class.getx(self: Class) function Class.getx(self: Class)
return self.x return self.x
end end
function test() function test()
local c = Class.new(42) local c = Class.new(42)
local n = c:@1 local n = c:@1
print(n) print(n)
end end
)"); )");
@ -2745,7 +2757,7 @@ end
CHECK(ac.entryMap.count("getx")); CHECK(ac.entryMap.count("getx"));
} }
TEST_CASE_FIXTURE(ACFixture, "autocomplete_on_string_singletons") TEST_CASE_FIXTURE(ACBuiltinsFixture, "autocomplete_on_string_singletons")
{ {
check(R"( check(R"(
--!strict --!strict
@ -2989,7 +3001,7 @@ s.@1
CHECK(ac.entryMap["sub"].wrongIndexType == true); CHECK(ac.entryMap["sub"].wrongIndexType == true);
} }
TEST_CASE_FIXTURE(ACFixture, "string_library_non_self_calls_are_fine") TEST_CASE_FIXTURE(ACBuiltinsFixture, "string_library_non_self_calls_are_fine")
{ {
ScopedFastFlag selfCallAutocompleteFix{"LuauSelfCallAutocompleteFix", true}; ScopedFastFlag selfCallAutocompleteFix{"LuauSelfCallAutocompleteFix", true};
@ -3007,7 +3019,7 @@ string.@1
CHECK(ac.entryMap["sub"].wrongIndexType == false); CHECK(ac.entryMap["sub"].wrongIndexType == false);
} }
TEST_CASE_FIXTURE(ACFixture, "string_library_self_calls_are_invalid") TEST_CASE_FIXTURE(ACBuiltinsFixture, "string_library_self_calls_are_invalid")
{ {
ScopedFastFlag selfCallAutocompleteFix{"LuauSelfCallAutocompleteFix", true}; ScopedFastFlag selfCallAutocompleteFix{"LuauSelfCallAutocompleteFix", true};

View File

@ -10,8 +10,10 @@ using namespace Luau;
TEST_SUITE_BEGIN("BuiltinDefinitionsTest"); TEST_SUITE_BEGIN("BuiltinDefinitionsTest");
TEST_CASE_FIXTURE(Fixture, "lib_documentation_symbols") TEST_CASE_FIXTURE(BuiltinsFixture, "lib_documentation_symbols")
{ {
CHECK(!typeChecker.globalScope->bindings.empty());
for (const auto& [name, binding] : typeChecker.globalScope->bindings) for (const auto& [name, binding] : typeChecker.globalScope->bindings)
{ {
std::string nameString(name.c_str()); std::string nameString(name.c_str());

View File

@ -4713,7 +4713,6 @@ local function foo()
end end
local a, b = foo() local a, b = foo()
return a, b return a, b
)", )",
1, 2), 1, 2),
@ -4721,9 +4720,7 @@ return a, b
DUPCLOSURE R0 K0 DUPCLOSURE R0 K0
LOADNIL R1 LOADNIL R1
LOADNIL R2 LOADNIL R2
MOVE R3 R1 RETURN R1 2
MOVE R4 R2
RETURN R3 2
)"); )");
// this happens even if the function returns conditionally // this happens even if the function returns conditionally
@ -4733,7 +4730,6 @@ local function foo(a)
end end
local a, b = foo(false) local a, b = foo(false)
return a, b return a, b
)", )",
1, 2), 1, 2),
@ -4741,9 +4737,7 @@ return a, b
DUPCLOSURE R0 K0 DUPCLOSURE R0 K0
LOADNIL R1 LOADNIL R1
LOADNIL R2 LOADNIL R2
MOVE R3 R1 RETURN R1 2
MOVE R4 R2
RETURN R3 2
)"); )");
// note though that we can't inline a function like this in multret context // note though that we can't inline a function like this in multret context
@ -4880,11 +4874,7 @@ LOADN R5 1
ADD R4 R5 R1 ADD R4 R5 R1
LOADN R5 3 LOADN R5 3
ADD R6 R1 R2 ADD R6 R1 R2
MOVE R7 R3 RETURN R3 4
MOVE R8 R4
MOVE R9 R5
MOVE R10 R6
RETURN R7 4
)"); )");
} }
@ -5151,4 +5141,59 @@ RETURN R0 0
)"); )");
} }
TEST_CASE("ReturnConsecutive")
{
// we can return a single local directly
CHECK_EQ("\n" + compileFunction0(R"(
local x = ...
return x
)"),
R"(
GETVARARGS R0 1
RETURN R0 1
)");
// or multiple, when they are allocated in consecutive registers
CHECK_EQ("\n" + compileFunction0(R"(
local x, y = ...
return x, y
)"),
R"(
GETVARARGS R0 2
RETURN R0 2
)");
// but not if it's an expression
CHECK_EQ("\n" + compileFunction0(R"(
local x, y = ...
return x, y + 1
)"),
R"(
GETVARARGS R0 2
MOVE R2 R0
ADDK R3 R1 K0
RETURN R2 2
)");
// or a local with wrong register number
CHECK_EQ("\n" + compileFunction0(R"(
local x, y = ...
return y, x
)"),
R"(
GETVARARGS R0 2
MOVE R2 R1
MOVE R3 R0
RETURN R2 2
)");
// also double check the optimization doesn't trip on no-argument return (these are rare)
CHECK_EQ("\n" + compileFunction0(R"(
return
)"),
R"(
RETURN R0 0
)");
}
TEST_SUITE_END(); TEST_SUITE_END();

View File

@ -76,9 +76,9 @@ end
const bool args1[] = {false}; const bool args1[] = {false};
const bool args2[] = {true}; const bool args2[] = {true};
// loop baseline cost is 2 // loop baseline cost is 5
CHECK_EQ(3, Luau::Compile::computeCost(model, args1, 1)); CHECK_EQ(6, Luau::Compile::computeCost(model, args1, 1));
CHECK_EQ(3, Luau::Compile::computeCost(model, args2, 1)); CHECK_EQ(6, Luau::Compile::computeCost(model, args2, 1));
} }
TEST_CASE("MutableVariable") TEST_CASE("MutableVariable")
@ -154,8 +154,8 @@ end
const bool args1[] = {false}; const bool args1[] = {false};
const bool args2[] = {true}; const bool args2[] = {true};
CHECK_EQ(38, Luau::Compile::computeCost(model, args1, 1)); CHECK_EQ(50, Luau::Compile::computeCost(model, args1, 1));
CHECK_EQ(37, Luau::Compile::computeCost(model, args2, 1)); CHECK_EQ(49, Luau::Compile::computeCost(model, args2, 1));
} }
TEST_CASE("Conditional") TEST_CASE("Conditional")
@ -219,8 +219,8 @@ end
const bool args1[] = {false}; const bool args1[] = {false};
const bool args2[] = {true}; const bool args2[] = {true};
CHECK_EQ(4, Luau::Compile::computeCost(model, args1, 1)); CHECK_EQ(7, Luau::Compile::computeCost(model, args1, 1));
CHECK_EQ(3, Luau::Compile::computeCost(model, args2, 1)); CHECK_EQ(6, Luau::Compile::computeCost(model, args2, 1));
} }
TEST_SUITE_END(); TEST_SUITE_END();

View File

@ -92,10 +92,6 @@ Fixture::Fixture(bool freeze, bool prepareAutocomplete)
configResolver.defaultConfig.enabledLint.warningMask = ~0ull; configResolver.defaultConfig.enabledLint.warningMask = ~0ull;
configResolver.defaultConfig.parseOptions.captureComments = true; configResolver.defaultConfig.parseOptions.captureComments = true;
registerBuiltinTypes(frontend.typeChecker);
if (prepareAutocomplete)
registerBuiltinTypes(frontend.typeCheckerForAutocomplete);
registerTestTypes();
Luau::freeze(frontend.typeChecker.globalTypes); Luau::freeze(frontend.typeChecker.globalTypes);
Luau::freeze(frontend.typeCheckerForAutocomplete.globalTypes); Luau::freeze(frontend.typeCheckerForAutocomplete.globalTypes);
@ -410,6 +406,21 @@ LoadDefinitionFileResult Fixture::loadDefinition(const std::string& source)
return result; return result;
} }
BuiltinsFixture::BuiltinsFixture(bool freeze, bool prepareAutocomplete)
: Fixture(freeze, prepareAutocomplete)
{
Luau::unfreeze(frontend.typeChecker.globalTypes);
Luau::unfreeze(frontend.typeCheckerForAutocomplete.globalTypes);
registerBuiltinTypes(frontend.typeChecker);
if (prepareAutocomplete)
registerBuiltinTypes(frontend.typeCheckerForAutocomplete);
registerTestTypes();
Luau::freeze(frontend.typeChecker.globalTypes);
Luau::freeze(frontend.typeCheckerForAutocomplete.globalTypes);
}
ModuleName fromString(std::string_view name) ModuleName fromString(std::string_view name)
{ {
return ModuleName(name); return ModuleName(name);

View File

@ -151,6 +151,11 @@ struct Fixture
LoadDefinitionFileResult loadDefinition(const std::string& source); LoadDefinitionFileResult loadDefinition(const std::string& source);
}; };
struct BuiltinsFixture : Fixture
{
BuiltinsFixture(bool freeze = true, bool prepareAutocomplete = false);
};
ModuleName fromString(std::string_view name); ModuleName fromString(std::string_view name);
template<typename T> template<typename T>

View File

@ -77,7 +77,7 @@ struct NaiveFileResolver : NullFileResolver
} // namespace } // namespace
struct FrontendFixture : Fixture struct FrontendFixture : BuiltinsFixture
{ {
FrontendFixture() FrontendFixture()
{ {

View File

@ -75,7 +75,7 @@ _ = 6
CHECK_EQ(result.warnings.size(), 0); CHECK_EQ(result.warnings.size(), 0);
} }
TEST_CASE_FIXTURE(Fixture, "BuiltinGlobalWrite") TEST_CASE_FIXTURE(BuiltinsFixture, "BuiltinGlobalWrite")
{ {
LintResult result = lint(R"( LintResult result = lint(R"(
math = {} math = {}
@ -309,7 +309,7 @@ print(arg)
CHECK_EQ(result.warnings[0].text, "Variable 'arg' shadows previous declaration at line 2"); CHECK_EQ(result.warnings[0].text, "Variable 'arg' shadows previous declaration at line 2");
} }
TEST_CASE_FIXTURE(Fixture, "LocalShadowGlobal") TEST_CASE_FIXTURE(BuiltinsFixture, "LocalShadowGlobal")
{ {
LintResult result = lint(R"( LintResult result = lint(R"(
local math = math local math = math
@ -1470,7 +1470,7 @@ end
CHECK_EQ(result.warnings[2].text, "Member 'Instance.DataCost' is deprecated"); CHECK_EQ(result.warnings[2].text, "Member 'Instance.DataCost' is deprecated");
} }
TEST_CASE_FIXTURE(Fixture, "TableOperations") TEST_CASE_FIXTURE(BuiltinsFixture, "TableOperations")
{ {
LintResult result = lintTyped(R"( LintResult result = lintTyped(R"(
local t = {} local t = {}

View File

@ -113,7 +113,7 @@ TEST_CASE_FIXTURE(Fixture, "deepClone_cyclic_table")
CHECK_EQ(2, dest.typeVars.size()); // One table and one function CHECK_EQ(2, dest.typeVars.size()); // One table and one function
} }
TEST_CASE_FIXTURE(Fixture, "builtin_types_point_into_globalTypes_arena") TEST_CASE_FIXTURE(BuiltinsFixture, "builtin_types_point_into_globalTypes_arena")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
return {sign=math.sign} return {sign=math.sign}
@ -250,7 +250,7 @@ TEST_CASE_FIXTURE(Fixture, "clone_constrained_intersection")
CHECK_EQ(getSingletonTypes().stringType, ctv->parts[1]); CHECK_EQ(getSingletonTypes().stringType, ctv->parts[1]);
} }
TEST_CASE_FIXTURE(Fixture, "clone_self_property") TEST_CASE_FIXTURE(BuiltinsFixture, "clone_self_property")
{ {
ScopedFastFlag sff{"LuauAnyInIsOptionalIsOptional", true}; ScopedFastFlag sff{"LuauAnyInIsOptionalIsOptional", true};

View File

@ -13,7 +13,7 @@ using namespace Luau;
TEST_SUITE_BEGIN("NonstrictModeTests"); TEST_SUITE_BEGIN("NonstrictModeTests");
TEST_CASE_FIXTURE(Fixture, "function_returns_number_or_string") TEST_CASE_FIXTURE(BuiltinsFixture, "function_returns_number_or_string")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauReturnTypeInferenceInNonstrict", true}, {"LuauReturnTypeInferenceInNonstrict", true},
@ -224,7 +224,7 @@ TEST_CASE_FIXTURE(Fixture, "inline_table_props_are_also_any")
CHECK_MESSAGE(get<FunctionTypeVar>(ttv->props["three"].type), "Should be a function: " << *ttv->props["three"].type); CHECK_MESSAGE(get<FunctionTypeVar>(ttv->props["three"].type), "Should be a function: " << *ttv->props["three"].type);
} }
TEST_CASE_FIXTURE(Fixture, "for_in_iterator_variables_are_any") TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_iterator_variables_are_any")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -243,7 +243,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_iterator_variables_are_any")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_dot_insert_and_recursive_calls") TEST_CASE_FIXTURE(BuiltinsFixture, "table_dot_insert_and_recursive_calls")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict

View File

@ -739,7 +739,7 @@ TEST_CASE_FIXTURE(Fixture, "cyclic_table_normalizes_sensibly")
CHECK_EQ("t1 where t1 = { get: () -> t1 }", toString(ty, {true})); CHECK_EQ("t1 where t1 = { get: () -> t1 }", toString(ty, {true}));
} }
TEST_CASE_FIXTURE(Fixture, "union_of_distinct_free_types") TEST_CASE_FIXTURE(BuiltinsFixture, "union_of_distinct_free_types")
{ {
ScopedFastFlag flags[] = { ScopedFastFlag flags[] = {
{"LuauLowerBoundsCalculation", true}, {"LuauLowerBoundsCalculation", true},
@ -760,7 +760,7 @@ TEST_CASE_FIXTURE(Fixture, "union_of_distinct_free_types")
CHECK("<a, b>(a, b) -> a | b" == toString(requireType("fussy"))); CHECK("<a, b>(a, b) -> a | b" == toString(requireType("fussy")));
} }
TEST_CASE_FIXTURE(Fixture, "constrained_intersection_of_intersections") TEST_CASE_FIXTURE(BuiltinsFixture, "constrained_intersection_of_intersections")
{ {
ScopedFastFlag flags[] = { ScopedFastFlag flags[] = {
{"LuauLowerBoundsCalculation", true}, {"LuauLowerBoundsCalculation", true},
@ -951,7 +951,7 @@ TEST_CASE_FIXTURE(Fixture, "nested_table_normalization_with_non_table__no_ice")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "visiting_a_type_twice_is_not_considered_normal") TEST_CASE_FIXTURE(BuiltinsFixture, "visiting_a_type_twice_is_not_considered_normal")
{ {
ScopedFastFlag sff{"LuauLowerBoundsCalculation", true}; ScopedFastFlag sff{"LuauLowerBoundsCalculation", true};
@ -976,7 +976,6 @@ TEST_CASE_FIXTURE(Fixture, "fuzz_failure_instersection_combine_must_follow")
{ {
ScopedFastFlag flags[] = { ScopedFastFlag flags[] = {
{"LuauLowerBoundsCalculation", true}, {"LuauLowerBoundsCalculation", true},
{"LuauNormalizeCombineIntersectionFix", true},
}; };
CheckResult result = check(R"( CheckResult result = check(R"(

View File

@ -1618,8 +1618,6 @@ TEST_CASE_FIXTURE(Fixture, "end_extent_doesnt_consume_comments")
TEST_CASE_FIXTURE(Fixture, "end_extent_doesnt_consume_comments_even_with_capture") TEST_CASE_FIXTURE(Fixture, "end_extent_doesnt_consume_comments_even_with_capture")
{ {
ScopedFastFlag luauParseLocationIgnoreCommentSkipInCapture{"LuauParseLocationIgnoreCommentSkipInCapture", true};
// Same should hold when comments are captured // Same should hold when comments are captured
ParseOptions opts; ParseOptions opts;
opts.captureComments = true; opts.captureComments = true;

View File

@ -17,7 +17,7 @@ using namespace Luau;
LUAU_FASTFLAG(LuauLowerBoundsCalculation); LUAU_FASTFLAG(LuauLowerBoundsCalculation);
struct LimitFixture : Fixture struct LimitFixture : BuiltinsFixture
{ {
#if defined(_NOOPT) || defined(_DEBUG) #if defined(_NOOPT) || defined(_DEBUG)
ScopedFastInt LuauTypeInferRecursionLimit{"LuauTypeInferRecursionLimit", 100}; ScopedFastInt LuauTypeInferRecursionLimit{"LuauTypeInferRecursionLimit", 100};

View File

@ -224,7 +224,7 @@ n1 -> n4 [label="typePackParam"];
(void)toDot(requireType("a")); (void)toDot(requireType("a"));
} }
TEST_CASE_FIXTURE(Fixture, "metatable") TEST_CASE_FIXTURE(BuiltinsFixture, "metatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a: typeof(setmetatable({}, {})) local a: typeof(setmetatable({}, {}))

View File

@ -60,7 +60,7 @@ TEST_CASE_FIXTURE(Fixture, "named_table")
CHECK_EQ("TheTable", toString(&table)); CHECK_EQ("TheTable", toString(&table));
} }
TEST_CASE_FIXTURE(Fixture, "exhaustive_toString_of_cyclic_table") TEST_CASE_FIXTURE(BuiltinsFixture, "exhaustive_toString_of_cyclic_table")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -338,7 +338,7 @@ TEST_CASE_FIXTURE(Fixture, "toStringDetailed")
REQUIRE_EQ("c", toString(params[2], opts)); REQUIRE_EQ("c", toString(params[2], opts));
} }
TEST_CASE_FIXTURE(Fixture, "toStringDetailed2") TEST_CASE_FIXTURE(BuiltinsFixture, "toStringDetailed2")
{ {
ScopedFastFlag sff{"LuauUnsealedTableLiteral", true}; ScopedFastFlag sff{"LuauUnsealedTableLiteral", true};

View File

@ -279,7 +279,7 @@ TEST_CASE_FIXTURE(Fixture, "stringify_optional_parameterized_alias")
CHECK_EQ("Node<T>", toString(e->wantedType)); CHECK_EQ("Node<T>", toString(e->wantedType));
} }
TEST_CASE_FIXTURE(Fixture, "general_require_multi_assign") TEST_CASE_FIXTURE(BuiltinsFixture, "general_require_multi_assign")
{ {
fileResolver.source["workspace/A"] = R"( fileResolver.source["workspace/A"] = R"(
export type myvec2 = {x: number, y: number} export type myvec2 = {x: number, y: number}
@ -317,7 +317,7 @@ TEST_CASE_FIXTURE(Fixture, "general_require_multi_assign")
REQUIRE(bType->props.size() == 3); REQUIRE(bType->props.size() == 3);
} }
TEST_CASE_FIXTURE(Fixture, "type_alias_import_mutation") TEST_CASE_FIXTURE(BuiltinsFixture, "type_alias_import_mutation")
{ {
CheckResult result = check("type t10<x> = typeof(table)"); CheckResult result = check("type t10<x> = typeof(table)");
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
@ -385,7 +385,7 @@ type Cool = typeof(c)
CHECK_EQ(ttv->name, "Cool"); CHECK_EQ(ttv->name, "Cool");
} }
TEST_CASE_FIXTURE(Fixture, "type_alias_of_an_imported_recursive_type") TEST_CASE_FIXTURE(BuiltinsFixture, "type_alias_of_an_imported_recursive_type")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
export type X = { a: number, b: X? } export type X = { a: number, b: X? }
@ -410,7 +410,7 @@ type X = Import.X
CHECK_EQ(follow(*ty1), follow(*ty2)); CHECK_EQ(follow(*ty1), follow(*ty2));
} }
TEST_CASE_FIXTURE(Fixture, "type_alias_of_an_imported_recursive_generic_type") TEST_CASE_FIXTURE(BuiltinsFixture, "type_alias_of_an_imported_recursive_generic_type")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
export type X<T, U> = { a: T, b: U, C: X<T, U>? } export type X<T, U> = { a: T, b: U, C: X<T, U>? }
@ -564,7 +564,7 @@ TEST_CASE_FIXTURE(Fixture, "non_recursive_aliases_that_reuse_a_generic_name")
* *
* We solved this by ascribing a unique subLevel to each prototyped alias. * We solved this by ascribing a unique subLevel to each prototyped alias.
*/ */
TEST_CASE_FIXTURE(Fixture, "do_not_quantify_unresolved_aliases") TEST_CASE_FIXTURE(BuiltinsFixture, "do_not_quantify_unresolved_aliases")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict

View File

@ -528,7 +528,7 @@ TEST_CASE_FIXTURE(Fixture, "cloned_interface_maintains_pointers_between_definiti
CHECK_EQ(recordType, bType); CHECK_EQ(recordType, bType);
} }
TEST_CASE_FIXTURE(Fixture, "use_type_required_from_another_file") TEST_CASE_FIXTURE(BuiltinsFixture, "use_type_required_from_another_file")
{ {
addGlobalBinding(frontend.typeChecker, "script", frontend.typeChecker.anyType, "@test"); addGlobalBinding(frontend.typeChecker, "script", frontend.typeChecker.anyType, "@test");
@ -554,7 +554,7 @@ TEST_CASE_FIXTURE(Fixture, "use_type_required_from_another_file")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "cannot_use_nonexported_type") TEST_CASE_FIXTURE(BuiltinsFixture, "cannot_use_nonexported_type")
{ {
addGlobalBinding(frontend.typeChecker, "script", frontend.typeChecker.anyType, "@test"); addGlobalBinding(frontend.typeChecker, "script", frontend.typeChecker.anyType, "@test");
@ -580,7 +580,7 @@ TEST_CASE_FIXTURE(Fixture, "cannot_use_nonexported_type")
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
} }
TEST_CASE_FIXTURE(Fixture, "builtin_types_are_not_exported") TEST_CASE_FIXTURE(BuiltinsFixture, "builtin_types_are_not_exported")
{ {
addGlobalBinding(frontend.typeChecker, "script", frontend.typeChecker.anyType, "@test"); addGlobalBinding(frontend.typeChecker, "script", frontend.typeChecker.anyType, "@test");
@ -676,7 +676,7 @@ TEST_CASE_FIXTURE(Fixture, "luau_ice_is_not_special_without_the_flag")
)"); )");
} }
TEST_CASE_FIXTURE(Fixture, "luau_print_is_magic_if_the_flag_is_set") TEST_CASE_FIXTURE(BuiltinsFixture, "luau_print_is_magic_if_the_flag_is_set")
{ {
// Luau::resetPrintLine(); // Luau::resetPrintLine();
ScopedFastFlag sffs{"DebugLuauMagicTypes", true}; ScopedFastFlag sffs{"DebugLuauMagicTypes", true};

View File

@ -237,7 +237,7 @@ TEST_CASE_FIXTURE(Fixture, "chain_calling_error_type_yields_error")
CHECK_EQ("*unknown*", toString(requireType("a"))); CHECK_EQ("*unknown*", toString(requireType("a")));
} }
TEST_CASE_FIXTURE(Fixture, "replace_every_free_type_when_unifying_a_complex_function_with_any") TEST_CASE_FIXTURE(BuiltinsFixture, "replace_every_free_type_when_unifying_a_complex_function_with_any")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a: any local a: any
@ -285,7 +285,7 @@ end
LUAU_REQUIRE_ERRORS(result); LUAU_REQUIRE_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "metatable_of_any_can_be_a_table") TEST_CASE_FIXTURE(BuiltinsFixture, "metatable_of_any_can_be_a_table")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict

View File

@ -12,7 +12,7 @@ LUAU_FASTFLAG(LuauLowerBoundsCalculation);
TEST_SUITE_BEGIN("BuiltinTests"); TEST_SUITE_BEGIN("BuiltinTests");
TEST_CASE_FIXTURE(Fixture, "math_things_are_defined") TEST_CASE_FIXTURE(BuiltinsFixture, "math_things_are_defined")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a00 = math.frexp local a00 = math.frexp
@ -50,7 +50,7 @@ TEST_CASE_FIXTURE(Fixture, "math_things_are_defined")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "next_iterator_should_infer_types_and_type_check") TEST_CASE_FIXTURE(BuiltinsFixture, "next_iterator_should_infer_types_and_type_check")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a: string, b: number = next({ 1 }) local a: string, b: number = next({ 1 })
@ -63,7 +63,7 @@ TEST_CASE_FIXTURE(Fixture, "next_iterator_should_infer_types_and_type_check")
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
} }
TEST_CASE_FIXTURE(Fixture, "pairs_iterator_should_infer_types_and_type_check") TEST_CASE_FIXTURE(BuiltinsFixture, "pairs_iterator_should_infer_types_and_type_check")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
type Map<K, V> = { [K]: V } type Map<K, V> = { [K]: V }
@ -75,7 +75,7 @@ TEST_CASE_FIXTURE(Fixture, "pairs_iterator_should_infer_types_and_type_check")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "ipairs_iterator_should_infer_types_and_type_check") TEST_CASE_FIXTURE(BuiltinsFixture, "ipairs_iterator_should_infer_types_and_type_check")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
type Map<K, V> = { [K]: V } type Map<K, V> = { [K]: V }
@ -87,7 +87,7 @@ TEST_CASE_FIXTURE(Fixture, "ipairs_iterator_should_infer_types_and_type_check")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_dot_remove_optionally_returns_generic") TEST_CASE_FIXTURE(BuiltinsFixture, "table_dot_remove_optionally_returns_generic")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = { 1 } local t = { 1 }
@ -98,7 +98,7 @@ TEST_CASE_FIXTURE(Fixture, "table_dot_remove_optionally_returns_generic")
CHECK_EQ(toString(requireType("n")), "number?"); CHECK_EQ(toString(requireType("n")), "number?");
} }
TEST_CASE_FIXTURE(Fixture, "table_concat_returns_string") TEST_CASE_FIXTURE(BuiltinsFixture, "table_concat_returns_string")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local r = table.concat({1,2,3,4}, ",", 2); local r = table.concat({1,2,3,4}, ",", 2);
@ -108,7 +108,7 @@ TEST_CASE_FIXTURE(Fixture, "table_concat_returns_string")
CHECK_EQ(*typeChecker.stringType, *requireType("r")); CHECK_EQ(*typeChecker.stringType, *requireType("r"));
} }
TEST_CASE_FIXTURE(Fixture, "sort") TEST_CASE_FIXTURE(BuiltinsFixture, "sort")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {1, 2, 3}; local t = {1, 2, 3};
@ -118,7 +118,7 @@ TEST_CASE_FIXTURE(Fixture, "sort")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "sort_with_predicate") TEST_CASE_FIXTURE(BuiltinsFixture, "sort_with_predicate")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -130,7 +130,7 @@ TEST_CASE_FIXTURE(Fixture, "sort_with_predicate")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "sort_with_bad_predicate") TEST_CASE_FIXTURE(BuiltinsFixture, "sort_with_bad_predicate")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -140,6 +140,12 @@ TEST_CASE_FIXTURE(Fixture, "sort_with_bad_predicate")
)"); )");
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
CHECK_EQ(R"(Type '(number, number) -> boolean' could not be converted into '((a, a) -> boolean)?'
caused by:
None of the union options are compatible. For example: Type '(number, number) -> boolean' could not be converted into '(a, a) -> boolean'
caused by:
Argument #1 type is not compatible. Type 'string' could not be converted into 'number')",
toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "strings_have_methods") TEST_CASE_FIXTURE(Fixture, "strings_have_methods")
@ -152,7 +158,7 @@ TEST_CASE_FIXTURE(Fixture, "strings_have_methods")
CHECK_EQ(*typeChecker.stringType, *requireType("s")); CHECK_EQ(*typeChecker.stringType, *requireType("s"));
} }
TEST_CASE_FIXTURE(Fixture, "math_max_variatic") TEST_CASE_FIXTURE(BuiltinsFixture, "math_max_variatic")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local n = math.max(1,2,3,4,5,6,7,8,9,0) local n = math.max(1,2,3,4,5,6,7,8,9,0)
@ -162,16 +168,17 @@ TEST_CASE_FIXTURE(Fixture, "math_max_variatic")
CHECK_EQ(*typeChecker.numberType, *requireType("n")); CHECK_EQ(*typeChecker.numberType, *requireType("n"));
} }
TEST_CASE_FIXTURE(Fixture, "math_max_checks_for_numbers") TEST_CASE_FIXTURE(BuiltinsFixture, "math_max_checks_for_numbers")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local n = math.max(1,2,"3") local n = math.max(1,2,"3")
)"); )");
CHECK(!result.errors.empty()); CHECK(!result.errors.empty());
CHECK_EQ("Type 'string' could not be converted into 'number'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "builtin_tables_sealed") TEST_CASE_FIXTURE(BuiltinsFixture, "builtin_tables_sealed")
{ {
CheckResult result = check(R"LUA( CheckResult result = check(R"LUA(
local b = bit32 local b = bit32
@ -183,7 +190,7 @@ TEST_CASE_FIXTURE(Fixture, "builtin_tables_sealed")
CHECK_EQ(bit32t->state, TableState::Sealed); CHECK_EQ(bit32t->state, TableState::Sealed);
} }
TEST_CASE_FIXTURE(Fixture, "lua_51_exported_globals_all_exist") TEST_CASE_FIXTURE(BuiltinsFixture, "lua_51_exported_globals_all_exist")
{ {
// Extracted from lua5.1 // Extracted from lua5.1
CheckResult result = check(R"( CheckResult result = check(R"(
@ -340,7 +347,7 @@ TEST_CASE_FIXTURE(Fixture, "lua_51_exported_globals_all_exist")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "setmetatable_unpacks_arg_types_correctly") TEST_CASE_FIXTURE(BuiltinsFixture, "setmetatable_unpacks_arg_types_correctly")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
setmetatable({}, setmetatable({}, {})) setmetatable({}, setmetatable({}, {}))
@ -348,7 +355,7 @@ TEST_CASE_FIXTURE(Fixture, "setmetatable_unpacks_arg_types_correctly")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_insert_correctly_infers_type_of_array_2_args_overload") TEST_CASE_FIXTURE(BuiltinsFixture, "table_insert_correctly_infers_type_of_array_2_args_overload")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {} local t = {}
@ -360,7 +367,7 @@ TEST_CASE_FIXTURE(Fixture, "table_insert_correctly_infers_type_of_array_2_args_o
CHECK_EQ(typeChecker.stringType, requireType("s")); CHECK_EQ(typeChecker.stringType, requireType("s"));
} }
TEST_CASE_FIXTURE(Fixture, "table_insert_correctly_infers_type_of_array_3_args_overload") TEST_CASE_FIXTURE(BuiltinsFixture, "table_insert_correctly_infers_type_of_array_3_args_overload")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {} local t = {}
@ -372,7 +379,7 @@ TEST_CASE_FIXTURE(Fixture, "table_insert_correctly_infers_type_of_array_3_args_o
CHECK_EQ("string", toString(requireType("s"))); CHECK_EQ("string", toString(requireType("s")));
} }
TEST_CASE_FIXTURE(Fixture, "table_pack") TEST_CASE_FIXTURE(BuiltinsFixture, "table_pack")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = table.pack(1, "foo", true) local t = table.pack(1, "foo", true)
@ -382,7 +389,7 @@ TEST_CASE_FIXTURE(Fixture, "table_pack")
CHECK_EQ("{| [number]: boolean | number | string, n: number |}", toString(requireType("t"))); CHECK_EQ("{| [number]: boolean | number | string, n: number |}", toString(requireType("t")));
} }
TEST_CASE_FIXTURE(Fixture, "table_pack_variadic") TEST_CASE_FIXTURE(BuiltinsFixture, "table_pack_variadic")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -397,7 +404,7 @@ local t = table.pack(f())
CHECK_EQ("{| [number]: number | string, n: number |}", toString(requireType("t"))); CHECK_EQ("{| [number]: number | string, n: number |}", toString(requireType("t")));
} }
TEST_CASE_FIXTURE(Fixture, "table_pack_reduce") TEST_CASE_FIXTURE(BuiltinsFixture, "table_pack_reduce")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = table.pack(1, 2, true) local t = table.pack(1, 2, true)
@ -414,7 +421,7 @@ TEST_CASE_FIXTURE(Fixture, "table_pack_reduce")
CHECK_EQ("{| [number]: string, n: number |}", toString(requireType("t"))); CHECK_EQ("{| [number]: string, n: number |}", toString(requireType("t")));
} }
TEST_CASE_FIXTURE(Fixture, "gcinfo") TEST_CASE_FIXTURE(BuiltinsFixture, "gcinfo")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local n = gcinfo() local n = gcinfo()
@ -424,12 +431,12 @@ TEST_CASE_FIXTURE(Fixture, "gcinfo")
CHECK_EQ(*typeChecker.numberType, *requireType("n")); CHECK_EQ(*typeChecker.numberType, *requireType("n"));
} }
TEST_CASE_FIXTURE(Fixture, "getfenv") TEST_CASE_FIXTURE(BuiltinsFixture, "getfenv")
{ {
LUAU_REQUIRE_NO_ERRORS(check("getfenv(1)")); LUAU_REQUIRE_NO_ERRORS(check("getfenv(1)"));
} }
TEST_CASE_FIXTURE(Fixture, "os_time_takes_optional_date_table") TEST_CASE_FIXTURE(BuiltinsFixture, "os_time_takes_optional_date_table")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local n1 = os.time() local n1 = os.time()
@ -443,7 +450,7 @@ TEST_CASE_FIXTURE(Fixture, "os_time_takes_optional_date_table")
CHECK_EQ(*typeChecker.numberType, *requireType("n3")); CHECK_EQ(*typeChecker.numberType, *requireType("n3"));
} }
TEST_CASE_FIXTURE(Fixture, "thread_is_a_type") TEST_CASE_FIXTURE(BuiltinsFixture, "thread_is_a_type")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local co = coroutine.create(function() end) local co = coroutine.create(function() end)
@ -453,7 +460,7 @@ TEST_CASE_FIXTURE(Fixture, "thread_is_a_type")
CHECK_EQ(*typeChecker.threadType, *requireType("co")); CHECK_EQ(*typeChecker.threadType, *requireType("co"));
} }
TEST_CASE_FIXTURE(Fixture, "coroutine_resume_anything_goes") TEST_CASE_FIXTURE(BuiltinsFixture, "coroutine_resume_anything_goes")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function nifty(x, y) local function nifty(x, y)
@ -471,7 +478,7 @@ TEST_CASE_FIXTURE(Fixture, "coroutine_resume_anything_goes")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "coroutine_wrap_anything_goes") TEST_CASE_FIXTURE(BuiltinsFixture, "coroutine_wrap_anything_goes")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -490,7 +497,7 @@ TEST_CASE_FIXTURE(Fixture, "coroutine_wrap_anything_goes")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "setmetatable_should_not_mutate_persisted_types") TEST_CASE_FIXTURE(BuiltinsFixture, "setmetatable_should_not_mutate_persisted_types")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local string = string local string = string
@ -505,7 +512,7 @@ TEST_CASE_FIXTURE(Fixture, "setmetatable_should_not_mutate_persisted_types")
REQUIRE(ttv); REQUIRE(ttv);
} }
TEST_CASE_FIXTURE(Fixture, "string_format_arg_types_inference") TEST_CASE_FIXTURE(BuiltinsFixture, "string_format_arg_types_inference")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -518,7 +525,7 @@ TEST_CASE_FIXTURE(Fixture, "string_format_arg_types_inference")
CHECK_EQ("(number, number, string) -> string", toString(requireType("f"))); CHECK_EQ("(number, number, string) -> string", toString(requireType("f")));
} }
TEST_CASE_FIXTURE(Fixture, "string_format_arg_count_mismatch") TEST_CASE_FIXTURE(BuiltinsFixture, "string_format_arg_count_mismatch")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -534,7 +541,7 @@ TEST_CASE_FIXTURE(Fixture, "string_format_arg_count_mismatch")
CHECK_EQ(result.errors[2].location.begin.line, 4); CHECK_EQ(result.errors[2].location.begin.line, 4);
} }
TEST_CASE_FIXTURE(Fixture, "string_format_correctly_ordered_types") TEST_CASE_FIXTURE(BuiltinsFixture, "string_format_correctly_ordered_types")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -548,7 +555,7 @@ TEST_CASE_FIXTURE(Fixture, "string_format_correctly_ordered_types")
CHECK_EQ(tm->givenType, typeChecker.numberType); CHECK_EQ(tm->givenType, typeChecker.numberType);
} }
TEST_CASE_FIXTURE(Fixture, "xpcall") TEST_CASE_FIXTURE(BuiltinsFixture, "xpcall")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -564,7 +571,7 @@ TEST_CASE_FIXTURE(Fixture, "xpcall")
CHECK_EQ("boolean", toString(requireType("c"))); CHECK_EQ("boolean", toString(requireType("c")));
} }
TEST_CASE_FIXTURE(Fixture, "see_thru_select") TEST_CASE_FIXTURE(BuiltinsFixture, "see_thru_select")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a:number, b:boolean = select(2,"hi", 10, true) local a:number, b:boolean = select(2,"hi", 10, true)
@ -573,7 +580,7 @@ TEST_CASE_FIXTURE(Fixture, "see_thru_select")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "see_thru_select_count") TEST_CASE_FIXTURE(BuiltinsFixture, "see_thru_select_count")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a = select("#","hi", 10, true) local a = select("#","hi", 10, true)
@ -583,7 +590,7 @@ TEST_CASE_FIXTURE(Fixture, "see_thru_select_count")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "select_with_decimal_argument_is_rounded_down") TEST_CASE_FIXTURE(BuiltinsFixture, "select_with_decimal_argument_is_rounded_down")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a: number, b: boolean = select(2.9, "foo", 1, true) local a: number, b: boolean = select(2.9, "foo", 1, true)
@ -608,7 +615,7 @@ TEST_CASE_FIXTURE(Fixture, "bad_select_should_not_crash")
CHECK_LE(0, result.errors.size()); CHECK_LE(0, result.errors.size());
} }
TEST_CASE_FIXTURE(Fixture, "select_way_out_of_range") TEST_CASE_FIXTURE(BuiltinsFixture, "select_way_out_of_range")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
select(5432598430953240958) select(5432598430953240958)
@ -619,7 +626,7 @@ TEST_CASE_FIXTURE(Fixture, "select_way_out_of_range")
CHECK_EQ("bad argument #1 to select (index out of range)", toString(result.errors[0])); CHECK_EQ("bad argument #1 to select (index out of range)", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "select_slightly_out_of_range") TEST_CASE_FIXTURE(BuiltinsFixture, "select_slightly_out_of_range")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
select(3, "a", 1) select(3, "a", 1)
@ -630,7 +637,7 @@ TEST_CASE_FIXTURE(Fixture, "select_slightly_out_of_range")
CHECK_EQ("bad argument #1 to select (index out of range)", toString(result.errors[0])); CHECK_EQ("bad argument #1 to select (index out of range)", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "select_with_variadic_typepack_tail") TEST_CASE_FIXTURE(BuiltinsFixture, "select_with_variadic_typepack_tail")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -649,7 +656,7 @@ TEST_CASE_FIXTURE(Fixture, "select_with_variadic_typepack_tail")
CHECK_EQ("any", toString(requireType("quux"))); CHECK_EQ("any", toString(requireType("quux")));
} }
TEST_CASE_FIXTURE(Fixture, "select_with_variadic_typepack_tail_and_string_head") TEST_CASE_FIXTURE(BuiltinsFixture, "select_with_variadic_typepack_tail_and_string_head")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -703,7 +710,7 @@ TEST_CASE_FIXTURE(Fixture, "string_format_use_correct_argument2")
CHECK_EQ("Type 'number' could not be converted into 'string'", toString(result.errors[1])); CHECK_EQ("Type 'number' could not be converted into 'string'", toString(result.errors[1]));
} }
TEST_CASE_FIXTURE(Fixture, "debug_traceback_is_crazy") TEST_CASE_FIXTURE(BuiltinsFixture, "debug_traceback_is_crazy")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local co: thread = ... local co: thread = ...
@ -720,7 +727,7 @@ debug.traceback(co, "msg", 1)
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "debug_info_is_crazy") TEST_CASE_FIXTURE(BuiltinsFixture, "debug_info_is_crazy")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local co: thread, f: ()->() = ... local co: thread, f: ()->() = ...
@ -734,7 +741,7 @@ debug.info(f, "n")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "aliased_string_format") TEST_CASE_FIXTURE(BuiltinsFixture, "aliased_string_format")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local fmt = string.format local fmt = string.format
@ -745,7 +752,7 @@ TEST_CASE_FIXTURE(Fixture, "aliased_string_format")
CHECK_EQ("Type 'string' could not be converted into 'number'", toString(result.errors[0])); CHECK_EQ("Type 'string' could not be converted into 'number'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "string_lib_self_noself") TEST_CASE_FIXTURE(BuiltinsFixture, "string_lib_self_noself")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -764,7 +771,7 @@ TEST_CASE_FIXTURE(Fixture, "string_lib_self_noself")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "gmatch_definition") TEST_CASE_FIXTURE(BuiltinsFixture, "gmatch_definition")
{ {
CheckResult result = check(R"_( CheckResult result = check(R"_(
local a, b, c = ("hey"):gmatch("(.)(.)(.)")() local a, b, c = ("hey"):gmatch("(.)(.)(.)")()
@ -777,7 +784,7 @@ end
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "select_on_variadic") TEST_CASE_FIXTURE(BuiltinsFixture, "select_on_variadic")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function f(): (number, ...(boolean | number)) local function f(): (number, ...(boolean | number))
@ -793,7 +800,7 @@ TEST_CASE_FIXTURE(Fixture, "select_on_variadic")
CHECK_EQ("any", toString(requireType("c"))); CHECK_EQ("any", toString(requireType("c")));
} }
TEST_CASE_FIXTURE(Fixture, "string_format_report_all_type_errors_at_correct_positions") TEST_CASE_FIXTURE(BuiltinsFixture, "string_format_report_all_type_errors_at_correct_positions")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
("%s%d%s"):format(1, "hello", true) ("%s%d%s"):format(1, "hello", true)
@ -825,7 +832,7 @@ TEST_CASE_FIXTURE(Fixture, "string_format_report_all_type_errors_at_correct_posi
CHECK_EQ(TypeErrorData(TypeMismatch{stringType, booleanType}), result.errors[5].data); CHECK_EQ(TypeErrorData(TypeMismatch{stringType, booleanType}), result.errors[5].data);
} }
TEST_CASE_FIXTURE(Fixture, "tonumber_returns_optional_number_type") TEST_CASE_FIXTURE(BuiltinsFixture, "tonumber_returns_optional_number_type")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -836,7 +843,7 @@ TEST_CASE_FIXTURE(Fixture, "tonumber_returns_optional_number_type")
CHECK_EQ("Type 'number?' could not be converted into 'number'", toString(result.errors[0])); CHECK_EQ("Type 'number?' could not be converted into 'number'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "tonumber_returns_optional_number_type2") TEST_CASE_FIXTURE(BuiltinsFixture, "tonumber_returns_optional_number_type2")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -846,7 +853,7 @@ TEST_CASE_FIXTURE(Fixture, "tonumber_returns_optional_number_type2")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "dont_add_definitions_to_persistent_types") TEST_CASE_FIXTURE(BuiltinsFixture, "dont_add_definitions_to_persistent_types")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local f = math.sin local f = math.sin
@ -868,7 +875,7 @@ TEST_CASE_FIXTURE(Fixture, "dont_add_definitions_to_persistent_types")
REQUIRE(gtv->definition); REQUIRE(gtv->definition);
} }
TEST_CASE_FIXTURE(Fixture, "assert_removes_falsy_types") TEST_CASE_FIXTURE(BuiltinsFixture, "assert_removes_falsy_types")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauAssertStripsFalsyTypes", true}, {"LuauAssertStripsFalsyTypes", true},
@ -889,7 +896,7 @@ TEST_CASE_FIXTURE(Fixture, "assert_removes_falsy_types")
CHECK_EQ("((boolean | number)?) -> boolean | number", toString(requireType("f"))); CHECK_EQ("((boolean | number)?) -> boolean | number", toString(requireType("f")));
} }
TEST_CASE_FIXTURE(Fixture, "assert_removes_falsy_types2") TEST_CASE_FIXTURE(BuiltinsFixture, "assert_removes_falsy_types2")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauAssertStripsFalsyTypes", true}, {"LuauAssertStripsFalsyTypes", true},
@ -907,7 +914,7 @@ TEST_CASE_FIXTURE(Fixture, "assert_removes_falsy_types2")
CHECK_EQ("((boolean | number)?) -> number | true", toString(requireType("f"))); CHECK_EQ("((boolean | number)?) -> number | true", toString(requireType("f")));
} }
TEST_CASE_FIXTURE(Fixture, "assert_removes_falsy_types_even_from_type_pack_tail_but_only_for_the_first_type") TEST_CASE_FIXTURE(BuiltinsFixture, "assert_removes_falsy_types_even_from_type_pack_tail_but_only_for_the_first_type")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauAssertStripsFalsyTypes", true}, {"LuauAssertStripsFalsyTypes", true},
@ -924,7 +931,7 @@ TEST_CASE_FIXTURE(Fixture, "assert_removes_falsy_types_even_from_type_pack_tail_
CHECK_EQ("(...number?) -> (number, ...number?)", toString(requireType("f"))); CHECK_EQ("(...number?) -> (number, ...number?)", toString(requireType("f")));
} }
TEST_CASE_FIXTURE(Fixture, "assert_returns_false_and_string_iff_it_knows_the_first_argument_cannot_be_truthy") TEST_CASE_FIXTURE(BuiltinsFixture, "assert_returns_false_and_string_iff_it_knows_the_first_argument_cannot_be_truthy")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauAssertStripsFalsyTypes", true}, {"LuauAssertStripsFalsyTypes", true},
@ -941,7 +948,7 @@ TEST_CASE_FIXTURE(Fixture, "assert_returns_false_and_string_iff_it_knows_the_fir
CHECK_EQ("(nil) -> nil", toString(requireType("f"))); CHECK_EQ("(nil) -> nil", toString(requireType("f")));
} }
TEST_CASE_FIXTURE(Fixture, "table_freeze_is_generic") TEST_CASE_FIXTURE(BuiltinsFixture, "table_freeze_is_generic")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t1: {a: number} = {a = 42} local t1: {a: number} = {a = 42}
@ -968,7 +975,7 @@ TEST_CASE_FIXTURE(Fixture, "table_freeze_is_generic")
CHECK_EQ("*unknown*", toString(requireType("d"))); CHECK_EQ("*unknown*", toString(requireType("d")));
} }
TEST_CASE_FIXTURE(Fixture, "set_metatable_needs_arguments") TEST_CASE_FIXTURE(BuiltinsFixture, "set_metatable_needs_arguments")
{ {
ScopedFastFlag sff{"LuauSetMetaTableArgsCheck", true}; ScopedFastFlag sff{"LuauSetMetaTableArgsCheck", true};
CheckResult result = check(R"( CheckResult result = check(R"(
@ -991,7 +998,7 @@ local function f(a: typeof(f)) end
CHECK_EQ("Unknown global 'f'", toString(result.errors[0])); CHECK_EQ("Unknown global 'f'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "no_persistent_typelevel_change") TEST_CASE_FIXTURE(BuiltinsFixture, "no_persistent_typelevel_change")
{ {
TypeId mathTy = requireType(typeChecker.globalScope, "math"); TypeId mathTy = requireType(typeChecker.globalScope, "math");
REQUIRE(mathTy); REQUIRE(mathTy);
@ -1008,7 +1015,7 @@ TEST_CASE_FIXTURE(Fixture, "no_persistent_typelevel_change")
CHECK(ftv->level.subLevel == original.subLevel); CHECK(ftv->level.subLevel == original.subLevel);
} }
TEST_CASE_FIXTURE(Fixture, "global_singleton_types_are_sealed") TEST_CASE_FIXTURE(BuiltinsFixture, "global_singleton_types_are_sealed")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function f(x: string) local function f(x: string)

View File

@ -10,7 +10,7 @@
using namespace Luau; using namespace Luau;
using std::nullopt; using std::nullopt;
struct ClassFixture : Fixture struct ClassFixture : BuiltinsFixture
{ {
ClassFixture() ClassFixture()
{ {

View File

@ -85,7 +85,7 @@ TEST_CASE_FIXTURE(Fixture, "vararg_functions_should_allow_calls_of_any_types_and
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "vararg_function_is_quantified") TEST_CASE_FIXTURE(BuiltinsFixture, "vararg_function_is_quantified")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local T = {} local T = {}
@ -555,7 +555,7 @@ TEST_CASE_FIXTURE(Fixture, "higher_order_function_3")
CHECK(bool(argType->indexer)); CHECK(bool(argType->indexer));
} }
TEST_CASE_FIXTURE(Fixture, "higher_order_function_4") TEST_CASE_FIXTURE(BuiltinsFixture, "higher_order_function_4")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function bottomupmerge(comp, a, b, left, mid, right) function bottomupmerge(comp, a, b, left, mid, right)
@ -620,7 +620,7 @@ TEST_CASE_FIXTURE(Fixture, "higher_order_function_4")
CHECK_EQ(*arg0->indexer->indexResultType, *arg1Args[1]); CHECK_EQ(*arg0->indexer->indexResultType, *arg1Args[1]);
} }
TEST_CASE_FIXTURE(Fixture, "mutual_recursion") TEST_CASE_FIXTURE(BuiltinsFixture, "mutual_recursion")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -639,7 +639,7 @@ TEST_CASE_FIXTURE(Fixture, "mutual_recursion")
dumpErrors(result); dumpErrors(result);
} }
TEST_CASE_FIXTURE(Fixture, "toposort_doesnt_break_mutual_recursion") TEST_CASE_FIXTURE(BuiltinsFixture, "toposort_doesnt_break_mutual_recursion")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -676,7 +676,7 @@ TEST_CASE_FIXTURE(Fixture, "check_function_before_lambda_that_uses_it")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "it_is_ok_to_oversaturate_a_higher_order_function_argument") TEST_CASE_FIXTURE(BuiltinsFixture, "it_is_ok_to_oversaturate_a_higher_order_function_argument")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function onerror() end function onerror() end
@ -794,7 +794,7 @@ TEST_CASE_FIXTURE(Fixture, "calling_function_with_incorrect_argument_type_yields
}})); }}));
} }
TEST_CASE_FIXTURE(Fixture, "calling_function_with_anytypepack_doesnt_leak_free_types") TEST_CASE_FIXTURE(BuiltinsFixture, "calling_function_with_anytypepack_doesnt_leak_free_types")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauReturnTypeInferenceInNonstrict", true}, {"LuauReturnTypeInferenceInNonstrict", true},
@ -966,7 +966,7 @@ TEST_CASE_FIXTURE(Fixture, "return_type_by_overload")
CHECK_EQ("string", toString(requireType("z"))); CHECK_EQ("string", toString(requireType("z")));
} }
TEST_CASE_FIXTURE(Fixture, "infer_anonymous_function_arguments") TEST_CASE_FIXTURE(BuiltinsFixture, "infer_anonymous_function_arguments")
{ {
// Simple direct arg to arg propagation // Simple direct arg to arg propagation
CheckResult result = check(R"( CheckResult result = check(R"(
@ -1068,7 +1068,7 @@ f(function(x) return x * 2 end)
} }
} }
TEST_CASE_FIXTURE(Fixture, "infer_anonymous_function_arguments") TEST_CASE_FIXTURE(BuiltinsFixture, "infer_anonymous_function_arguments")
{ {
// Simple direct arg to arg propagation // Simple direct arg to arg propagation
CheckResult result = check(R"( CheckResult result = check(R"(
@ -1287,10 +1287,8 @@ caused by:
Return #2 type is not compatible. Type 'string' could not be converted into 'boolean')"); Return #2 type is not compatible. Type 'string' could not be converted into 'boolean')");
} }
TEST_CASE_FIXTURE(Fixture, "function_decl_quantify_right_type") TEST_CASE_FIXTURE(BuiltinsFixture, "function_decl_quantify_right_type")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
fileResolver.source["game/isAMagicMock"] = R"( fileResolver.source["game/isAMagicMock"] = R"(
--!nonstrict --!nonstrict
return function(value) return function(value)
@ -1311,10 +1309,8 @@ end
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "function_decl_non_self_sealed_overwrite") TEST_CASE_FIXTURE(BuiltinsFixture, "function_decl_non_self_sealed_overwrite")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
CheckResult result = check(R"( CheckResult result = check(R"(
function string.len(): number function string.len(): number
return 1 return 1
@ -1333,11 +1329,8 @@ print(string.len('hello'))
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "function_decl_non_self_sealed_overwrite_2") TEST_CASE_FIXTURE(BuiltinsFixture, "function_decl_non_self_sealed_overwrite_2")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
ScopedFastFlag inferStatFunction{"LuauInferStatFunction", true};
CheckResult result = check(R"( CheckResult result = check(R"(
local t: { f: ((x: number) -> number)? } = {} local t: { f: ((x: number) -> number)? } = {}
@ -1477,11 +1470,8 @@ TEST_CASE_FIXTURE(Fixture, "inferred_higher_order_functions_are_quantified_at_th
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "function_decl_non_self_unsealed_overwrite") TEST_CASE_FIXTURE(BuiltinsFixture, "function_decl_non_self_unsealed_overwrite")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
ScopedFastFlag inferStatFunction{"LuauInferStatFunction", true};
CheckResult result = check(R"( CheckResult result = check(R"(
local t = { f = nil :: ((x: number) -> number)? } local t = { f = nil :: ((x: number) -> number)? }
@ -1518,8 +1508,6 @@ TEST_CASE_FIXTURE(Fixture, "strict_mode_ok_with_missing_arguments")
TEST_CASE_FIXTURE(Fixture, "function_statement_sealed_table_assignment_through_indexer") TEST_CASE_FIXTURE(Fixture, "function_statement_sealed_table_assignment_through_indexer")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
CheckResult result = check(R"( CheckResult result = check(R"(
local t: {[string]: () -> number} = {} local t: {[string]: () -> number} = {}
@ -1580,7 +1568,7 @@ wrapper(test)
CHECK(acm->isVariadic); CHECK(acm->isVariadic);
} }
TEST_CASE_FIXTURE(Fixture, "too_few_arguments_variadic_generic2") TEST_CASE_FIXTURE(BuiltinsFixture, "too_few_arguments_variadic_generic2")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function test(a: number, b: string, ...) function test(a: number, b: string, ...)

View File

@ -67,7 +67,7 @@ TEST_CASE_FIXTURE(Fixture, "local_vars_can_be_polytypes")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "inferred_local_vars_can_be_polytypes") TEST_CASE_FIXTURE(BuiltinsFixture, "inferred_local_vars_can_be_polytypes")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function id(x) return x end local function id(x) return x end
@ -79,7 +79,7 @@ TEST_CASE_FIXTURE(Fixture, "inferred_local_vars_can_be_polytypes")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "local_vars_can_be_instantiated_polytypes") TEST_CASE_FIXTURE(BuiltinsFixture, "local_vars_can_be_instantiated_polytypes")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function id(x) return x end local function id(x) return x end
@ -609,7 +609,7 @@ TEST_CASE_FIXTURE(Fixture, "typefuns_sharing_types")
CHECK(requireType("y1") == requireType("y2")); CHECK(requireType("y1") == requireType("y2"));
} }
TEST_CASE_FIXTURE(Fixture, "bound_tables_do_not_clone_original_fields") TEST_CASE_FIXTURE(BuiltinsFixture, "bound_tables_do_not_clone_original_fields")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local exports = {} local exports = {}
@ -675,7 +675,7 @@ local d: D = c
R"(Type '() -> ()' could not be converted into '<T...>() -> ()'; different number of generic type pack parameters)"); R"(Type '() -> ()' could not be converted into '<T...>() -> ()'; different number of generic type pack parameters)");
} }
TEST_CASE_FIXTURE(Fixture, "generic_functions_dont_cache_type_parameters") TEST_CASE_FIXTURE(BuiltinsFixture, "generic_functions_dont_cache_type_parameters")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
-- See https://github.com/Roblox/luau/issues/332 -- See https://github.com/Roblox/luau/issues/332
@ -1013,7 +1013,7 @@ TEST_CASE_FIXTURE(Fixture, "no_stack_overflow_from_quantifying")
CHECK(it != result.errors.end()); CHECK(it != result.errors.end());
} }
TEST_CASE_FIXTURE(Fixture, "infer_generic_function_function_argument") TEST_CASE_FIXTURE(BuiltinsFixture, "infer_generic_function_function_argument")
{ {
ScopedFastFlag sff{"LuauUnsealedTableLiteral", true}; ScopedFastFlag sff{"LuauUnsealedTableLiteral", true};
@ -1078,7 +1078,7 @@ TEST_CASE_FIXTURE(Fixture, "infer_generic_function_function_argument_overloaded"
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "infer_generic_lib_function_function_argument") TEST_CASE_FIXTURE(BuiltinsFixture, "infer_generic_lib_function_function_argument")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a = {{x=4}, {x=7}, {x=1}} local a = {{x=4}, {x=7}, {x=1}}

View File

@ -316,8 +316,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")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
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 }
@ -351,8 +349,6 @@ caused by:
TEST_CASE_FIXTURE(Fixture, "table_write_sealed_indirect") TEST_CASE_FIXTURE(Fixture, "table_write_sealed_indirect")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
// After normalization, previous 'table_intersection_write_sealed_indirect' is identical to this one // After normalization, previous 'table_intersection_write_sealed_indirect' is identical to this one
CheckResult result = check(R"( CheckResult result = check(R"(
type XY = { x: (number) -> number, y: (string) -> string } type XY = { x: (number) -> number, y: (string) -> string }
@ -375,7 +371,7 @@ caused by:
CHECK_EQ(toString(result.errors[3]), "Cannot add property 'w' to table 'XY'"); CHECK_EQ(toString(result.errors[3]), "Cannot add property 'w' to table 'XY'");
} }
TEST_CASE_FIXTURE(Fixture, "table_intersection_setmetatable") TEST_CASE_FIXTURE(BuiltinsFixture, "table_intersection_setmetatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t: {} & {} local t: {} & {}

View File

@ -29,7 +29,7 @@ TEST_CASE_FIXTURE(Fixture, "for_loop")
CHECK_EQ(*typeChecker.numberType, *requireType("q")); CHECK_EQ(*typeChecker.numberType, *requireType("q"));
} }
TEST_CASE_FIXTURE(Fixture, "for_in_loop") TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local n local n
@ -46,7 +46,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop")
CHECK_EQ(*typeChecker.stringType, *requireType("s")); CHECK_EQ(*typeChecker.stringType, *requireType("s"));
} }
TEST_CASE_FIXTURE(Fixture, "for_in_loop_with_next") TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop_with_next")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local n local n
@ -90,7 +90,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_should_fail_with_non_function_iterator")
CHECK_EQ("Cannot call non-function string", toString(result.errors[0])); CHECK_EQ("Cannot call non-function string", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "for_in_with_just_one_iterator_is_ok") TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_with_just_one_iterator_is_ok")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function keys(dictionary) local function keys(dictionary)
@ -109,7 +109,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_with_just_one_iterator_is_ok")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "for_in_with_a_custom_iterator_should_type_check") TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_with_a_custom_iterator_should_type_check")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function range(l, h): () -> number local function range(l, h): () -> number
@ -161,7 +161,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_on_non_function")
REQUIRE(get<CannotCallNonFunction>(result.errors[0])); REQUIRE(get<CannotCallNonFunction>(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "for_in_loop_error_on_factory_not_returning_the_right_amount_of_values") TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop_error_on_factory_not_returning_the_right_amount_of_values")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function hasDivisors(value: number, table) local function hasDivisors(value: number, table)
@ -210,7 +210,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_error_on_factory_not_returning_the_right
CHECK_EQ(typeChecker.stringType, tm->givenType); CHECK_EQ(typeChecker.stringType, tm->givenType);
} }
TEST_CASE_FIXTURE(Fixture, "for_in_loop_error_on_iterator_requiring_args_but_none_given") TEST_CASE_FIXTURE(BuiltinsFixture, "for_in_loop_error_on_iterator_requiring_args_but_none_given")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function prime_iter(state, index) function prime_iter(state, index)
@ -288,7 +288,7 @@ TEST_CASE_FIXTURE(Fixture, "repeat_loop_condition_binds_to_its_block")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "symbols_in_repeat_block_should_not_be_visible_beyond_until_condition") TEST_CASE_FIXTURE(BuiltinsFixture, "symbols_in_repeat_block_should_not_be_visible_beyond_until_condition")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
repeat repeat
@ -301,7 +301,7 @@ TEST_CASE_FIXTURE(Fixture, "symbols_in_repeat_block_should_not_be_visible_beyond
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
} }
TEST_CASE_FIXTURE(Fixture, "varlist_declared_by_for_in_loop_should_be_free") TEST_CASE_FIXTURE(BuiltinsFixture, "varlist_declared_by_for_in_loop_should_be_free")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local T = {} local T = {}
@ -316,7 +316,7 @@ TEST_CASE_FIXTURE(Fixture, "varlist_declared_by_for_in_loop_should_be_free")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "properly_infer_iteratee_is_a_free_table") TEST_CASE_FIXTURE(BuiltinsFixture, "properly_infer_iteratee_is_a_free_table")
{ {
// In this case, we cannot know the element type of the table {}. It could be anything. // In this case, we cannot know the element type of the table {}. It could be anything.
// We therefore must initially ascribe a free typevar to iter. // We therefore must initially ascribe a free typevar to iter.
@ -329,7 +329,7 @@ TEST_CASE_FIXTURE(Fixture, "properly_infer_iteratee_is_a_free_table")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "correctly_scope_locals_while") TEST_CASE_FIXTURE(BuiltinsFixture, "correctly_scope_locals_while")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
while true do while true do
@ -346,7 +346,7 @@ TEST_CASE_FIXTURE(Fixture, "correctly_scope_locals_while")
CHECK_EQ(us->name, "a"); CHECK_EQ(us->name, "a");
} }
TEST_CASE_FIXTURE(Fixture, "ipairs_produces_integral_indices") TEST_CASE_FIXTURE(BuiltinsFixture, "ipairs_produces_integral_indices")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local key local key
@ -378,7 +378,7 @@ TEST_CASE_FIXTURE(Fixture, "for_in_loop_where_iteratee_is_free")
)"); )");
} }
TEST_CASE_FIXTURE(Fixture, "unreachable_code_after_infinite_loop") TEST_CASE_FIXTURE(BuiltinsFixture, "unreachable_code_after_infinite_loop")
{ {
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
@ -460,7 +460,7 @@ TEST_CASE_FIXTURE(Fixture, "unreachable_code_after_infinite_loop")
} }
} }
TEST_CASE_FIXTURE(Fixture, "loop_typecheck_crash_on_empty_optional") TEST_CASE_FIXTURE(BuiltinsFixture, "loop_typecheck_crash_on_empty_optional")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {} local t = {}
@ -541,7 +541,7 @@ TEST_CASE_FIXTURE(Fixture, "loop_iter_no_indexer")
CHECK_EQ("Cannot iterate over a table without indexer", ge->message); CHECK_EQ("Cannot iterate over a table without indexer", ge->message);
} }
TEST_CASE_FIXTURE(Fixture, "loop_iter_iter_metamethod") TEST_CASE_FIXTURE(BuiltinsFixture, "loop_iter_iter_metamethod")
{ {
ScopedFastFlag sff{"LuauTypecheckIter", true}; ScopedFastFlag sff{"LuauTypecheckIter", true};

View File

@ -16,7 +16,7 @@ LUAU_FASTFLAG(LuauTableSubtypingVariance2)
TEST_SUITE_BEGIN("TypeInferModules"); TEST_SUITE_BEGIN("TypeInferModules");
TEST_CASE_FIXTURE(Fixture, "require") TEST_CASE_FIXTURE(BuiltinsFixture, "require")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
local function hooty(x: number): string local function hooty(x: number): string
@ -54,7 +54,7 @@ TEST_CASE_FIXTURE(Fixture, "require")
REQUIRE_EQ("number", toString(*hType)); REQUIRE_EQ("number", toString(*hType));
} }
TEST_CASE_FIXTURE(Fixture, "require_types") TEST_CASE_FIXTURE(BuiltinsFixture, "require_types")
{ {
fileResolver.source["workspace/A"] = R"( fileResolver.source["workspace/A"] = R"(
export type Point = {x: number, y: number} export type Point = {x: number, y: number}
@ -69,7 +69,7 @@ TEST_CASE_FIXTURE(Fixture, "require_types")
)"; )";
CheckResult bResult = frontend.check("workspace/B"); CheckResult bResult = frontend.check("workspace/B");
dumpErrors(bResult); LUAU_REQUIRE_NO_ERRORS(bResult);
ModulePtr b = frontend.moduleResolver.modules["workspace/B"]; ModulePtr b = frontend.moduleResolver.modules["workspace/B"];
REQUIRE(b != nullptr); REQUIRE(b != nullptr);
@ -78,7 +78,7 @@ TEST_CASE_FIXTURE(Fixture, "require_types")
REQUIRE_MESSAGE(bool(get<TableTypeVar>(hType)), "Expected table but got " << toString(hType)); REQUIRE_MESSAGE(bool(get<TableTypeVar>(hType)), "Expected table but got " << toString(hType));
} }
TEST_CASE_FIXTURE(Fixture, "require_a_variadic_function") TEST_CASE_FIXTURE(BuiltinsFixture, "require_a_variadic_function")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
local T = {} local T = {}
@ -121,7 +121,7 @@ TEST_CASE_FIXTURE(Fixture, "type_error_of_unknown_qualified_type")
REQUIRE_EQ(result.errors[0], (TypeError{Location{{1, 17}, {1, 40}}, UnknownSymbol{"SomeModule.DoesNotExist"}})); REQUIRE_EQ(result.errors[0], (TypeError{Location{{1, 17}, {1, 40}}, UnknownSymbol{"SomeModule.DoesNotExist"}}));
} }
TEST_CASE_FIXTURE(Fixture, "require_module_that_does_not_export") TEST_CASE_FIXTURE(BuiltinsFixture, "require_module_that_does_not_export")
{ {
const std::string sourceA = R"( const std::string sourceA = R"(
)"; )";
@ -148,7 +148,7 @@ TEST_CASE_FIXTURE(Fixture, "require_module_that_does_not_export")
CHECK_EQ("*unknown*", toString(hootyType)); CHECK_EQ("*unknown*", toString(hootyType));
} }
TEST_CASE_FIXTURE(Fixture, "warn_if_you_try_to_require_a_non_modulescript") TEST_CASE_FIXTURE(BuiltinsFixture, "warn_if_you_try_to_require_a_non_modulescript")
{ {
fileResolver.source["Modules/A"] = ""; fileResolver.source["Modules/A"] = "";
fileResolver.sourceTypes["Modules/A"] = SourceCode::Local; fileResolver.sourceTypes["Modules/A"] = SourceCode::Local;
@ -164,7 +164,7 @@ TEST_CASE_FIXTURE(Fixture, "warn_if_you_try_to_require_a_non_modulescript")
CHECK(get<IllegalRequire>(result.errors[0])); CHECK(get<IllegalRequire>(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "general_require_call_expression") TEST_CASE_FIXTURE(BuiltinsFixture, "general_require_call_expression")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
--!strict --!strict
@ -183,7 +183,7 @@ a = tbl.abc.def
CHECK_EQ("Type 'number' could not be converted into 'string'", toString(result.errors[0])); CHECK_EQ("Type 'number' could not be converted into 'string'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "general_require_type_mismatch") TEST_CASE_FIXTURE(BuiltinsFixture, "general_require_type_mismatch")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
return { def = 4 } return { def = 4 }
@ -219,7 +219,7 @@ return m
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "custom_require_global") TEST_CASE_FIXTURE(BuiltinsFixture, "custom_require_global")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -231,7 +231,7 @@ local crash = require(game.A)
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "require_failed_module") TEST_CASE_FIXTURE(BuiltinsFixture, "require_failed_module")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
return unfortunately() return unfortunately()
@ -267,7 +267,7 @@ function x:Destroy(): () end
LUAU_REQUIRE_ERRORS(result); LUAU_REQUIRE_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "do_not_modify_imported_types_2") TEST_CASE_FIXTURE(BuiltinsFixture, "do_not_modify_imported_types_2")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
export type Type = { x: { a: number } } export type Type = { x: { a: number } }
@ -285,7 +285,7 @@ type Rename = typeof(x.x)
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "do_not_modify_imported_types_3") TEST_CASE_FIXTURE(BuiltinsFixture, "do_not_modify_imported_types_3")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
local y = setmetatable({}, {}) local y = setmetatable({}, {})
@ -304,7 +304,7 @@ type Rename = typeof(x.x)
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "module_type_conflict") TEST_CASE_FIXTURE(BuiltinsFixture, "module_type_conflict")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
export type T = { x: number } export type T = { x: number }
@ -338,7 +338,7 @@ caused by:
} }
} }
TEST_CASE_FIXTURE(Fixture, "module_type_conflict_instantiated") TEST_CASE_FIXTURE(BuiltinsFixture, "module_type_conflict_instantiated")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
export type Wrap<T> = { x: T } export type Wrap<T> = { x: T }

View File

@ -142,7 +142,7 @@ TEST_CASE_FIXTURE(Fixture, "inferring_hundreds_of_self_calls_should_not_suffocat
CHECK_GE(50, module->internalTypes.typeVars.size()); CHECK_GE(50, module->internalTypes.typeVars.size());
} }
TEST_CASE_FIXTURE(Fixture, "object_constructor_can_refer_to_method_of_self") TEST_CASE_FIXTURE(BuiltinsFixture, "object_constructor_can_refer_to_method_of_self")
{ {
// CLI-30902 // CLI-30902
CheckResult result = check(R"( CheckResult result = check(R"(
@ -243,7 +243,7 @@ TEST_CASE_FIXTURE(Fixture, "inferred_methods_of_free_tables_have_the_same_level_
)"); )");
} }
TEST_CASE_FIXTURE(Fixture, "table_oop") TEST_CASE_FIXTURE(BuiltinsFixture, "table_oop")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict

View File

@ -77,7 +77,7 @@ TEST_CASE_FIXTURE(Fixture, "and_or_ternary")
CHECK_EQ(toString(*requireType("s")), "number | string"); CHECK_EQ(toString(*requireType("s")), "number | string");
} }
TEST_CASE_FIXTURE(Fixture, "primitive_arith_no_metatable") TEST_CASE_FIXTURE(BuiltinsFixture, "primitive_arith_no_metatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function add(a: number, b: string) function add(a: number, b: string)
@ -140,7 +140,7 @@ TEST_CASE_FIXTURE(Fixture, "some_primitive_binary_ops")
CHECK_EQ("number", toString(requireType("c"))); CHECK_EQ("number", toString(requireType("c")));
} }
TEST_CASE_FIXTURE(Fixture, "typecheck_overloaded_multiply_that_is_an_intersection") TEST_CASE_FIXTURE(BuiltinsFixture, "typecheck_overloaded_multiply_that_is_an_intersection")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -174,7 +174,7 @@ TEST_CASE_FIXTURE(Fixture, "typecheck_overloaded_multiply_that_is_an_intersectio
CHECK_EQ("Vec3", toString(requireType("e"))); CHECK_EQ("Vec3", toString(requireType("e")));
} }
TEST_CASE_FIXTURE(Fixture, "typecheck_overloaded_multiply_that_is_an_intersection_on_rhs") TEST_CASE_FIXTURE(BuiltinsFixture, "typecheck_overloaded_multiply_that_is_an_intersection_on_rhs")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -245,7 +245,7 @@ TEST_CASE_FIXTURE(Fixture, "cannot_indirectly_compare_types_that_do_not_have_a_m
REQUIRE_EQ(gen->message, "Type a cannot be compared with < because it has no metatable"); REQUIRE_EQ(gen->message, "Type a cannot be compared with < because it has no metatable");
} }
TEST_CASE_FIXTURE(Fixture, "cannot_indirectly_compare_types_that_do_not_offer_overloaded_ordering_operators") TEST_CASE_FIXTURE(BuiltinsFixture, "cannot_indirectly_compare_types_that_do_not_offer_overloaded_ordering_operators")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local M = {} local M = {}
@ -266,7 +266,7 @@ TEST_CASE_FIXTURE(Fixture, "cannot_indirectly_compare_types_that_do_not_offer_ov
REQUIRE_EQ(gen->message, "Table M does not offer metamethod __lt"); REQUIRE_EQ(gen->message, "Table M does not offer metamethod __lt");
} }
TEST_CASE_FIXTURE(Fixture, "cannot_compare_tables_that_do_not_have_the_same_metatable") TEST_CASE_FIXTURE(BuiltinsFixture, "cannot_compare_tables_that_do_not_have_the_same_metatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -289,7 +289,7 @@ TEST_CASE_FIXTURE(Fixture, "cannot_compare_tables_that_do_not_have_the_same_meta
REQUIRE_EQ((Location{{11, 18}, {11, 23}}), result.errors[1].location); REQUIRE_EQ((Location{{11, 18}, {11, 23}}), result.errors[1].location);
} }
TEST_CASE_FIXTURE(Fixture, "produce_the_correct_error_message_when_comparing_a_table_with_a_metatable_with_one_that_does_not") TEST_CASE_FIXTURE(BuiltinsFixture, "produce_the_correct_error_message_when_comparing_a_table_with_a_metatable_with_one_that_does_not")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -361,7 +361,7 @@ TEST_CASE_FIXTURE(Fixture, "compound_assign_mismatch_result")
CHECK_EQ(result.errors[1], (TypeError{Location{{2, 8}, {2, 15}}, TypeMismatch{typeChecker.stringType, typeChecker.numberType}})); CHECK_EQ(result.errors[1], (TypeError{Location{{2, 8}, {2, 15}}, TypeMismatch{typeChecker.stringType, typeChecker.numberType}}));
} }
TEST_CASE_FIXTURE(Fixture, "compound_assign_metatable") TEST_CASE_FIXTURE(BuiltinsFixture, "compound_assign_metatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -381,7 +381,7 @@ TEST_CASE_FIXTURE(Fixture, "compound_assign_metatable")
CHECK_EQ(0, result.errors.size()); CHECK_EQ(0, result.errors.size());
} }
TEST_CASE_FIXTURE(Fixture, "compound_assign_mismatch_metatable") TEST_CASE_FIXTURE(BuiltinsFixture, "compound_assign_mismatch_metatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -428,7 +428,7 @@ local x = false
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "typecheck_unary_minus") TEST_CASE_FIXTURE(BuiltinsFixture, "typecheck_unary_minus")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -461,7 +461,7 @@ TEST_CASE_FIXTURE(Fixture, "typecheck_unary_minus")
REQUIRE_EQ(gen->message, "Unary operator '-' not supported by type 'bar'"); REQUIRE_EQ(gen->message, "Unary operator '-' not supported by type 'bar'");
} }
TEST_CASE_FIXTURE(Fixture, "unary_not_is_boolean") TEST_CASE_FIXTURE(BuiltinsFixture, "unary_not_is_boolean")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local b = not "string" local b = not "string"
@ -473,7 +473,7 @@ TEST_CASE_FIXTURE(Fixture, "unary_not_is_boolean")
REQUIRE_EQ("boolean", toString(requireType("c"))); REQUIRE_EQ("boolean", toString(requireType("c")));
} }
TEST_CASE_FIXTURE(Fixture, "disallow_string_and_types_without_metatables_from_arithmetic_binary_ops") TEST_CASE_FIXTURE(BuiltinsFixture, "disallow_string_and_types_without_metatables_from_arithmetic_binary_ops")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -573,7 +573,7 @@ TEST_CASE_FIXTURE(Fixture, "strict_binary_op_where_lhs_unknown")
CHECK_EQ("Unknown type used in + operation; consider adding a type annotation to 'a'", toString(result.errors[0])); CHECK_EQ("Unknown type used in + operation; consider adding a type annotation to 'a'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "and_binexps_dont_unify") TEST_CASE_FIXTURE(BuiltinsFixture, "and_binexps_dont_unify")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -628,7 +628,7 @@ TEST_CASE_FIXTURE(Fixture, "cli_38355_recursive_union")
CHECK_EQ("Type contains a self-recursive construct that cannot be resolved", toString(result.errors[0])); CHECK_EQ("Type contains a self-recursive construct that cannot be resolved", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "UnknownGlobalCompoundAssign") TEST_CASE_FIXTURE(BuiltinsFixture, "UnknownGlobalCompoundAssign")
{ {
// In non-strict mode, global definition is still allowed // In non-strict mode, global definition is still allowed
{ {
@ -755,8 +755,6 @@ TEST_CASE_FIXTURE(Fixture, "refine_and_or")
TEST_CASE_FIXTURE(Fixture, "infer_any_in_all_modes_when_lhs_is_unknown") TEST_CASE_FIXTURE(Fixture, "infer_any_in_all_modes_when_lhs_is_unknown")
{ {
ScopedFastFlag sff{"LuauDecoupleOperatorInferenceFromUnifiedTypeInference", true};
CheckResult result = check(Mode::Strict, R"( CheckResult result = check(Mode::Strict, R"(
local function f(x, y) local function f(x, y)
return x + y return x + y
@ -779,4 +777,47 @@ TEST_CASE_FIXTURE(Fixture, "infer_any_in_all_modes_when_lhs_is_unknown")
// the case right now, though. // the case right now, though.
} }
TEST_CASE_FIXTURE(BuiltinsFixture, "equality_operations_succeed_if_any_union_branch_succeeds")
{
ScopedFastFlag sff("LuauSuccessTypingForEqualityOperations", true);
CheckResult result = check(R"(
local mm = {}
type Foo = typeof(setmetatable({}, mm))
local x: Foo
local y: Foo?
local v1 = x == y
local v2 = y == x
local v3 = x ~= y
local v4 = y ~= x
)");
LUAU_REQUIRE_NO_ERRORS(result);
CheckResult result2 = check(R"(
local mm1 = {
x = "foo",
}
local mm2 = {
y = "bar",
}
type Foo = typeof(setmetatable({}, mm1))
type Bar = typeof(setmetatable({}, mm2))
local x1: Foo
local x2: Foo?
local y1: Bar
local y2: Bar?
local v1 = x1 == y1
local v2 = x2 == y2
)");
LUAU_REQUIRE_ERROR_COUNT(1, result2);
CHECK(toString(result2.errors[0]) == "Types Foo and Bar cannot be compared with == because they do not have the same metatable");
}
TEST_SUITE_END(); TEST_SUITE_END();

View File

@ -53,7 +53,7 @@ TEST_CASE_FIXTURE(Fixture, "typeguard_inference_incomplete")
CHECK_EQ(expected, decorateWithTypes(code)); CHECK_EQ(expected, decorateWithTypes(code));
} }
TEST_CASE_FIXTURE(Fixture, "xpcall_returns_what_f_returns") TEST_CASE_FIXTURE(BuiltinsFixture, "xpcall_returns_what_f_returns")
{ {
const std::string code = R"( const std::string code = R"(
local a, b, c = xpcall(function() return 1, "foo" end, function() return "foo", 1 end) local a, b, c = xpcall(function() return 1, "foo" end, function() return "foo", 1 end)
@ -105,7 +105,7 @@ TEST_CASE_FIXTURE(Fixture, "it_should_be_agnostic_of_actual_size")
// Ideally setmetatable's second argument would be an optional free table. // Ideally setmetatable's second argument would be an optional free table.
// For now, infer it as just a free table. // For now, infer it as just a free table.
TEST_CASE_FIXTURE(Fixture, "setmetatable_constrains_free_type_into_free_table") TEST_CASE_FIXTURE(BuiltinsFixture, "setmetatable_constrains_free_type_into_free_table")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a = {} local a = {}
@ -146,7 +146,7 @@ TEST_CASE_FIXTURE(Fixture, "while_body_are_also_refined")
// Originally from TypeInfer.test.cpp. // Originally from TypeInfer.test.cpp.
// I dont think type checking the metamethod at every site of == is the correct thing to do. // I dont think type checking the metamethod at every site of == is the correct thing to do.
// We should be type checking the metamethod at the call site of setmetatable. // We should be type checking the metamethod at the call site of setmetatable.
TEST_CASE_FIXTURE(Fixture, "error_on_eq_metamethod_returning_a_type_other_than_boolean") TEST_CASE_FIXTURE(BuiltinsFixture, "error_on_eq_metamethod_returning_a_type_other_than_boolean")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local tab = {a = 1} local tab = {a = 1}
@ -428,7 +428,7 @@ TEST_CASE_FIXTURE(Fixture, "pcall_returns_at_least_two_value_but_function_return
} }
// Belongs in TypeInfer.builtins.test.cpp. // Belongs in TypeInfer.builtins.test.cpp.
TEST_CASE_FIXTURE(Fixture, "choose_the_right_overload_for_pcall") TEST_CASE_FIXTURE(BuiltinsFixture, "choose_the_right_overload_for_pcall")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function f(): number local function f(): number
@ -449,7 +449,7 @@ TEST_CASE_FIXTURE(Fixture, "choose_the_right_overload_for_pcall")
} }
// Belongs in TypeInfer.builtins.test.cpp. // Belongs in TypeInfer.builtins.test.cpp.
TEST_CASE_FIXTURE(Fixture, "function_returns_many_things_but_first_of_it_is_forgotten") TEST_CASE_FIXTURE(BuiltinsFixture, "function_returns_many_things_but_first_of_it_is_forgotten")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function f(): (number, string, boolean) local function f(): (number, string, boolean)

View File

@ -240,7 +240,7 @@ TEST_CASE_FIXTURE(Fixture, "typeguard_in_if_condition_position")
CHECK_EQ("number", toString(requireTypeAtPosition({3, 26}))); CHECK_EQ("number", toString(requireTypeAtPosition({3, 26})));
} }
TEST_CASE_FIXTURE(Fixture, "typeguard_in_assert_position") TEST_CASE_FIXTURE(BuiltinsFixture, "typeguard_in_assert_position")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a local a
@ -300,7 +300,7 @@ TEST_CASE_FIXTURE(Fixture, "call_a_more_specific_function_using_typeguard")
CHECK_EQ("Type 'string' could not be converted into 'number'", toString(result.errors[0])); CHECK_EQ("Type 'string' could not be converted into 'number'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "impossible_type_narrow_is_not_an_error") TEST_CASE_FIXTURE(BuiltinsFixture, "impossible_type_narrow_is_not_an_error")
{ {
// This unit test serves as a reminder to not implement this warning until Luau is intelligent enough. // This unit test serves as a reminder to not implement this warning until Luau is intelligent enough.
// For instance, getting a value out of the indexer and checking whether the value exists is not an error. // For instance, getting a value out of the indexer and checking whether the value exists is not an error.
@ -333,7 +333,7 @@ TEST_CASE_FIXTURE(Fixture, "truthy_constraint_on_properties")
CHECK_EQ("number?", toString(requireType("bar"))); CHECK_EQ("number?", toString(requireType("bar")));
} }
TEST_CASE_FIXTURE(Fixture, "index_on_a_refined_property") TEST_CASE_FIXTURE(BuiltinsFixture, "index_on_a_refined_property")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t: {x: {y: string}?} = {x = {y = "hello!"}} local t: {x: {y: string}?} = {x = {y = "hello!"}}
@ -346,7 +346,7 @@ TEST_CASE_FIXTURE(Fixture, "index_on_a_refined_property")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "assert_non_binary_expressions_actually_resolve_constraints") TEST_CASE_FIXTURE(BuiltinsFixture, "assert_non_binary_expressions_actually_resolve_constraints")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local foo: string? = "hello" local foo: string? = "hello"
@ -730,7 +730,7 @@ TEST_CASE_FIXTURE(Fixture, "type_guard_can_filter_for_overloaded_function")
CHECK_EQ("nil", toString(requireTypeAtPosition({6, 28}))); CHECK_EQ("nil", toString(requireTypeAtPosition({6, 28})));
} }
TEST_CASE_FIXTURE(Fixture, "type_guard_warns_on_no_overlapping_types_only_when_sense_is_true") TEST_CASE_FIXTURE(BuiltinsFixture, "type_guard_warns_on_no_overlapping_types_only_when_sense_is_true")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function f(t: {x: number}) local function f(t: {x: number})
@ -846,7 +846,7 @@ TEST_CASE_FIXTURE(Fixture, "not_t_or_some_prop_of_t")
CHECK_EQ("{| x: boolean |}?", toString(requireTypeAtPosition({3, 28}))); CHECK_EQ("{| x: boolean |}?", toString(requireTypeAtPosition({3, 28})));
} }
TEST_CASE_FIXTURE(Fixture, "assert_a_to_be_truthy_then_assert_a_to_be_number") TEST_CASE_FIXTURE(BuiltinsFixture, "assert_a_to_be_truthy_then_assert_a_to_be_number")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a: (number | string)? local a: (number | string)?
@ -862,7 +862,7 @@ TEST_CASE_FIXTURE(Fixture, "assert_a_to_be_truthy_then_assert_a_to_be_number")
CHECK_EQ("number", toString(requireTypeAtPosition({5, 18}))); CHECK_EQ("number", toString(requireTypeAtPosition({5, 18})));
} }
TEST_CASE_FIXTURE(Fixture, "merge_should_be_fully_agnostic_of_hashmap_ordering") TEST_CASE_FIXTURE(BuiltinsFixture, "merge_should_be_fully_agnostic_of_hashmap_ordering")
{ {
// This bug came up because there was a mistake in Luau::merge where zipping on two maps would produce the wrong merged result. // This bug came up because there was a mistake in Luau::merge where zipping on two maps would produce the wrong merged result.
CheckResult result = check(R"( CheckResult result = check(R"(
@ -899,7 +899,7 @@ TEST_CASE_FIXTURE(Fixture, "refine_the_correct_types_opposite_of_when_a_is_not_n
CHECK_EQ("number | string", toString(requireTypeAtPosition({5, 28}))); CHECK_EQ("number | string", toString(requireTypeAtPosition({5, 28})));
} }
TEST_CASE_FIXTURE(Fixture, "is_truthy_constraint_ifelse_expression") TEST_CASE_FIXTURE(BuiltinsFixture, "is_truthy_constraint_ifelse_expression")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function f(v:string?) function f(v:string?)
@ -913,7 +913,7 @@ TEST_CASE_FIXTURE(Fixture, "is_truthy_constraint_ifelse_expression")
CHECK_EQ("nil", toString(requireTypeAtPosition({2, 45}))); CHECK_EQ("nil", toString(requireTypeAtPosition({2, 45})));
} }
TEST_CASE_FIXTURE(Fixture, "invert_is_truthy_constraint_ifelse_expression") TEST_CASE_FIXTURE(BuiltinsFixture, "invert_is_truthy_constraint_ifelse_expression")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function f(v:string?) function f(v:string?)
@ -945,7 +945,7 @@ TEST_CASE_FIXTURE(Fixture, "type_comparison_ifelse_expression")
CHECK_EQ("any", toString(requireTypeAtPosition({6, 66}))); CHECK_EQ("any", toString(requireTypeAtPosition({6, 66})));
} }
TEST_CASE_FIXTURE(Fixture, "correctly_lookup_a_shadowed_local_that_which_was_previously_refined") TEST_CASE_FIXTURE(BuiltinsFixture, "correctly_lookup_a_shadowed_local_that_which_was_previously_refined")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local foo: string? = "hi" local foo: string? = "hi"

View File

@ -415,7 +415,7 @@ TEST_CASE_FIXTURE(Fixture, "widening_happens_almost_everywhere_except_for_tables
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_insert_with_a_singleton_argument") TEST_CASE_FIXTURE(BuiltinsFixture, "table_insert_with_a_singleton_argument")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauWidenIfSupertypeIsFree2", true}, {"LuauWidenIfSupertypeIsFree2", true},

View File

@ -201,7 +201,7 @@ TEST_CASE_FIXTURE(Fixture, "used_dot_instead_of_colon")
REQUIRE(it != result.errors.end()); REQUIRE(it != result.errors.end());
} }
TEST_CASE_FIXTURE(Fixture, "used_colon_correctly") TEST_CASE_FIXTURE(BuiltinsFixture, "used_colon_correctly")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -883,7 +883,7 @@ TEST_CASE_FIXTURE(Fixture, "assigning_to_an_unsealed_table_with_string_literal_s
CHECK_EQ(*typeChecker.stringType, *propertyA); CHECK_EQ(*typeChecker.stringType, *propertyA);
} }
TEST_CASE_FIXTURE(Fixture, "oop_indexer_works") TEST_CASE_FIXTURE(BuiltinsFixture, "oop_indexer_works")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local clazz = {} local clazz = {}
@ -906,7 +906,7 @@ TEST_CASE_FIXTURE(Fixture, "oop_indexer_works")
CHECK_EQ(*typeChecker.stringType, *requireType("words")); CHECK_EQ(*typeChecker.stringType, *requireType("words"));
} }
TEST_CASE_FIXTURE(Fixture, "indexer_table") TEST_CASE_FIXTURE(BuiltinsFixture, "indexer_table")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local clazz = {a="hello"} local clazz = {a="hello"}
@ -919,7 +919,7 @@ TEST_CASE_FIXTURE(Fixture, "indexer_table")
CHECK_EQ(*typeChecker.stringType, *requireType("b")); CHECK_EQ(*typeChecker.stringType, *requireType("b"));
} }
TEST_CASE_FIXTURE(Fixture, "indexer_fn") TEST_CASE_FIXTURE(BuiltinsFixture, "indexer_fn")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local instanace = setmetatable({}, {__index=function() return 10 end}) local instanace = setmetatable({}, {__index=function() return 10 end})
@ -930,7 +930,7 @@ TEST_CASE_FIXTURE(Fixture, "indexer_fn")
CHECK_EQ(*typeChecker.numberType, *requireType("b")); CHECK_EQ(*typeChecker.numberType, *requireType("b"));
} }
TEST_CASE_FIXTURE(Fixture, "meta_add") TEST_CASE_FIXTURE(BuiltinsFixture, "meta_add")
{ {
// Note: meta_add_inferred and this unit test are currently the same exact thing. // Note: meta_add_inferred and this unit test are currently the same exact thing.
// We'll want to change this one in particular when we add real syntax for metatables. // We'll want to change this one in particular when we add real syntax for metatables.
@ -947,7 +947,7 @@ TEST_CASE_FIXTURE(Fixture, "meta_add")
CHECK_EQ(follow(requireType("a")), follow(requireType("c"))); CHECK_EQ(follow(requireType("a")), follow(requireType("c")));
} }
TEST_CASE_FIXTURE(Fixture, "meta_add_inferred") TEST_CASE_FIXTURE(BuiltinsFixture, "meta_add_inferred")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a = {} local a = {}
@ -960,7 +960,7 @@ TEST_CASE_FIXTURE(Fixture, "meta_add_inferred")
CHECK_EQ(*requireType("a"), *requireType("c")); CHECK_EQ(*requireType("a"), *requireType("c"));
} }
TEST_CASE_FIXTURE(Fixture, "meta_add_both_ways") TEST_CASE_FIXTURE(BuiltinsFixture, "meta_add_both_ways")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
type VectorMt = { __add: (Vector, number) -> Vector } type VectorMt = { __add: (Vector, number) -> Vector }
@ -980,7 +980,7 @@ TEST_CASE_FIXTURE(Fixture, "meta_add_both_ways")
// This test exposed a bug where we let go of the "seen" stack while unifying table types // This test exposed a bug where we let go of the "seen" stack while unifying table types
// As a result, type inference crashed with a stack overflow. // As a result, type inference crashed with a stack overflow.
TEST_CASE_FIXTURE(Fixture, "unification_of_unions_in_a_self_referential_type") TEST_CASE_FIXTURE(BuiltinsFixture, "unification_of_unions_in_a_self_referential_type")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
type A = {} type A = {}
@ -1009,7 +1009,7 @@ TEST_CASE_FIXTURE(Fixture, "unification_of_unions_in_a_self_referential_type")
CHECK_EQ(bmtv->metatable, requireType("bmt")); CHECK_EQ(bmtv->metatable, requireType("bmt"));
} }
TEST_CASE_FIXTURE(Fixture, "oop_polymorphic") TEST_CASE_FIXTURE(BuiltinsFixture, "oop_polymorphic")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local animal = {} local animal = {}
@ -1060,7 +1060,7 @@ TEST_CASE_FIXTURE(Fixture, "user_defined_table_types_are_named")
CHECK_EQ("Vector3", toString(requireType("v"))); CHECK_EQ("Vector3", toString(requireType("v")));
} }
TEST_CASE_FIXTURE(Fixture, "result_is_always_any_if_lhs_is_any") TEST_CASE_FIXTURE(BuiltinsFixture, "result_is_always_any_if_lhs_is_any")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
type Vector3MT = { type Vector3MT = {
@ -1133,7 +1133,7 @@ TEST_CASE_FIXTURE(Fixture, "nice_error_when_trying_to_fetch_property_of_boolean"
CHECK_EQ("Type 'boolean' does not have key 'some_prop'", toString(result.errors[0])); CHECK_EQ("Type 'boolean' does not have key 'some_prop'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "defining_a_method_for_a_builtin_sealed_table_must_fail") TEST_CASE_FIXTURE(BuiltinsFixture, "defining_a_method_for_a_builtin_sealed_table_must_fail")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function string.m() end function string.m() end
@ -1142,7 +1142,7 @@ TEST_CASE_FIXTURE(Fixture, "defining_a_method_for_a_builtin_sealed_table_must_fa
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
} }
TEST_CASE_FIXTURE(Fixture, "defining_a_self_method_for_a_builtin_sealed_table_must_fail") TEST_CASE_FIXTURE(BuiltinsFixture, "defining_a_self_method_for_a_builtin_sealed_table_must_fail")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
function string:m() end function string:m() end
@ -1261,7 +1261,7 @@ TEST_CASE_FIXTURE(Fixture, "found_like_key_in_table_function_call")
CHECK_EQ(toString(te), "Key 'fOo' not found in table 't'. Did you mean 'Foo'?"); CHECK_EQ(toString(te), "Key 'fOo' not found in table 't'. Did you mean 'Foo'?");
} }
TEST_CASE_FIXTURE(Fixture, "found_like_key_in_table_property_access") TEST_CASE_FIXTURE(BuiltinsFixture, "found_like_key_in_table_property_access")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {X = 1} local t = {X = 1}
@ -1286,7 +1286,7 @@ TEST_CASE_FIXTURE(Fixture, "found_like_key_in_table_property_access")
CHECK_EQ(toString(te), "Key 'x' not found in table 't'. Did you mean 'X'?"); CHECK_EQ(toString(te), "Key 'x' not found in table 't'. Did you mean 'X'?");
} }
TEST_CASE_FIXTURE(Fixture, "found_multiple_like_keys") TEST_CASE_FIXTURE(BuiltinsFixture, "found_multiple_like_keys")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {Foo = 1, foO = 2} local t = {Foo = 1, foO = 2}
@ -1312,7 +1312,7 @@ TEST_CASE_FIXTURE(Fixture, "found_multiple_like_keys")
CHECK_EQ(toString(te), "Key 'foo' not found in table 't'. Did you mean one of 'Foo', 'foO'?"); CHECK_EQ(toString(te), "Key 'foo' not found in table 't'. Did you mean one of 'Foo', 'foO'?");
} }
TEST_CASE_FIXTURE(Fixture, "dont_suggest_exact_match_keys") TEST_CASE_FIXTURE(BuiltinsFixture, "dont_suggest_exact_match_keys")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {} local t = {}
@ -1339,7 +1339,7 @@ TEST_CASE_FIXTURE(Fixture, "dont_suggest_exact_match_keys")
CHECK_EQ(toString(te), "Key 'Foo' not found in table 't'. Did you mean 'foO'?"); CHECK_EQ(toString(te), "Key 'Foo' not found in table 't'. Did you mean 'foO'?");
} }
TEST_CASE_FIXTURE(Fixture, "getmetatable_returns_pointer_to_metatable") TEST_CASE_FIXTURE(BuiltinsFixture, "getmetatable_returns_pointer_to_metatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {x = 1} local t = {x = 1}
@ -1352,7 +1352,7 @@ TEST_CASE_FIXTURE(Fixture, "getmetatable_returns_pointer_to_metatable")
CHECK_EQ(*requireType("mt"), *requireType("returnedMT")); CHECK_EQ(*requireType("mt"), *requireType("returnedMT"));
} }
TEST_CASE_FIXTURE(Fixture, "metatable_mismatch_should_fail") TEST_CASE_FIXTURE(BuiltinsFixture, "metatable_mismatch_should_fail")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t1 = {x = 1} local t1 = {x = 1}
@ -1374,7 +1374,7 @@ TEST_CASE_FIXTURE(Fixture, "metatable_mismatch_should_fail")
CHECK_EQ(*tm->givenType, *requireType("t2")); CHECK_EQ(*tm->givenType, *requireType("t2"));
} }
TEST_CASE_FIXTURE(Fixture, "property_lookup_through_tabletypevar_metatable") TEST_CASE_FIXTURE(BuiltinsFixture, "property_lookup_through_tabletypevar_metatable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {x = 1} local t = {x = 1}
@ -1393,7 +1393,7 @@ TEST_CASE_FIXTURE(Fixture, "property_lookup_through_tabletypevar_metatable")
CHECK_EQ(up->key, "z"); CHECK_EQ(up->key, "z");
} }
TEST_CASE_FIXTURE(Fixture, "missing_metatable_for_sealed_tables_do_not_get_inferred") TEST_CASE_FIXTURE(BuiltinsFixture, "missing_metatable_for_sealed_tables_do_not_get_inferred")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {x = 1} local t = {x = 1}
@ -1742,7 +1742,7 @@ TEST_CASE_FIXTURE(Fixture, "hide_table_error_properties")
CHECK_EQ("Cannot add property 'b' to table '{| x: number |}'", toString(result.errors[1])); CHECK_EQ("Cannot add property 'b' to table '{| x: number |}'", toString(result.errors[1]));
} }
TEST_CASE_FIXTURE(Fixture, "builtin_table_names") TEST_CASE_FIXTURE(BuiltinsFixture, "builtin_table_names")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
os.h = 2 os.h = 2
@ -1755,7 +1755,7 @@ TEST_CASE_FIXTURE(Fixture, "builtin_table_names")
CHECK_EQ("Cannot add property 'k' to table 'string'", toString(result.errors[1])); CHECK_EQ("Cannot add property 'k' to table 'string'", toString(result.errors[1]));
} }
TEST_CASE_FIXTURE(Fixture, "persistent_sealed_table_is_immutable") TEST_CASE_FIXTURE(BuiltinsFixture, "persistent_sealed_table_is_immutable")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -1858,7 +1858,7 @@ local foos: {Foo} = {
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "quantifying_a_bound_var_works") TEST_CASE_FIXTURE(BuiltinsFixture, "quantifying_a_bound_var_works")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local clazz = {} local clazz = {}
@ -1983,7 +1983,7 @@ TEST_CASE_FIXTURE(Fixture, "invariant_table_properties_means_instantiating_table
LUAU_REQUIRE_ERRORS(result); LUAU_REQUIRE_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_insert_should_cope_with_optional_properties_in_nonstrict") TEST_CASE_FIXTURE(BuiltinsFixture, "table_insert_should_cope_with_optional_properties_in_nonstrict")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -1996,7 +1996,7 @@ TEST_CASE_FIXTURE(Fixture, "table_insert_should_cope_with_optional_properties_in
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_insert_should_cope_with_optional_properties_in_strict") TEST_CASE_FIXTURE(BuiltinsFixture, "table_insert_should_cope_with_optional_properties_in_strict")
{ {
ScopedFastFlag sff{"LuauTableSubtypingVariance2", true}; ScopedFastFlag sff{"LuauTableSubtypingVariance2", true};
@ -2052,7 +2052,7 @@ caused by:
Property 'y' is not compatible. Type 'number' could not be converted into 'string')"); Property 'y' is not compatible. Type 'number' could not be converted into 'string')");
} }
TEST_CASE_FIXTURE(Fixture, "error_detailed_metatable_prop") TEST_CASE_FIXTURE(BuiltinsFixture, "error_detailed_metatable_prop")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauTableSubtypingVariance2", true}, {"LuauTableSubtypingVariance2", true},
@ -2183,7 +2183,7 @@ a.p = { x = 9 }
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "recursive_metatable_type_call") TEST_CASE_FIXTURE(BuiltinsFixture, "recursive_metatable_type_call")
{ {
ScopedFastFlag sff[]{ ScopedFastFlag sff[]{
{"LuauUnsealedTableLiteral", true}, {"LuauUnsealedTableLiteral", true},
@ -2277,7 +2277,7 @@ local y = #x
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
} }
TEST_CASE_FIXTURE(Fixture, "dont_hang_when_trying_to_look_up_in_cyclic_metatable_index") TEST_CASE_FIXTURE(BuiltinsFixture, "dont_hang_when_trying_to_look_up_in_cyclic_metatable_index")
{ {
ScopedFastFlag sff{"LuauTerminateCyclicMetatableIndexLookup", true}; ScopedFastFlag sff{"LuauTerminateCyclicMetatableIndexLookup", true};
@ -2296,7 +2296,7 @@ TEST_CASE_FIXTURE(Fixture, "dont_hang_when_trying_to_look_up_in_cyclic_metatable
CHECK_EQ("Type 't' does not have key 'p'", toString(result.errors[0])); CHECK_EQ("Type 't' does not have key 'p'", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "give_up_after_one_metatable_index_look_up") TEST_CASE_FIXTURE(BuiltinsFixture, "give_up_after_one_metatable_index_look_up")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local data = { x = 5 } local data = { x = 5 }
@ -2478,7 +2478,7 @@ TEST_CASE_FIXTURE(Fixture, "free_rhs_table_can_also_be_bound")
)"); )");
} }
TEST_CASE_FIXTURE(Fixture, "table_unifies_into_map") TEST_CASE_FIXTURE(BuiltinsFixture, "table_unifies_into_map")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local Instance: any local Instance: any
@ -2564,7 +2564,7 @@ TEST_CASE_FIXTURE(Fixture, "generalize_table_argument")
* the generalization process), then it loses the knowledge that its metatable will have an :incr() * the generalization process), then it loses the knowledge that its metatable will have an :incr()
* method. * method.
*/ */
TEST_CASE_FIXTURE(Fixture, "dont_quantify_table_that_belongs_to_outer_scope") TEST_CASE_FIXTURE(BuiltinsFixture, "dont_quantify_table_that_belongs_to_outer_scope")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local Counter = {} local Counter = {}
@ -2606,7 +2606,7 @@ TEST_CASE_FIXTURE(Fixture, "dont_quantify_table_that_belongs_to_outer_scope")
} }
// TODO: CLI-39624 // TODO: CLI-39624
TEST_CASE_FIXTURE(Fixture, "instantiate_tables_at_scope_level") TEST_CASE_FIXTURE(BuiltinsFixture, "instantiate_tables_at_scope_level")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict
@ -2690,7 +2690,7 @@ TEST_CASE_FIXTURE(Fixture, "dont_crash_when_setmetatable_does_not_produce_a_meta
LUAU_REQUIRE_ERROR_COUNT(1, result); LUAU_REQUIRE_ERROR_COUNT(1, result);
} }
TEST_CASE_FIXTURE(Fixture, "instantiate_table_cloning") TEST_CASE_FIXTURE(BuiltinsFixture, "instantiate_table_cloning")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!nonstrict --!nonstrict
@ -2711,7 +2711,7 @@ type t0<t32> = any
CHECK(ttv->instantiatedTypeParams.empty()); CHECK(ttv->instantiatedTypeParams.empty());
} }
TEST_CASE_FIXTURE(Fixture, "instantiate_table_cloning_2") TEST_CASE_FIXTURE(BuiltinsFixture, "instantiate_table_cloning_2")
{ {
ScopedFastFlag sff{"LuauOnlyMutateInstantiatedTables", true}; ScopedFastFlag sff{"LuauOnlyMutateInstantiatedTables", true};
@ -2767,7 +2767,7 @@ local baz = foo[bar]
CHECK_EQ(result.errors[0].location, Location{Position{3, 16}, Position{3, 19}}); CHECK_EQ(result.errors[0].location, Location{Position{3, 16}, Position{3, 19}});
} }
TEST_CASE_FIXTURE(Fixture, "table_simple_call") TEST_CASE_FIXTURE(BuiltinsFixture, "table_simple_call")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a = setmetatable({ x = 2 }, { local a = setmetatable({ x = 2 }, {
@ -2783,7 +2783,7 @@ local c = a(2) -- too many arguments
CHECK_EQ("Argument count mismatch. Function expects 1 argument, but 2 are specified", toString(result.errors[0])); CHECK_EQ("Argument count mismatch. Function expects 1 argument, but 2 are specified", toString(result.errors[0]));
} }
TEST_CASE_FIXTURE(Fixture, "access_index_metamethod_that_returns_variadic") TEST_CASE_FIXTURE(BuiltinsFixture, "access_index_metamethod_that_returns_variadic")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
type Foo = {x: string} type Foo = {x: string}
@ -2878,7 +2878,7 @@ TEST_CASE_FIXTURE(Fixture, "pairs_parameters_are_not_unsealed_tables")
)"); )");
} }
TEST_CASE_FIXTURE(Fixture, "table_function_check_use_after_free") TEST_CASE_FIXTURE(BuiltinsFixture, "table_function_check_use_after_free")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local t = {} local t = {}
@ -2916,7 +2916,7 @@ TEST_CASE_FIXTURE(Fixture, "inferred_properties_of_a_table_should_start_with_the
} }
// The real bug here was that we weren't always uncondionally typechecking a trailing return statement last. // The real bug here was that we weren't always uncondionally typechecking a trailing return statement last.
TEST_CASE_FIXTURE(Fixture, "dont_leak_free_table_props") TEST_CASE_FIXTURE(BuiltinsFixture, "dont_leak_free_table_props")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function a(state) local function a(state)

View File

@ -161,7 +161,7 @@ TEST_CASE_FIXTURE(Fixture, "unify_nearly_identical_recursive_types")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "warn_on_lowercase_parent_property") TEST_CASE_FIXTURE(BuiltinsFixture, "warn_on_lowercase_parent_property")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local M = require(script.parent.DoesNotMatter) local M = require(script.parent.DoesNotMatter)
@ -175,7 +175,7 @@ TEST_CASE_FIXTURE(Fixture, "warn_on_lowercase_parent_property")
REQUIRE_EQ("parent", ed->symbol); REQUIRE_EQ("parent", ed->symbol);
} }
TEST_CASE_FIXTURE(Fixture, "weird_case") TEST_CASE_FIXTURE(BuiltinsFixture, "weird_case")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function f() return 4 end local function f() return 4 end
@ -419,7 +419,7 @@ TEST_CASE_FIXTURE(Fixture, "globals_everywhere")
CHECK_EQ("any", toString(requireType("bar"))); CHECK_EQ("any", toString(requireType("bar")));
} }
TEST_CASE_FIXTURE(Fixture, "correctly_scope_locals_do") TEST_CASE_FIXTURE(BuiltinsFixture, "correctly_scope_locals_do")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
do do
@ -534,7 +534,7 @@ TEST_CASE_FIXTURE(Fixture, "tc_after_error_recovery_no_assert")
LUAU_REQUIRE_ERRORS(result); LUAU_REQUIRE_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "tc_after_error_recovery_no_replacement_name_in_error") TEST_CASE_FIXTURE(BuiltinsFixture, "tc_after_error_recovery_no_replacement_name_in_error")
{ {
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
@ -587,7 +587,7 @@ TEST_CASE_FIXTURE(Fixture, "tc_after_error_recovery_no_replacement_name_in_error
} }
} }
TEST_CASE_FIXTURE(Fixture, "index_expr_should_be_checked") TEST_CASE_FIXTURE(BuiltinsFixture, "index_expr_should_be_checked")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local foo: any local foo: any
@ -768,7 +768,7 @@ b, c = {2, "s"}, {"b", 4}
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "infer_assignment_value_types_mutable_lval") TEST_CASE_FIXTURE(BuiltinsFixture, "infer_assignment_value_types_mutable_lval")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local a = {} local a = {}
@ -836,7 +836,7 @@ local a: number? = if true then 1 else nil
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "tc_if_else_expressions_expected_type_3") TEST_CASE_FIXTURE(BuiltinsFixture, "tc_if_else_expressions_expected_type_3")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function times<T>(n: any, f: () -> T) local function times<T>(n: any, f: () -> T)
@ -907,7 +907,7 @@ TEST_CASE_FIXTURE(Fixture, "fuzzer_found_this")
)"); )");
} }
TEST_CASE_FIXTURE(Fixture, "recursive_metatable_crash") TEST_CASE_FIXTURE(BuiltinsFixture, "recursive_metatable_crash")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
local function getIt() local function getIt()
@ -1041,7 +1041,6 @@ TEST_CASE_FIXTURE(Fixture, "follow_on_new_types_in_substitution")
TEST_CASE_FIXTURE(Fixture, "do_not_bind_a_free_table_to_a_union_containing_that_table") TEST_CASE_FIXTURE(Fixture, "do_not_bind_a_free_table_to_a_union_containing_that_table")
{ {
ScopedFastFlag flag[] = { ScopedFastFlag flag[] = {
{"LuauStatFunctionSimplify4", true},
{"LuauLowerBoundsCalculation", true}, {"LuauLowerBoundsCalculation", true},
{"LuauDifferentOrderOfUnificationDoesntMatter2", true}, {"LuauDifferentOrderOfUnificationDoesntMatter2", true},
}; };

View File

@ -196,7 +196,7 @@ TEST_CASE_FIXTURE(TryUnifyFixture, "variadics_should_use_reversed_properly")
CHECK_EQ(toString(tm->wantedType), "string"); CHECK_EQ(toString(tm->wantedType), "string");
} }
TEST_CASE_FIXTURE(TryUnifyFixture, "cli_41095_concat_log_in_sealed_table_unification") TEST_CASE_FIXTURE(BuiltinsFixture, "cli_41095_concat_log_in_sealed_table_unification")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
--!strict --!strict

View File

@ -339,7 +339,7 @@ local c: Packed<string, number, boolean>
CHECK_EQ(toString(ttvC->instantiatedTypePackParams[0], {true}), "number, boolean"); CHECK_EQ(toString(ttvC->instantiatedTypePackParams[0], {true}), "number, boolean");
} }
TEST_CASE_FIXTURE(Fixture, "type_alias_type_packs_import") TEST_CASE_FIXTURE(BuiltinsFixture, "type_alias_type_packs_import")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
export type Packed<T, U...> = { a: T, b: (U...) -> () } export type Packed<T, U...> = { a: T, b: (U...) -> () }
@ -369,7 +369,7 @@ local d: { a: typeof(c) }
CHECK_EQ(toString(requireType("d")), "{| a: Packed<string, number, boolean> |}"); CHECK_EQ(toString(requireType("d")), "{| a: Packed<string, number, boolean> |}");
} }
TEST_CASE_FIXTURE(Fixture, "type_pack_type_parameters") TEST_CASE_FIXTURE(BuiltinsFixture, "type_pack_type_parameters")
{ {
fileResolver.source["game/A"] = R"( fileResolver.source["game/A"] = R"(
export type Packed<T, U...> = { a: T, b: (U...) -> () } export type Packed<T, U...> = { a: T, b: (U...) -> () }
@ -784,7 +784,7 @@ local a: Y<...number>
LUAU_REQUIRE_ERRORS(result); LUAU_REQUIRE_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "type_alias_default_export") TEST_CASE_FIXTURE(BuiltinsFixture, "type_alias_default_export")
{ {
fileResolver.source["Module/Types"] = R"( fileResolver.source["Module/Types"] = R"(
export type A<T, U = string> = { a: T, b: U } export type A<T, U = string> = { a: T, b: U }

View File

@ -104,7 +104,7 @@ TEST_CASE_FIXTURE(Fixture, "optional_arguments_table2")
REQUIRE(!result.errors.empty()); REQUIRE(!result.errors.empty());
} }
TEST_CASE_FIXTURE(Fixture, "error_takes_optional_arguments") TEST_CASE_FIXTURE(BuiltinsFixture, "error_takes_optional_arguments")
{ {
CheckResult result = check(R"( CheckResult result = check(R"(
error("message") error("message")
@ -517,10 +517,8 @@ TEST_CASE_FIXTURE(Fixture, "dont_allow_cyclic_unions_to_be_inferred")
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_union_write_indirect") TEST_CASE_FIXTURE(BuiltinsFixture, "table_union_write_indirect")
{ {
ScopedFastFlag statFunctionSimplify{"LuauStatFunctionSimplify4", true};
CheckResult result = check(R"( CheckResult result = check(R"(
type A = { x: number, y: (number) -> string } | { z: number, y: (number) -> string } type A = { x: number, y: (number) -> string } | { z: number, y: (number) -> string }