Sync to upstream/release/525 (#467)
This commit is contained in:
parent
74c84815a0
commit
bd6d44f5e3
|
@ -24,7 +24,7 @@ LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3, false)
|
|||
LUAU_FASTFLAGVARIABLE(LuauSeparateTypechecks, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauAutocompleteDynamicLimits, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDirtySourceModule, false)
|
||||
LUAU_FASTINTVARIABLE(LuauAutocompleteCheckTimeoutMs, 0)
|
||||
LUAU_FASTINTVARIABLE(LuauAutocompleteCheckTimeoutMs, 100)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
|
|
@ -2653,12 +2653,12 @@ static void lintComments(LintContext& context, const std::vector<HotComment>& ho
|
|||
}
|
||||
else
|
||||
{
|
||||
std::string::size_type space = hc.content.find_first_of(" \t");
|
||||
size_t space = hc.content.find_first_of(" \t");
|
||||
std::string_view first = std::string_view(hc.content).substr(0, space);
|
||||
|
||||
if (first == "nolint")
|
||||
{
|
||||
std::string::size_type notspace = hc.content.find_first_not_of(" \t", space);
|
||||
size_t notspace = hc.content.find_first_not_of(" \t", space);
|
||||
|
||||
if (space == std::string::npos || notspace == std::string::npos)
|
||||
{
|
||||
|
@ -2827,7 +2827,7 @@ uint64_t LintWarning::parseMask(const std::vector<HotComment>& hotcomments)
|
|||
if (hc.content.compare(0, 6, "nolint") != 0)
|
||||
continue;
|
||||
|
||||
std::string::size_type name = hc.content.find_first_not_of(" \t", 6);
|
||||
size_t name = hc.content.find_first_not_of(" \t", 6);
|
||||
|
||||
// --!nolint disables everything
|
||||
if (name == std::string::npos)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <stdexcept>
|
||||
|
||||
LUAU_FASTFLAG(LuauLowerBoundsCalculation)
|
||||
LUAU_FASTINTVARIABLE(LuauTarjanChildLimit, 1000)
|
||||
LUAU_FASTINTVARIABLE(LuauTarjanChildLimit, 10000)
|
||||
LUAU_FASTFLAG(LuauTypecheckOptPass)
|
||||
LUAU_FASTFLAGVARIABLE(LuauSubstituteFollowNewTypes, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauSubstituteFollowPossibleMutations, false)
|
||||
|
|
|
@ -22,29 +22,25 @@
|
|||
#include <iterator>
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(DebugLuauMagicTypes, false)
|
||||
LUAU_FASTINTVARIABLE(LuauTypeInferRecursionLimit, 500)
|
||||
LUAU_FASTINTVARIABLE(LuauTypeInferIterationLimit, 2000)
|
||||
LUAU_FASTINTVARIABLE(LuauTypeInferRecursionLimit, 165)
|
||||
LUAU_FASTINTVARIABLE(LuauTypeInferIterationLimit, 20000)
|
||||
LUAU_FASTINTVARIABLE(LuauTypeInferTypePackLoopLimit, 5000)
|
||||
LUAU_FASTINTVARIABLE(LuauCheckRecursionLimit, 500)
|
||||
LUAU_FASTINTVARIABLE(LuauCheckRecursionLimit, 300)
|
||||
LUAU_FASTFLAG(LuauKnowsTheDataModel3)
|
||||
LUAU_FASTFLAG(LuauSeparateTypechecks)
|
||||
LUAU_FASTFLAG(LuauAutocompleteDynamicLimits)
|
||||
LUAU_FASTFLAG(LuauAutocompleteSingletonTypes)
|
||||
LUAU_FASTFLAGVARIABLE(LuauCyclicModuleTypeSurface, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDoNotRelyOnNextBinding, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauEqConstraint, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauWeakEqConstraint, false) // Eventually removed as false.
|
||||
LUAU_FASTFLAGVARIABLE(LuauLowerBoundsCalculation, false)
|
||||
LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauRecursiveTypeParameterRestriction, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauGenericFunctionsDontCacheTypeParams, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauInferStatFunction, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauSealExports, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauInstantiateFollows, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauSelfCallAutocompleteFix, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDiscriminableUnions2, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauExpectedTypesOfProperties, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauErrorRecoveryType, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauOnlyMutateInstantiatedTables, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauPropertiesGetExpectedType, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauStatFunctionSimplify4, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTypecheckOptPass, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauUnsealedTableLiteral, false)
|
||||
|
@ -54,12 +50,9 @@ LUAU_FASTFLAGVARIABLE(LuauReturnAnyInsteadOfICE, false) // Eventually removed as
|
|||
LUAU_FASTFLAG(LuauWidenIfSupertypeIsFree2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDoNotTryToReduce, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDoNotAccidentallyDependOnPointerOrdering, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauFixArgumentCountMismatchAmountWithGenericTypes, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauFixIncorrectLineNumberDuplicateType, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauCheckImplicitNumbericKeys, false)
|
||||
LUAU_FASTFLAG(LuauAnyInIsOptionalIsOptional)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDecoupleOperatorInferenceFromUnifiedTypeInference, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauArgCountMismatchSaysAtLeastWhenVariadic, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTableUseCounterInstead, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauReturnTypeInferenceInNonstrict, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauRecursionLimitException, false);
|
||||
|
@ -1160,7 +1153,10 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatForIn& forin)
|
|||
}
|
||||
else
|
||||
{
|
||||
iterTy = follow(instantiate(scope, checkExpr(scope, *firstValue).type, firstValue->location));
|
||||
if (FFlag::LuauInstantiateFollows)
|
||||
iterTy = instantiate(scope, checkExpr(scope, *firstValue).type, firstValue->location);
|
||||
else
|
||||
iterTy = follow(instantiate(scope, checkExpr(scope, *firstValue).type, firstValue->location));
|
||||
}
|
||||
|
||||
const FunctionTypeVar* iterFunc = get<FunctionTypeVar>(iterTy);
|
||||
|
@ -1172,7 +1168,12 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatForIn& forin)
|
|||
unify(varTy, var, forin.location);
|
||||
|
||||
if (!get<ErrorTypeVar>(iterTy) && !get<AnyTypeVar>(iterTy) && !get<FreeTypeVar>(iterTy))
|
||||
reportError(TypeError{firstValue->location, TypeMismatch{globalScope->bindings[AstName{"next"}].typeId, iterTy}});
|
||||
{
|
||||
if (FFlag::LuauDoNotRelyOnNextBinding)
|
||||
reportError(firstValue->location, CannotCallNonFunction{iterTy});
|
||||
else
|
||||
reportError(TypeError{firstValue->location, TypeMismatch{globalScope->bindings[AstName{"next"}].typeId, iterTy}});
|
||||
}
|
||||
|
||||
return check(loopScope, *forin.body);
|
||||
}
|
||||
|
@ -1427,8 +1428,7 @@ void TypeChecker::check(const ScopePtr& scope, const AstStatTypeAlias& typealias
|
|||
ftv->forwardedTypeAlias = true;
|
||||
bindingsMap[name] = {std::move(generics), std::move(genericPacks), ty};
|
||||
|
||||
if (FFlag::LuauFixIncorrectLineNumberDuplicateType)
|
||||
scope->typeAliasLocations[name] = typealias.location;
|
||||
scope->typeAliasLocations[name] = typealias.location;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2217,7 +2217,7 @@ TypeId TypeChecker::checkExprTable(
|
|||
if (isNonstrictMode() && !getTableType(exprType) && !get<FunctionTypeVar>(exprType))
|
||||
exprType = anyType;
|
||||
|
||||
if (FFlag::LuauPropertiesGetExpectedType && expectedTable)
|
||||
if (expectedTable)
|
||||
{
|
||||
auto it = expectedTable->props.find(key->value.data);
|
||||
if (it != expectedTable->props.end())
|
||||
|
@ -2309,9 +2309,8 @@ ExprResult<TypeId> TypeChecker::checkExpr_(const ScopePtr& scope, const AstExprT
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (FFlag::LuauExpectedTypesOfProperties)
|
||||
if (const UnionTypeVar* utv = get<UnionTypeVar>(follow(*expectedType)))
|
||||
expectedUnion = utv;
|
||||
else if (const UnionTypeVar* utv = get<UnionTypeVar>(follow(*expectedType)))
|
||||
expectedUnion = utv;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < expr.items.size; ++i)
|
||||
|
@ -2334,7 +2333,7 @@ ExprResult<TypeId> TypeChecker::checkExpr_(const ScopePtr& scope, const AstExprT
|
|||
if (auto prop = expectedTable->props.find(key->value.data); prop != expectedTable->props.end())
|
||||
expectedResultType = prop->second.type;
|
||||
}
|
||||
else if (FFlag::LuauExpectedTypesOfProperties && expectedUnion)
|
||||
else if (expectedUnion)
|
||||
{
|
||||
std::vector<TypeId> expectedResultTypes;
|
||||
for (TypeId expectedOption : expectedUnion)
|
||||
|
@ -2713,8 +2712,6 @@ TypeId TypeChecker::checkBinaryOperation(
|
|||
{
|
||||
auto name = getIdentifierOfBaseVar(expr.left);
|
||||
reportError(expr.location, CannotInferBinaryOperation{expr.op, name, CannotInferBinaryOperation::Operation});
|
||||
if (!FFlag::LuauErrorRecoveryType)
|
||||
return errorRecoveryType(scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2754,7 +2751,7 @@ TypeId TypeChecker::checkBinaryOperation(
|
|||
reportErrors(state.errors);
|
||||
bool hasErrors = !state.errors.empty();
|
||||
|
||||
if (FFlag::LuauErrorRecoveryType && hasErrors)
|
||||
if (hasErrors)
|
||||
{
|
||||
// If there are unification errors, the return type may still be unknown
|
||||
// so we loosen the argument types to see if that helps.
|
||||
|
@ -2768,8 +2765,7 @@ TypeId TypeChecker::checkBinaryOperation(
|
|||
if (state.errors.empty())
|
||||
state.log.commit();
|
||||
}
|
||||
|
||||
if (!hasErrors)
|
||||
else
|
||||
{
|
||||
state.log.commit();
|
||||
}
|
||||
|
@ -3196,16 +3192,7 @@ TypeId TypeChecker::checkFunctionName(const ScopePtr& scope, AstExpr& funName, T
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!ttv)
|
||||
{
|
||||
if (!FFlag::LuauErrorRecoveryType && !isTableIntersection(lhsType))
|
||||
// This error now gets reported when we check the function body.
|
||||
reportError(TypeError{funName.location, OnlyTablesCanHaveMethods{lhsType}});
|
||||
|
||||
return errorRecoveryType(scope);
|
||||
}
|
||||
|
||||
if (lhsType->persistent || ttv->state == TableState::Sealed)
|
||||
if (!ttv || lhsType->persistent || ttv->state == TableState::Sealed)
|
||||
return errorRecoveryType(scope);
|
||||
}
|
||||
|
||||
|
@ -3532,32 +3519,6 @@ ExprResult<TypePackId> TypeChecker::checkExprPack(const ScopePtr& scope, const A
|
|||
}
|
||||
|
||||
// Returns the minimum number of arguments the argument list can accept.
|
||||
static size_t getMinParameterCount_DEPRECATED(TypePackId tp)
|
||||
{
|
||||
size_t minCount = 0;
|
||||
size_t optionalCount = 0;
|
||||
|
||||
auto it = begin(tp);
|
||||
auto endIter = end(tp);
|
||||
|
||||
while (it != endIter)
|
||||
{
|
||||
TypeId ty = *it;
|
||||
if (isOptional(ty))
|
||||
++optionalCount;
|
||||
else
|
||||
{
|
||||
minCount += optionalCount;
|
||||
optionalCount = 0;
|
||||
minCount++;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
return minCount;
|
||||
}
|
||||
|
||||
static size_t getMinParameterCount(TxnLog* log, TypePackId tp)
|
||||
{
|
||||
size_t minCount = 0;
|
||||
|
@ -3597,19 +3558,14 @@ void TypeChecker::checkArgumentList(
|
|||
|
||||
size_t paramIndex = 0;
|
||||
|
||||
size_t minParams = FFlag::LuauFixIncorrectLineNumberDuplicateType ? 0 : getMinParameterCount_DEPRECATED(paramPack);
|
||||
|
||||
auto reportCountMismatchError = [&state, &argLocations, minParams, paramPack, argPack]() {
|
||||
auto reportCountMismatchError = [&state, &argLocations, paramPack, argPack]() {
|
||||
// For this case, we want the error span to cover every errant extra parameter
|
||||
Location location = state.location;
|
||||
if (!argLocations.empty())
|
||||
location = {state.location.begin, argLocations.back().end};
|
||||
|
||||
size_t mp = minParams;
|
||||
if (FFlag::LuauFixArgumentCountMismatchAmountWithGenericTypes)
|
||||
mp = getMinParameterCount(&state.log, paramPack);
|
||||
|
||||
state.reportError(TypeError{location, CountMismatch{mp, std::distance(begin(argPack), end(argPack))}});
|
||||
size_t minParams = getMinParameterCount(&state.log, paramPack);
|
||||
state.reportError(TypeError{location, CountMismatch{minParams, std::distance(begin(argPack), end(argPack))}});
|
||||
};
|
||||
|
||||
while (true)
|
||||
|
@ -3707,16 +3663,10 @@ void TypeChecker::checkArgumentList(
|
|||
} // ok
|
||||
else
|
||||
{
|
||||
if (FFlag::LuauFixArgumentCountMismatchAmountWithGenericTypes)
|
||||
minParams = getMinParameterCount(&state.log, paramPack);
|
||||
size_t minParams = getMinParameterCount(&state.log, paramPack);
|
||||
|
||||
bool isVariadic = false;
|
||||
if (FFlag::LuauArgCountMismatchSaysAtLeastWhenVariadic)
|
||||
{
|
||||
std::optional<TypePackId> tail = flatten(paramPack, state.log).second;
|
||||
if (tail)
|
||||
isVariadic = Luau::isVariadic(*tail);
|
||||
}
|
||||
std::optional<TypePackId> tail = flatten(paramPack, state.log).second;
|
||||
bool isVariadic = tail && Luau::isVariadic(*tail);
|
||||
|
||||
state.reportError(TypeError{state.location, CountMismatch{minParams, paramIndex, CountMismatch::Context::Arg, isVariadic}});
|
||||
return;
|
||||
|
@ -3863,7 +3813,8 @@ ExprResult<TypePackId> TypeChecker::checkExprPack(const ScopePtr& scope, const A
|
|||
actualFunctionType = instantiate(scope, functionType, expr.func->location);
|
||||
}
|
||||
|
||||
actualFunctionType = follow(actualFunctionType);
|
||||
if (!FFlag::LuauInstantiateFollows)
|
||||
actualFunctionType = follow(actualFunctionType);
|
||||
|
||||
TypePackId retPack;
|
||||
if (FFlag::LuauLowerBoundsCalculation || !FFlag::LuauWidenIfSupertypeIsFree2)
|
||||
|
@ -3930,16 +3881,13 @@ ExprResult<TypePackId> TypeChecker::checkExprPack(const ScopePtr& scope, const A
|
|||
|
||||
reportOverloadResolutionError(scope, expr, retPack, argPack, argLocations, overloads, overloadsThatMatchArgCount, errors);
|
||||
|
||||
if (FFlag::LuauErrorRecoveryType)
|
||||
{
|
||||
const FunctionTypeVar* overload = nullptr;
|
||||
if (!overloadsThatMatchArgCount.empty())
|
||||
overload = get<FunctionTypeVar>(overloadsThatMatchArgCount[0]);
|
||||
if (!overload && !overloadsThatDont.empty())
|
||||
overload = get<FunctionTypeVar>(overloadsThatDont[0]);
|
||||
if (overload)
|
||||
return {errorRecoveryTypePack(overload->retType)};
|
||||
}
|
||||
const FunctionTypeVar* overload = nullptr;
|
||||
if (!overloadsThatMatchArgCount.empty())
|
||||
overload = get<FunctionTypeVar>(overloadsThatMatchArgCount[0]);
|
||||
if (!overload && !overloadsThatDont.empty())
|
||||
overload = get<FunctionTypeVar>(overloadsThatDont[0]);
|
||||
if (overload)
|
||||
return {errorRecoveryTypePack(overload->retType)};
|
||||
|
||||
return {errorRecoveryTypePack(retPack)};
|
||||
}
|
||||
|
@ -4129,7 +4077,7 @@ std::optional<ExprResult<TypePackId>> TypeChecker::checkCallOverload(const Scope
|
|||
|
||||
if (!argMismatch)
|
||||
overloadsThatMatchArgCount.push_back(fn);
|
||||
else if (FFlag::LuauErrorRecoveryType)
|
||||
else
|
||||
overloadsThatDont.push_back(fn);
|
||||
|
||||
errors.emplace_back(std::move(state.errors), args->head, ftv);
|
||||
|
@ -4715,7 +4663,7 @@ bool Anyification::isDirty(TypeId ty)
|
|||
return false;
|
||||
|
||||
if (const TableTypeVar* ttv = log->getMutable<TableTypeVar>(ty))
|
||||
return (ttv->state == TableState::Free || (FFlag::LuauSealExports && ttv->state == TableState::Unsealed));
|
||||
return (ttv->state == TableState::Free || ttv->state == TableState::Unsealed);
|
||||
else if (log->getMutable<FreeTypeVar>(ty))
|
||||
return true;
|
||||
else if (get<ConstrainedTypeVar>(ty))
|
||||
|
@ -4743,12 +4691,9 @@ TypeId Anyification::clean(TypeId ty)
|
|||
TableTypeVar clone = TableTypeVar{ttv->props, ttv->indexer, ttv->level, TableState::Sealed};
|
||||
clone.methodDefinitionLocations = ttv->methodDefinitionLocations;
|
||||
clone.definitionModuleName = ttv->definitionModuleName;
|
||||
if (FFlag::LuauSealExports)
|
||||
{
|
||||
clone.name = ttv->name;
|
||||
clone.syntheticName = ttv->syntheticName;
|
||||
clone.tags = ttv->tags;
|
||||
}
|
||||
clone.name = ttv->name;
|
||||
clone.syntheticName = ttv->syntheticName;
|
||||
clone.tags = ttv->tags;
|
||||
TypeId res = addType(std::move(clone));
|
||||
asMutable(res)->normal = ty->normal;
|
||||
return res;
|
||||
|
@ -4791,9 +4736,12 @@ TypeId TypeChecker::quantify(const ScopePtr& scope, TypeId ty, Location location
|
|||
|
||||
TypeId TypeChecker::instantiate(const ScopePtr& scope, TypeId ty, Location location, const TxnLog* log)
|
||||
{
|
||||
if (FFlag::LuauInstantiateFollows)
|
||||
ty = follow(ty);
|
||||
|
||||
if (FFlag::LuauTypecheckOptPass)
|
||||
{
|
||||
const FunctionTypeVar* ftv = get<FunctionTypeVar>(follow(ty));
|
||||
const FunctionTypeVar* ftv = get<FunctionTypeVar>(FFlag::LuauInstantiateFollows ? ty : follow(ty));
|
||||
if (ftv && ftv->hasNoGenerics)
|
||||
return ty;
|
||||
}
|
||||
|
@ -5175,8 +5123,6 @@ TypeId TypeChecker::resolveType(const ScopePtr& scope, const AstType& annotation
|
|||
{
|
||||
reportError(TypeError{annotation.location, GenericError{"Type parameter list is required"}});
|
||||
parameterCountErrorReported = true;
|
||||
if (!FFlag::LuauErrorRecoveryType)
|
||||
return errorRecoveryType(scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5294,33 +5240,25 @@ TypeId TypeChecker::resolveType(const ScopePtr& scope, const AstType& annotation
|
|||
reportError(
|
||||
TypeError{annotation.location, IncorrectGenericParameterCount{lit->name.value, *tf, typeParams.size(), typePackParams.size()}});
|
||||
|
||||
if (FFlag::LuauErrorRecoveryType)
|
||||
{
|
||||
// Pad the types out with error recovery types
|
||||
while (typeParams.size() < tf->typeParams.size())
|
||||
typeParams.push_back(errorRecoveryType(scope));
|
||||
while (typePackParams.size() < tf->typePackParams.size())
|
||||
typePackParams.push_back(errorRecoveryTypePack(scope));
|
||||
}
|
||||
else
|
||||
return errorRecoveryType(scope);
|
||||
// Pad the types out with error recovery types
|
||||
while (typeParams.size() < tf->typeParams.size())
|
||||
typeParams.push_back(errorRecoveryType(scope));
|
||||
while (typePackParams.size() < tf->typePackParams.size())
|
||||
typePackParams.push_back(errorRecoveryTypePack(scope));
|
||||
}
|
||||
|
||||
if (FFlag::LuauRecursiveTypeParameterRestriction)
|
||||
{
|
||||
bool sameTys = std::equal(typeParams.begin(), typeParams.end(), tf->typeParams.begin(), tf->typeParams.end(), [](auto&& itp, auto&& tp) {
|
||||
return itp == tp.ty;
|
||||
bool sameTys = std::equal(typeParams.begin(), typeParams.end(), tf->typeParams.begin(), tf->typeParams.end(), [](auto&& itp, auto&& tp) {
|
||||
return itp == tp.ty;
|
||||
});
|
||||
bool sameTps = std::equal(
|
||||
typePackParams.begin(), typePackParams.end(), tf->typePackParams.begin(), tf->typePackParams.end(), [](auto&& itpp, auto&& tpp) {
|
||||
return itpp == tpp.tp;
|
||||
});
|
||||
bool sameTps = std::equal(
|
||||
typePackParams.begin(), typePackParams.end(), tf->typePackParams.begin(), tf->typePackParams.end(), [](auto&& itpp, auto&& tpp) {
|
||||
return itpp == tpp.tp;
|
||||
});
|
||||
|
||||
// If the generic parameters and the type arguments are the same, we are about to
|
||||
// perform an identity substitution, which we can just short-circuit.
|
||||
if (sameTys && sameTps)
|
||||
return tf->type;
|
||||
}
|
||||
// If the generic parameters and the type arguments are the same, we are about to
|
||||
// perform an identity substitution, which we can just short-circuit.
|
||||
if (sameTys && sameTps)
|
||||
return tf->type;
|
||||
|
||||
return instantiateTypeFun(scope, *tf, typeParams, typePackParams, annotation.location);
|
||||
}
|
||||
|
@ -5483,7 +5421,7 @@ bool ApplyTypeFunction::isDirty(TypeId ty)
|
|||
return true;
|
||||
else if (const FreeTypeVar* ftv = get<FreeTypeVar>(ty))
|
||||
{
|
||||
if (FFlag::LuauRecursiveTypeParameterRestriction && ftv->forwardedTypeAlias)
|
||||
if (ftv->forwardedTypeAlias)
|
||||
encounteredForwardedType = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -5562,7 +5500,7 @@ TypeId TypeChecker::instantiateTypeFun(const ScopePtr& scope, const TypeFun& tf,
|
|||
reportError(location, UnificationTooComplex{});
|
||||
return errorRecoveryType(scope);
|
||||
}
|
||||
if (FFlag::LuauRecursiveTypeParameterRestriction && applyTypeFunction.encounteredForwardedType)
|
||||
if (applyTypeFunction.encounteredForwardedType)
|
||||
{
|
||||
reportError(TypeError{location, GenericError{"Recursive type being used with different parameters"}});
|
||||
return errorRecoveryType(scope);
|
||||
|
@ -5632,7 +5570,7 @@ GenericTypeDefinitions TypeChecker::createGenericTypes(const ScopePtr& scope, st
|
|||
}
|
||||
|
||||
TypeId g;
|
||||
if (FFlag::LuauRecursiveTypeParameterRestriction && (!FFlag::LuauGenericFunctionsDontCacheTypeParams || useCache))
|
||||
if (useCache)
|
||||
{
|
||||
TypeId& cached = scope->parent->typeAliasTypeParameters[n];
|
||||
if (!cached)
|
||||
|
@ -5667,21 +5605,12 @@ GenericTypeDefinitions TypeChecker::createGenericTypes(const ScopePtr& scope, st
|
|||
reportError(TypeError{node.location, DuplicateGenericParameter{n}});
|
||||
}
|
||||
|
||||
TypePackId g;
|
||||
if (FFlag::LuauRecursiveTypeParameterRestriction)
|
||||
{
|
||||
TypePackId& cached = scope->parent->typeAliasTypePackParameters[n];
|
||||
if (!cached)
|
||||
cached = addTypePack(TypePackVar{Unifiable::Generic{level, n}});
|
||||
g = cached;
|
||||
}
|
||||
else
|
||||
{
|
||||
g = addTypePack(TypePackVar{Unifiable::Generic{level, n}});
|
||||
}
|
||||
TypePackId& cached = scope->parent->typeAliasTypePackParameters[n];
|
||||
if (!cached)
|
||||
cached = addTypePack(TypePackVar{Unifiable::Generic{level, n}});
|
||||
|
||||
genericPacks.push_back({g, defaultValue});
|
||||
scope->privateTypePackBindings[n] = g;
|
||||
genericPacks.push_back({cached, defaultValue});
|
||||
scope->privateTypePackBindings[n] = cached;
|
||||
}
|
||||
|
||||
return {generics, genericPacks};
|
||||
|
|
|
@ -23,7 +23,6 @@ LUAU_FASTFLAG(DebugLuauFreezeArena)
|
|||
LUAU_FASTINTVARIABLE(LuauTypeMaximumStringifierLength, 500)
|
||||
LUAU_FASTINTVARIABLE(LuauTableTypeMaximumStringifierLength, 0)
|
||||
LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
||||
LUAU_FASTFLAG(LuauErrorRecoveryType)
|
||||
LUAU_FASTFLAG(LuauSubtypingAddOptPropsToUnsealedTables)
|
||||
LUAU_FASTFLAG(LuauDiscriminableUnions2)
|
||||
LUAU_FASTFLAGVARIABLE(LuauAnyInIsOptionalIsOptional, false)
|
||||
|
@ -775,18 +774,12 @@ TypePackId SingletonTypes::errorRecoveryTypePack()
|
|||
|
||||
TypeId SingletonTypes::errorRecoveryType(TypeId guess)
|
||||
{
|
||||
if (FFlag::LuauErrorRecoveryType)
|
||||
return guess;
|
||||
else
|
||||
return &errorType_;
|
||||
return guess;
|
||||
}
|
||||
|
||||
TypePackId SingletonTypes::errorRecoveryTypePack(TypePackId guess)
|
||||
{
|
||||
if (FFlag::LuauErrorRecoveryType)
|
||||
return guess;
|
||||
else
|
||||
return &errorTypePack_;
|
||||
return guess;
|
||||
}
|
||||
|
||||
SingletonTypes& getSingletonTypes()
|
||||
|
|
|
@ -23,10 +23,7 @@ LUAU_FASTFLAG(LuauErrorRecoveryType);
|
|||
LUAU_FASTFLAGVARIABLE(LuauSubtypingAddOptPropsToUnsealedTables, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauWidenIfSupertypeIsFree2, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauDifferentOrderOfUnificationDoesntMatter, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTxnLogSeesTypePacks2, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTxnLogCheckForInvalidation, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTxnLogRefreshFunctionPointers, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTxnLogDontRetryForIndexers, false)
|
||||
LUAU_FASTFLAG(LuauAnyInIsOptionalIsOptional)
|
||||
LUAU_FASTFLAG(LuauTypecheckOptPass)
|
||||
|
||||
|
@ -1021,7 +1018,7 @@ void Unifier::tryUnify_(TypePackId subTp, TypePackId superTp, bool isFunctionCal
|
|||
if (superTp == subTp)
|
||||
return;
|
||||
|
||||
if (FFlag::LuauTxnLogSeesTypePacks2 && log.haveSeen(superTp, subTp))
|
||||
if (log.haveSeen(superTp, subTp))
|
||||
return;
|
||||
|
||||
if (log.getMutable<Unifiable::Free>(superTp))
|
||||
|
@ -1265,12 +1262,9 @@ void Unifier::tryUnifyFunctions(TypeId subTy, TypeId superTy, bool isFunctionCal
|
|||
log.pushSeen(superFunction->generics[i], subFunction->generics[i]);
|
||||
}
|
||||
|
||||
if (FFlag::LuauTxnLogSeesTypePacks2)
|
||||
for (size_t i = 0; i < numGenericPacks; i++)
|
||||
{
|
||||
for (size_t i = 0; i < numGenericPacks; i++)
|
||||
{
|
||||
log.pushSeen(superFunction->genericPacks[i], subFunction->genericPacks[i]);
|
||||
}
|
||||
log.pushSeen(superFunction->genericPacks[i], subFunction->genericPacks[i]);
|
||||
}
|
||||
|
||||
CountMismatch::Context context = ctx;
|
||||
|
@ -1330,12 +1324,9 @@ void Unifier::tryUnifyFunctions(TypeId subTy, TypeId superTy, bool isFunctionCal
|
|||
|
||||
ctx = context;
|
||||
|
||||
if (FFlag::LuauTxnLogSeesTypePacks2)
|
||||
for (int i = int(numGenericPacks) - 1; 0 <= i; i--)
|
||||
{
|
||||
for (int i = int(numGenericPacks) - 1; 0 <= i; i--)
|
||||
{
|
||||
log.popSeen(superFunction->genericPacks[i], subFunction->genericPacks[i]);
|
||||
}
|
||||
log.popSeen(superFunction->genericPacks[i], subFunction->genericPacks[i]);
|
||||
}
|
||||
|
||||
for (int i = int(numGenerics) - 1; 0 <= i; i--)
|
||||
|
@ -1499,20 +1490,17 @@ void Unifier::tryUnifyTables(TypeId subTy, TypeId superTy, bool isIntersection)
|
|||
else
|
||||
missingProperties.push_back(name);
|
||||
|
||||
if (FFlag::LuauTxnLogCheckForInvalidation)
|
||||
// Recursive unification can change the txn log, and invalidate the old
|
||||
// table. If we detect that this has happened, we start over, with the updated
|
||||
// txn log.
|
||||
TableTypeVar* newSuperTable = log.getMutable<TableTypeVar>(superTy);
|
||||
TableTypeVar* newSubTable = log.getMutable<TableTypeVar>(subTy);
|
||||
if (superTable != newSuperTable || subTable != newSubTable)
|
||||
{
|
||||
// Recursive unification can change the txn log, and invalidate the old
|
||||
// table. If we detect that this has happened, we start over, with the updated
|
||||
// txn log.
|
||||
TableTypeVar* newSuperTable = log.getMutable<TableTypeVar>(superTy);
|
||||
TableTypeVar* newSubTable = log.getMutable<TableTypeVar>(subTy);
|
||||
if (superTable != newSuperTable || subTable != newSubTable)
|
||||
{
|
||||
if (errors.empty())
|
||||
return tryUnifyTables(subTy, superTy, isIntersection);
|
||||
else
|
||||
return;
|
||||
}
|
||||
if (errors.empty())
|
||||
return tryUnifyTables(subTy, superTy, isIntersection);
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1570,20 +1558,17 @@ void Unifier::tryUnifyTables(TypeId subTy, TypeId superTy, bool isIntersection)
|
|||
else
|
||||
extraProperties.push_back(name);
|
||||
|
||||
if (FFlag::LuauTxnLogCheckForInvalidation)
|
||||
// Recursive unification can change the txn log, and invalidate the old
|
||||
// table. If we detect that this has happened, we start over, with the updated
|
||||
// txn log.
|
||||
TableTypeVar* newSuperTable = log.getMutable<TableTypeVar>(superTy);
|
||||
TableTypeVar* newSubTable = log.getMutable<TableTypeVar>(subTy);
|
||||
if (superTable != newSuperTable || subTable != newSubTable)
|
||||
{
|
||||
// Recursive unification can change the txn log, and invalidate the old
|
||||
// table. If we detect that this has happened, we start over, with the updated
|
||||
// txn log.
|
||||
TableTypeVar* newSuperTable = log.getMutable<TableTypeVar>(superTy);
|
||||
TableTypeVar* newSubTable = log.getMutable<TableTypeVar>(subTy);
|
||||
if (superTable != newSuperTable || subTable != newSubTable)
|
||||
{
|
||||
if (errors.empty())
|
||||
return tryUnifyTables(subTy, superTy, isIntersection);
|
||||
else
|
||||
return;
|
||||
}
|
||||
if (errors.empty())
|
||||
return tryUnifyTables(subTy, superTy, isIntersection);
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1630,27 +1615,9 @@ void Unifier::tryUnifyTables(TypeId subTy, TypeId superTy, bool isIntersection)
|
|||
}
|
||||
}
|
||||
|
||||
if (FFlag::LuauTxnLogDontRetryForIndexers)
|
||||
{
|
||||
// Changing the indexer can invalidate the table pointers.
|
||||
superTable = log.getMutable<TableTypeVar>(superTy);
|
||||
subTable = log.getMutable<TableTypeVar>(subTy);
|
||||
}
|
||||
else if (FFlag::LuauTxnLogCheckForInvalidation)
|
||||
{
|
||||
// Recursive unification can change the txn log, and invalidate the old
|
||||
// table. If we detect that this has happened, we start over, with the updated
|
||||
// txn log.
|
||||
TableTypeVar* newSuperTable = log.getMutable<TableTypeVar>(superTy);
|
||||
TableTypeVar* newSubTable = log.getMutable<TableTypeVar>(subTy);
|
||||
if (superTable != newSuperTable || subTable != newSubTable)
|
||||
{
|
||||
if (errors.empty())
|
||||
return tryUnifyTables(subTy, superTy, isIntersection);
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Changing the indexer can invalidate the table pointers.
|
||||
superTable = log.getMutable<TableTypeVar>(superTy);
|
||||
subTable = log.getMutable<TableTypeVar>(subTy);
|
||||
|
||||
if (!missingProperties.empty())
|
||||
{
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauParseLocationIgnoreCommentSkip, false)
|
||||
|
||||
namespace Luau
|
||||
{
|
||||
|
||||
|
@ -361,7 +359,7 @@ const Lexeme& Lexer::next(bool skipComments, bool updatePrevLocation)
|
|||
while (isSpace(peekch()))
|
||||
consume();
|
||||
|
||||
if (!FFlag::LuauParseLocationIgnoreCommentSkip || updatePrevLocation)
|
||||
if (updatePrevLocation)
|
||||
prevLocation = lexeme.location;
|
||||
|
||||
lexeme = readNext();
|
||||
|
|
|
@ -240,7 +240,7 @@ std::optional<std::string> getParentPath(const std::string& path)
|
|||
return std::nullopt;
|
||||
#endif
|
||||
|
||||
std::string::size_type slash = path.find_last_of("\\/", path.size() - 1);
|
||||
size_t slash = path.find_last_of("\\/", path.size() - 1);
|
||||
|
||||
if (slash == 0)
|
||||
return "/";
|
||||
|
@ -253,7 +253,7 @@ std::optional<std::string> getParentPath(const std::string& path)
|
|||
|
||||
static std::string getExtension(const std::string& path)
|
||||
{
|
||||
std::string::size_type dot = path.find_last_of(".\\/");
|
||||
size_t dot = path.find_last_of(".\\/");
|
||||
|
||||
if (dot == std::string::npos || path[dot] != '.')
|
||||
return "";
|
||||
|
|
|
@ -34,7 +34,8 @@ enum class CliMode
|
|||
enum class CompileFormat
|
||||
{
|
||||
Text,
|
||||
Binary
|
||||
Binary,
|
||||
Null
|
||||
};
|
||||
|
||||
constexpr int MaxTraversalLimit = 50;
|
||||
|
@ -594,6 +595,8 @@ static bool compileFile(const char* name, CompileFormat format)
|
|||
case CompileFormat::Binary:
|
||||
fwrite(bcb.getBytecode().data(), 1, bcb.getBytecode().size(), stdout);
|
||||
break;
|
||||
case CompileFormat::Null:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -716,6 +719,10 @@ int replMain(int argc, char** argv)
|
|||
{
|
||||
compileFormat = CompileFormat::Text;
|
||||
}
|
||||
else if (strcmp(argv[1], "--compile=null") == 0)
|
||||
{
|
||||
compileFormat = CompileFormat::Null;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: Unrecognized value for '--compile' specified.\n");
|
||||
|
|
|
@ -232,7 +232,7 @@ private:
|
|||
|
||||
DenseHashMap<StringRef, unsigned int, StringRefHash> stringTable;
|
||||
|
||||
DenseHashMap<uint32_t, uint32_t> debugRemarks;
|
||||
std::vector<std::pair<uint32_t, uint32_t>> debugRemarks;
|
||||
std::string debugRemarkBuffer;
|
||||
|
||||
BytecodeEncoder* encoder = nullptr;
|
||||
|
|
|
@ -181,7 +181,6 @@ BytecodeBuilder::BytecodeBuilder(BytecodeEncoder* encoder)
|
|||
: constantMap({Constant::Type_Nil, ~0ull})
|
||||
, tableShapeMap(TableShape())
|
||||
, stringTable({nullptr, 0})
|
||||
, debugRemarks(~0u)
|
||||
, encoder(encoder)
|
||||
{
|
||||
LUAU_ASSERT(stringTable.find(StringRef{"", 0}) == nullptr);
|
||||
|
@ -257,6 +256,8 @@ void BytecodeBuilder::endFunction(uint8_t maxstacksize, uint8_t numupvalues)
|
|||
|
||||
void BytecodeBuilder::setMainFunction(uint32_t fid)
|
||||
{
|
||||
LUAU_ASSERT(fid < functions.size());
|
||||
|
||||
mainFunction = fid;
|
||||
}
|
||||
|
||||
|
@ -531,7 +532,7 @@ void BytecodeBuilder::addDebugRemark(const char* format, ...)
|
|||
// we null-terminate all remarks to avoid storing remark length
|
||||
debugRemarkBuffer += '\0';
|
||||
|
||||
debugRemarks[uint32_t(insns.size())] = uint32_t(offset);
|
||||
debugRemarks.emplace_back(uint32_t(insns.size()), uint32_t(offset));
|
||||
}
|
||||
|
||||
void BytecodeBuilder::finalize()
|
||||
|
@ -1719,6 +1720,7 @@ std::string BytecodeBuilder::dumpCurrentFunction() const
|
|||
const uint32_t* codeEnd = insns.data() + insns.size();
|
||||
|
||||
int lastLine = -1;
|
||||
size_t nextRemark = 0;
|
||||
|
||||
std::string result;
|
||||
|
||||
|
@ -1741,6 +1743,7 @@ std::string BytecodeBuilder::dumpCurrentFunction() const
|
|||
while (code != codeEnd)
|
||||
{
|
||||
uint8_t op = LUAU_INSN_OP(*code);
|
||||
uint32_t pc = uint32_t(code - insns.data());
|
||||
|
||||
if (op == LOP_PREPVARARGS)
|
||||
{
|
||||
|
@ -1751,15 +1754,16 @@ std::string BytecodeBuilder::dumpCurrentFunction() const
|
|||
|
||||
if (dumpFlags & Dump_Remarks)
|
||||
{
|
||||
const uint32_t* remark = debugRemarks.find(uint32_t(code - insns.data()));
|
||||
|
||||
if (remark)
|
||||
formatAppend(result, "REMARK %s\n", debugRemarkBuffer.c_str() + *remark);
|
||||
while (nextRemark < debugRemarks.size() && debugRemarks[nextRemark].first == pc)
|
||||
{
|
||||
formatAppend(result, "REMARK %s\n", debugRemarkBuffer.c_str() + debugRemarks[nextRemark].second);
|
||||
nextRemark++;
|
||||
}
|
||||
}
|
||||
|
||||
if (dumpFlags & Dump_Source)
|
||||
{
|
||||
int line = lines[code - insns.data()];
|
||||
int line = lines[pc];
|
||||
|
||||
if (line > 0 && line != lastLine)
|
||||
{
|
||||
|
@ -1771,7 +1775,7 @@ std::string BytecodeBuilder::dumpCurrentFunction() const
|
|||
|
||||
if (dumpFlags & Dump_Lines)
|
||||
{
|
||||
formatAppend(result, "%d: ", lines[code - insns.data()]);
|
||||
formatAppend(result, "%d: ", lines[pc]);
|
||||
}
|
||||
|
||||
code = dumpInstruction(code, result);
|
||||
|
@ -1784,11 +1788,11 @@ void BytecodeBuilder::setDumpSource(const std::string& source)
|
|||
{
|
||||
dumpSource.clear();
|
||||
|
||||
std::string::size_type pos = 0;
|
||||
size_t pos = 0;
|
||||
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
std::string::size_type next = source.find('\n', pos);
|
||||
size_t next = source.find('\n', pos);
|
||||
|
||||
if (next == std::string::npos)
|
||||
{
|
||||
|
|
|
@ -2206,9 +2206,15 @@ struct Compiler
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Variable* lv = variables.find(stat->var); lv && lv->written)
|
||||
{
|
||||
bytecode.addDebugRemark("loop unroll failed: mutable loop variable");
|
||||
return false;
|
||||
}
|
||||
|
||||
int tripCount = (to - from) / step + 1;
|
||||
|
||||
if (tripCount > thresholdBase * thresholdMaxBoost / 100)
|
||||
if (tripCount > thresholdBase)
|
||||
{
|
||||
bytecode.addDebugRemark("loop unroll failed: too many iterations (%d)", tripCount);
|
||||
return false;
|
||||
|
|
|
@ -249,7 +249,7 @@ int computeCost(uint64_t model, const bool* varsConst, size_t varCount)
|
|||
return cost;
|
||||
|
||||
for (size_t i = 0; i < varCount && i < 7; ++i)
|
||||
cost -= int((model >> (8 * i + 8)) & 0x7f) * varsConst[i];
|
||||
cost -= int((model >> (i * 8 + 8)) & 0x7f) * varsConst[i];
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
|
|
@ -220,8 +220,8 @@ if(TARGET Luau.UnitTest)
|
|||
tests/Autocomplete.test.cpp
|
||||
tests/BuiltinDefinitions.test.cpp
|
||||
tests/Compiler.test.cpp
|
||||
tests/CostModel.test.cpp
|
||||
tests/Config.test.cpp
|
||||
tests/CostModel.test.cpp
|
||||
tests/Error.test.cpp
|
||||
tests/Frontend.test.cpp
|
||||
tests/JsonEncoder.test.cpp
|
||||
|
@ -232,6 +232,7 @@ if(TARGET Luau.UnitTest)
|
|||
tests/Normalize.test.cpp
|
||||
tests/Parser.test.cpp
|
||||
tests/RequireTracer.test.cpp
|
||||
tests/RuntimeLimits.test.cpp
|
||||
tests/StringUtils.test.cpp
|
||||
tests/Symbol.test.cpp
|
||||
tests/ToDot.test.cpp
|
||||
|
|
|
@ -299,7 +299,7 @@ LUA_API uintptr_t lua_encodepointer(lua_State* L, uintptr_t p);
|
|||
|
||||
LUA_API double lua_clock();
|
||||
|
||||
LUA_API void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(void*));
|
||||
LUA_API void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*));
|
||||
|
||||
LUA_API void lua_clonefunction(lua_State* L, int idx);
|
||||
|
||||
|
|
|
@ -1323,7 +1323,7 @@ void lua_unref(lua_State* L, int ref)
|
|||
return;
|
||||
}
|
||||
|
||||
void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(void*))
|
||||
void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*))
|
||||
{
|
||||
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
|
||||
L->global->udatagc[tag] = dtor;
|
||||
|
|
|
@ -200,7 +200,7 @@ typedef struct global_State
|
|||
uint64_t rngstate; /* PCG random number generator state */
|
||||
uint64_t ptrenckey[4]; /* pointer encoding key for display */
|
||||
|
||||
void (*udatagc[LUA_UTAG_LIMIT])(void*); /* for each userdata tag, a gc callback to be called immediately before freeing memory */
|
||||
void (*udatagc[LUA_UTAG_LIMIT])(lua_State*, void*); /* for each userdata tag, a gc callback to be called immediately before freeing memory */
|
||||
|
||||
lua_Callbacks cb;
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauTableRehashRework, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTableNewBoundary2, false)
|
||||
|
||||
// max size of both array and hash part is 2^MAXBITS
|
||||
|
@ -400,16 +399,9 @@ static void resize(lua_State* L, Table* t, int nasize, int nhsize)
|
|||
{
|
||||
if (!ttisnil(&t->array[i]))
|
||||
{
|
||||
if (FFlag::LuauTableRehashRework)
|
||||
{
|
||||
TValue ok;
|
||||
setnvalue(&ok, cast_num(i + 1));
|
||||
setobjt2t(L, newkey(L, t, &ok), &t->array[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
setobjt2t(L, luaH_setnum(L, t, i + 1), &t->array[i]);
|
||||
}
|
||||
TValue ok;
|
||||
setnvalue(&ok, cast_num(i + 1));
|
||||
setobjt2t(L, newkey(L, t, &ok), &t->array[i]);
|
||||
}
|
||||
}
|
||||
/* shrink array */
|
||||
|
@ -418,30 +410,14 @@ static void resize(lua_State* L, Table* t, int nasize, int nhsize)
|
|||
/* used for the migration check at the end */
|
||||
TValue* anew = t->array;
|
||||
/* re-insert elements from hash part */
|
||||
if (FFlag::LuauTableRehashRework)
|
||||
for (int i = twoto(oldhsize) - 1; i >= 0; i--)
|
||||
{
|
||||
for (int i = twoto(oldhsize) - 1; i >= 0; i--)
|
||||
LuaNode* old = nold + i;
|
||||
if (!ttisnil(gval(old)))
|
||||
{
|
||||
LuaNode* old = nold + i;
|
||||
if (!ttisnil(gval(old)))
|
||||
{
|
||||
TValue ok;
|
||||
getnodekey(L, &ok, old);
|
||||
setobjt2t(L, arrayornewkey(L, t, &ok), gval(old));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = twoto(oldhsize) - 1; i >= 0; i--)
|
||||
{
|
||||
LuaNode* old = nold + i;
|
||||
if (!ttisnil(gval(old)))
|
||||
{
|
||||
TValue ok;
|
||||
getnodekey(L, &ok, old);
|
||||
setobjt2t(L, luaH_set(L, t, &ok), gval(old));
|
||||
}
|
||||
TValue ok;
|
||||
getnodekey(L, &ok, old);
|
||||
setobjt2t(L, arrayornewkey(L, t, &ok), gval(old));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,7 +535,7 @@ static TValue* newkey(lua_State* L, Table* t, const TValue* key)
|
|||
{
|
||||
rehash(L, t, key); /* grow table */
|
||||
|
||||
// after rehash, numeric keys might be located in the new array part, but won't be found in the node part
|
||||
/* after rehash, numeric keys might be located in the new array part, but won't be found in the node part */
|
||||
return arrayornewkey(L, t, key);
|
||||
}
|
||||
|
||||
|
@ -571,15 +547,8 @@ static TValue* newkey(lua_State* L, Table* t, const TValue* key)
|
|||
{ /* cannot find a free place? */
|
||||
rehash(L, t, key); /* grow table */
|
||||
|
||||
if (!FFlag::LuauTableRehashRework)
|
||||
{
|
||||
return luaH_set(L, t, key); /* re-insert key into grown table */
|
||||
}
|
||||
else
|
||||
{
|
||||
// after rehash, numeric keys might be located in the new array part, but won't be found in the node part
|
||||
return arrayornewkey(L, t, key);
|
||||
}
|
||||
/* after rehash, numeric keys might be located in the new array part, but won't be found in the node part */
|
||||
return arrayornewkey(L, t, key);
|
||||
}
|
||||
LUAU_ASSERT(n != dummynode);
|
||||
TValue mk;
|
||||
|
|
|
@ -22,14 +22,21 @@ Udata* luaU_newudata(lua_State* L, size_t s, int tag)
|
|||
|
||||
void luaU_freeudata(lua_State* L, Udata* u, lua_Page* page)
|
||||
{
|
||||
void (*dtor)(void*) = nullptr;
|
||||
if (u->tag < LUA_UTAG_LIMIT)
|
||||
{
|
||||
void (*dtor)(lua_State*, void*) = nullptr;
|
||||
dtor = L->global->udatagc[u->tag];
|
||||
if (dtor)
|
||||
dtor(L, u->data);
|
||||
}
|
||||
else if (u->tag == UTAG_IDTOR)
|
||||
{
|
||||
void (*dtor)(void*) = nullptr;
|
||||
memcpy(&dtor, &u->data + u->len - sizeof(dtor), sizeof(dtor));
|
||||
if (dtor)
|
||||
dtor(u->data);
|
||||
}
|
||||
|
||||
if (dtor)
|
||||
dtor(u->data);
|
||||
|
||||
luaM_freegco(L, u, sizeudata(u->len), u->memcat, page);
|
||||
}
|
||||
|
|
|
@ -137,6 +137,21 @@ int registerTypes(Luau::TypeChecker& env)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setupFrontend(Luau::Frontend& frontend)
|
||||
{
|
||||
registerTypes(frontend.typeChecker);
|
||||
Luau::freeze(frontend.typeChecker.globalTypes);
|
||||
|
||||
registerTypes(frontend.typeCheckerForAutocomplete);
|
||||
Luau::freeze(frontend.typeCheckerForAutocomplete.globalTypes);
|
||||
|
||||
frontend.iceHandler.onInternalError = [](const char* error) {
|
||||
printf("ICE: %s\n", error);
|
||||
LUAU_ASSERT(!"ICE");
|
||||
};
|
||||
}
|
||||
|
||||
struct FuzzFileResolver : Luau::FileResolver
|
||||
{
|
||||
std::optional<Luau::SourceCode> readSource(const Luau::ModuleName& name) override
|
||||
|
@ -238,19 +253,11 @@ DEFINE_PROTO_FUZZER(const luau::ModuleSet& message)
|
|||
if (kFuzzTypeck)
|
||||
{
|
||||
static FuzzFileResolver fileResolver;
|
||||
static Luau::NullConfigResolver configResolver;
|
||||
static FuzzConfigResolver configResolver;
|
||||
static Luau::FrontendOptions options{true, true};
|
||||
static Luau::Frontend frontend(&fileResolver, &configResolver, options);
|
||||
|
||||
static int once = registerTypes(frontend.typeChecker);
|
||||
(void)once;
|
||||
static int once2 = (Luau::freeze(frontend.typeChecker.globalTypes), 0);
|
||||
(void)once2;
|
||||
|
||||
frontend.iceHandler.onInternalError = [](const char* error) {
|
||||
printf("ICE: %s\n", error);
|
||||
LUAU_ASSERT(!"ICE");
|
||||
};
|
||||
static int once = (setupFrontend(frontend), 0);
|
||||
|
||||
// restart
|
||||
frontend.clear();
|
||||
|
|
|
@ -2761,7 +2761,6 @@ TEST_CASE_FIXTURE(ACFixture, "autocomplete_on_string_singletons")
|
|||
TEST_CASE_FIXTURE(ACFixture, "autocomplete_string_singletons")
|
||||
{
|
||||
ScopedFastFlag luauAutocompleteSingletonTypes{"LuauAutocompleteSingletonTypes", true};
|
||||
ScopedFastFlag luauExpectedTypesOfProperties{"LuauExpectedTypesOfProperties", true};
|
||||
|
||||
check(R"(
|
||||
type tag = "cat" | "dog"
|
||||
|
|
|
@ -2698,16 +2698,22 @@ TEST_CASE("DebugRemarks")
|
|||
|
||||
uint32_t fid = bcb.beginFunction(0);
|
||||
|
||||
bcb.addDebugRemark("test remark #%d", 42);
|
||||
bcb.addDebugRemark("test remark #%d", 1);
|
||||
bcb.emitABC(LOP_LOADNIL, 0, 0, 0);
|
||||
bcb.addDebugRemark("test remark #%d", 2);
|
||||
bcb.addDebugRemark("test remark #%d", 3);
|
||||
bcb.emitABC(LOP_RETURN, 0, 1, 0);
|
||||
|
||||
bcb.endFunction(0, 0);
|
||||
bcb.endFunction(1, 0);
|
||||
|
||||
bcb.setMainFunction(fid);
|
||||
bcb.finalize();
|
||||
|
||||
CHECK_EQ("\n" + bcb.dumpFunction(0), R"(
|
||||
REMARK test remark #42
|
||||
REMARK test remark #1
|
||||
LOADNIL R0
|
||||
REMARK test remark #2
|
||||
REMARK test remark #3
|
||||
RETURN R0 0
|
||||
)");
|
||||
}
|
||||
|
@ -4332,7 +4338,7 @@ RETURN R0 1
|
|||
// loops with body that's long but has a high boost factor due to constant folding
|
||||
CHECK_EQ("\n" + compileFunction(R"(
|
||||
local t = {}
|
||||
for i=1,30 do
|
||||
for i=1,25 do
|
||||
t[i] = i * i * i
|
||||
end
|
||||
return t
|
||||
|
@ -4390,16 +4396,6 @@ LOADN R1 13824
|
|||
SETTABLEN R1 R0 24
|
||||
LOADN R1 15625
|
||||
SETTABLEN R1 R0 25
|
||||
LOADN R1 17576
|
||||
SETTABLEN R1 R0 26
|
||||
LOADN R1 19683
|
||||
SETTABLEN R1 R0 27
|
||||
LOADN R1 21952
|
||||
SETTABLEN R1 R0 28
|
||||
LOADN R1 24389
|
||||
SETTABLEN R1 R0 29
|
||||
LOADN R1 27000
|
||||
SETTABLEN R1 R0 30
|
||||
RETURN R0 1
|
||||
)");
|
||||
|
||||
|
@ -4431,4 +4427,30 @@ RETURN R0 1
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_CASE("LoopUnrollMutable")
|
||||
{
|
||||
// can't unroll loops that mutate iteration variable
|
||||
CHECK_EQ("\n" + compileFunction(R"(
|
||||
for i=1,3 do
|
||||
i = 3
|
||||
print(i) -- should print 3 three times in a row
|
||||
end
|
||||
)",
|
||||
0, 2),
|
||||
R"(
|
||||
LOADN R2 1
|
||||
LOADN R0 3
|
||||
LOADN R1 1
|
||||
FORNPREP R0 +7
|
||||
MOVE R3 R2
|
||||
LOADN R3 3
|
||||
GETIMPORT R4 1
|
||||
MOVE R5 R3
|
||||
CALL R4 1 0
|
||||
FORNLOOP R0 -7
|
||||
RETURN R0 0
|
||||
)");
|
||||
}
|
||||
|
||||
|
||||
TEST_SUITE_END();
|
||||
|