mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 14:25:44 +08:00
Sync to upstream/release/643 (#1408)
Pretty small release this week as well. ## New Solver * We now unconditionally generalize functions with explicit generics * Bugfixes for how we run builtin tests ## VM * Fixed running Luau conformance tests in LUA_VECTOR_SIZE == 4 configuration Internal Contributors: Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com> Co-authored-by: James McNellis <jmcnellis@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> --------- Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: David Cope <dcope@roblox.com> Co-authored-by: Lily Brown <lbrown@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> Co-authored-by: Junseo Yoo <jyoo@roblox.com>
This commit is contained in:
parent
f2488bdfa4
commit
b765d7bafd
@ -887,9 +887,6 @@ std::optional<TypeId> generalize(
|
|||||||
if (ty->owningArena != arena || ty->persistent)
|
if (ty->owningArena != arena || ty->persistent)
|
||||||
return ty;
|
return ty;
|
||||||
|
|
||||||
if (const FunctionType* ft = get<FunctionType>(ty); ft && (!ft->generics.empty() || !ft->genericPacks.empty()))
|
|
||||||
return ty;
|
|
||||||
|
|
||||||
FreeTypeSearcher fts{scope, cachedTypes};
|
FreeTypeSearcher fts{scope, cachedTypes};
|
||||||
fts.traverse(ty);
|
fts.traverse(ty);
|
||||||
|
|
||||||
@ -912,8 +909,17 @@ std::optional<TypeId> generalize(
|
|||||||
FunctionType* ftv = getMutable<FunctionType>(ty);
|
FunctionType* ftv = getMutable<FunctionType>(ty);
|
||||||
if (ftv)
|
if (ftv)
|
||||||
{
|
{
|
||||||
ftv->generics = std::move(gen.generics);
|
// If we're generalizing a function type, add any of the newly inferred
|
||||||
ftv->genericPacks = std::move(gen.genericPacks);
|
// generics to the list of existing generic types.
|
||||||
|
for (const auto g : std::move(gen.generics))
|
||||||
|
{
|
||||||
|
ftv->generics.push_back(g);
|
||||||
|
}
|
||||||
|
// Ditto for generic packs.
|
||||||
|
for (const auto gp : std::move(gen.genericPacks))
|
||||||
|
{
|
||||||
|
ftv->genericPacks.push_back(gp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ty;
|
return ty;
|
||||||
|
@ -107,6 +107,7 @@ std::optional<ErrorVec> OverloadResolver::testIsSubtype(const Location& location
|
|||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
errors.emplace_back(location, NormalizationTooComplex{});
|
errors.emplace_back(location, NormalizationTooComplex{});
|
||||||
// intentionally fallthrough here since we couldn't prove this was error-suppressing
|
// intentionally fallthrough here since we couldn't prove this was error-suppressing
|
||||||
|
[[fallthrough]];
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
errors.emplace_back(location, TypeMismatch{superTy, subTy});
|
errors.emplace_back(location, TypeMismatch{superTy, subTy});
|
||||||
break;
|
break;
|
||||||
@ -136,6 +137,7 @@ std::optional<ErrorVec> OverloadResolver::testIsSubtype(const Location& location
|
|||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
errors.emplace_back(location, NormalizationTooComplex{});
|
errors.emplace_back(location, NormalizationTooComplex{});
|
||||||
// intentionally fallthrough here since we couldn't prove this was error-suppressing
|
// intentionally fallthrough here since we couldn't prove this was error-suppressing
|
||||||
|
[[fallthrough]];
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
errors.emplace_back(location, TypePackMismatch{superTy, subTy});
|
errors.emplace_back(location, TypePackMismatch{superTy, subTy});
|
||||||
break;
|
break;
|
||||||
@ -301,6 +303,7 @@ std::pair<OverloadResolver::Analysis, ErrorVec> OverloadResolver::checkOverload_
|
|||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
errors.emplace_back(argLocation, NormalizationTooComplex{});
|
errors.emplace_back(argLocation, NormalizationTooComplex{});
|
||||||
// intentionally fallthrough here since we couldn't prove this was error-suppressing
|
// intentionally fallthrough here since we couldn't prove this was error-suppressing
|
||||||
|
[[fallthrough]];
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
// TODO extract location from the SubtypingResult path and argExprs
|
// TODO extract location from the SubtypingResult path and argExprs
|
||||||
switch (reason.variance)
|
switch (reason.variance)
|
||||||
|
@ -141,6 +141,7 @@ Relation combine(Relation a, Relation b)
|
|||||||
case Relation::Superset:
|
case Relation::Superset:
|
||||||
return Relation::Intersects;
|
return Relation::Intersects;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case Relation::Coincident:
|
case Relation::Coincident:
|
||||||
switch (b)
|
switch (b)
|
||||||
{
|
{
|
||||||
@ -155,6 +156,7 @@ Relation combine(Relation a, Relation b)
|
|||||||
case Relation::Superset:
|
case Relation::Superset:
|
||||||
return Relation::Intersects;
|
return Relation::Intersects;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case Relation::Superset:
|
case Relation::Superset:
|
||||||
switch (b)
|
switch (b)
|
||||||
{
|
{
|
||||||
@ -169,6 +171,7 @@ Relation combine(Relation a, Relation b)
|
|||||||
case Relation::Superset:
|
case Relation::Superset:
|
||||||
return Relation::Superset;
|
return Relation::Superset;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case Relation::Subset:
|
case Relation::Subset:
|
||||||
switch (b)
|
switch (b)
|
||||||
{
|
{
|
||||||
@ -183,6 +186,7 @@ Relation combine(Relation a, Relation b)
|
|||||||
case Relation::Superset:
|
case Relation::Superset:
|
||||||
return Relation::Intersects;
|
return Relation::Intersects;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case Relation::Intersects:
|
case Relation::Intersects:
|
||||||
switch (b)
|
switch (b)
|
||||||
{
|
{
|
||||||
@ -197,6 +201,7 @@ Relation combine(Relation a, Relation b)
|
|||||||
case Relation::Superset:
|
case Relation::Superset:
|
||||||
return Relation::Intersects;
|
return Relation::Intersects;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LUAU_UNREACHABLE();
|
LUAU_UNREACHABLE();
|
||||||
|
@ -1378,7 +1378,7 @@ void TypeChecker2::visitCall(AstExprCall* call)
|
|||||||
break;
|
break;
|
||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
reportError(NormalizationTooComplex{}, call->func->location);
|
reportError(NormalizationTooComplex{}, call->func->location);
|
||||||
// fallthrough intentional
|
[[fallthrough]];
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
reportError(OptionalValueAccess{fnTy}, call->func->location);
|
reportError(OptionalValueAccess{fnTy}, call->func->location);
|
||||||
}
|
}
|
||||||
@ -1582,7 +1582,7 @@ TypeId TypeChecker2::stripFromNilAndReport(TypeId ty, const Location& location)
|
|||||||
break;
|
break;
|
||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
reportError(NormalizationTooComplex{}, location);
|
reportError(NormalizationTooComplex{}, location);
|
||||||
// fallthrough intentional
|
[[fallthrough]];
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
reportError(OptionalValueAccess{ty}, location);
|
reportError(OptionalValueAccess{ty}, location);
|
||||||
}
|
}
|
||||||
@ -1666,7 +1666,7 @@ void TypeChecker2::visit(AstExprIndexExpr* indexExpr, ValueContext context)
|
|||||||
break;
|
break;
|
||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
reportError(NormalizationTooComplex{}, indexExpr->location);
|
reportError(NormalizationTooComplex{}, indexExpr->location);
|
||||||
// fallthrough intentional
|
[[fallthrough]];
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
reportError(OptionalValueAccess{exprType}, indexExpr->location);
|
reportError(OptionalValueAccess{exprType}, indexExpr->location);
|
||||||
}
|
}
|
||||||
@ -2723,6 +2723,7 @@ void TypeChecker2::explainError(TypeId subTy, TypeId superTy, Location location,
|
|||||||
return;
|
return;
|
||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
reportError(NormalizationTooComplex{}, location);
|
reportError(NormalizationTooComplex{}, location);
|
||||||
|
break;
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2741,6 +2742,7 @@ void TypeChecker2::explainError(TypePackId subTy, TypePackId superTy, Location l
|
|||||||
return;
|
return;
|
||||||
case ErrorSuppression::NormalizationFailed:
|
case ErrorSuppression::NormalizationFailed:
|
||||||
reportError(NormalizationTooComplex{}, location);
|
reportError(NormalizationTooComplex{}, location);
|
||||||
|
break;
|
||||||
case ErrorSuppression::DoNotSuppress:
|
case ErrorSuppression::DoNotSuppress:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2751,7 +2751,7 @@ TypeId TypeChecker::checkRelationalOperation(
|
|||||||
if (lhsIsAny || rhsIsAny)
|
if (lhsIsAny || rhsIsAny)
|
||||||
return booleanType;
|
return booleanType;
|
||||||
|
|
||||||
// Fallthrough here is intentional
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
case AstExprBinary::CompareLt:
|
case AstExprBinary::CompareLt:
|
||||||
case AstExprBinary::CompareGt:
|
case AstExprBinary::CompareGt:
|
||||||
|
@ -784,6 +784,7 @@ AstStat* Parser::parseAttributeStat()
|
|||||||
AstExpr* expr = parsePrimaryExpr(/* asStatement= */ true);
|
AstExpr* expr = parsePrimaryExpr(/* asStatement= */ true);
|
||||||
return parseDeclaration(expr->location, attributes);
|
return parseDeclaration(expr->location, attributes);
|
||||||
}
|
}
|
||||||
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
return reportStatError(
|
return reportStatError(
|
||||||
lexer.current().location,
|
lexer.current().location,
|
||||||
|
@ -204,7 +204,18 @@ void RequireResolver::substituteAliasIfPresent(std::string& path)
|
|||||||
{
|
{
|
||||||
if (path.size() < 1 || path[0] != '@')
|
if (path.size() < 1 || path[0] != '@')
|
||||||
return;
|
return;
|
||||||
std::string potentialAlias = path.substr(1, path.find_first_of("\\/"));
|
|
||||||
|
// To ignore the '@' alias prefix when processing the alias
|
||||||
|
const size_t aliasStartPos = 1;
|
||||||
|
|
||||||
|
// If a directory separator was found, the length of the alias is the
|
||||||
|
// distance between the start of the alias and the separator. Otherwise,
|
||||||
|
// the whole string after the alias symbol is the alias.
|
||||||
|
size_t aliasLen = path.find_first_of("\\/");
|
||||||
|
if (aliasLen != std::string::npos)
|
||||||
|
aliasLen -= aliasStartPos;
|
||||||
|
|
||||||
|
const std::string potentialAlias = path.substr(aliasStartPos, aliasLen);
|
||||||
|
|
||||||
// Not worth searching when potentialAlias cannot be an alias
|
// Not worth searching when potentialAlias cannot be an alias
|
||||||
if (!Luau::isValidAlias(potentialAlias))
|
if (!Luau::isValidAlias(potentialAlias))
|
||||||
|
@ -111,6 +111,7 @@ if(MSVC)
|
|||||||
list(APPEND LUAU_OPTIONS "/we4388") # Also signed/unsigned mismatch
|
list(APPEND LUAU_OPTIONS "/we4388") # Also signed/unsigned mismatch
|
||||||
else()
|
else()
|
||||||
list(APPEND LUAU_OPTIONS -Wall) # All warnings
|
list(APPEND LUAU_OPTIONS -Wall) # All warnings
|
||||||
|
list(APPEND LUAU_OPTIONS -Wimplicit-fallthrough)
|
||||||
list(APPEND LUAU_OPTIONS -Wsign-compare) # This looks to be included in -Wall for GCC but not clang
|
list(APPEND LUAU_OPTIONS -Wsign-compare) # This looks to be included in -Wall for GCC but not clang
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -20,6 +20,19 @@
|
|||||||
#define LUAU_DEBUGBREAK() __builtin_trap()
|
#define LUAU_DEBUGBREAK() __builtin_trap()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// LUAU_FALLTHROUGH is a C++11-compatible alternative to [[fallthrough]] for use in the VM library
|
||||||
|
#if defined(__clang__) && defined(__has_warning)
|
||||||
|
#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
|
||||||
|
#define LUAU_FALLTHROUGH [[clang::fallthrough]]
|
||||||
|
#else
|
||||||
|
#define LUAU_FALLTHROUGH
|
||||||
|
#endif
|
||||||
|
#elif defined(__GNUC__) && __GNUC__ >= 7
|
||||||
|
#define LUAU_FALLTHROUGH [[gnu::fallthrough]]
|
||||||
|
#else
|
||||||
|
#define LUAU_FALLTHROUGH
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
#define LUAU_BIG_ENDIAN
|
#define LUAU_BIG_ENDIAN
|
||||||
#endif
|
#endif
|
||||||
|
@ -552,9 +552,9 @@ init: // using goto's to optimize tail recursion
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '+': // 1 or more repetitions
|
case '+': // 1 or more repetitions
|
||||||
s++; // 1 match already done
|
s++; // 1 match already done
|
||||||
// go through
|
LUAU_FALLTHROUGH; // go through
|
||||||
case '*': // 0 or more repetitions
|
case '*': // 0 or more repetitions
|
||||||
s = max_expand(ms, s, p, ep);
|
s = max_expand(ms, s, p, ep);
|
||||||
break;
|
break;
|
||||||
@ -1480,7 +1480,8 @@ static int str_pack(lua_State* L)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Kpadding:
|
case Kpadding:
|
||||||
luaL_addchar(&b, LUAL_PACKPADBYTE); // FALLTHROUGH
|
luaL_addchar(&b, LUAL_PACKPADBYTE);
|
||||||
|
LUAU_FALLTHROUGH;
|
||||||
case Kpaddalign:
|
case Kpaddalign:
|
||||||
case Knop:
|
case Knop:
|
||||||
arg--; // undo increment
|
arg--; // undo increment
|
||||||
|
@ -659,7 +659,7 @@ const TValue* luaH_get(Table* t, const TValue* key)
|
|||||||
luai_num2int(k, n);
|
luai_num2int(k, n);
|
||||||
if (luai_numeq(cast_num(k), nvalue(key))) // index is int?
|
if (luai_numeq(cast_num(k), nvalue(key))) // index is int?
|
||||||
return luaH_getnum(t, k); // use specialized version
|
return luaH_getnum(t, k); // use specialized version
|
||||||
// else go through
|
LUAU_FALLTHROUGH; // else go through
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -133,7 +133,12 @@ static int lua_vector_cross(lua_State* L)
|
|||||||
const float* a = luaL_checkvector(L, 1);
|
const float* a = luaL_checkvector(L, 1);
|
||||||
const float* b = luaL_checkvector(L, 2);
|
const float* b = luaL_checkvector(L, 2);
|
||||||
|
|
||||||
|
#if LUA_VECTOR_SIZE == 4
|
||||||
|
lua_pushvector(L, a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0f);
|
||||||
|
#else
|
||||||
lua_pushvector(L, a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]);
|
lua_pushvector(L, a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,15 +149,25 @@ static int lua_vector_index(lua_State* L)
|
|||||||
|
|
||||||
if (strcmp(name, "Magnitude") == 0)
|
if (strcmp(name, "Magnitude") == 0)
|
||||||
{
|
{
|
||||||
|
#if LUA_VECTOR_SIZE == 4
|
||||||
|
lua_pushnumber(L, sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]));
|
||||||
|
#else
|
||||||
lua_pushnumber(L, sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
|
lua_pushnumber(L, sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(name, "Unit") == 0)
|
if (strcmp(name, "Unit") == 0)
|
||||||
{
|
{
|
||||||
|
#if LUA_VECTOR_SIZE == 4
|
||||||
|
float invSqrt = 1.0f / sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
|
||||||
|
|
||||||
|
lua_pushvector(L, v[0] * invSqrt, v[1] * invSqrt, v[2] * invSqrt, v[3] * invSqrt);
|
||||||
|
#else
|
||||||
float invSqrt = 1.0f / sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
float invSqrt = 1.0f / sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
|
|
||||||
lua_pushvector(L, v[0] * invSqrt, v[1] * invSqrt, v[2] * invSqrt);
|
lua_pushvector(L, v[0] * invSqrt, v[1] * invSqrt, v[2] * invSqrt);
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "Luau/AstQuery.h"
|
#include "Luau/AstQuery.h"
|
||||||
#include "Luau/BuiltinDefinitions.h"
|
#include "Luau/BuiltinDefinitions.h"
|
||||||
|
#include "Luau/Common.h"
|
||||||
#include "Luau/Constraint.h"
|
#include "Luau/Constraint.h"
|
||||||
#include "Luau/ModuleResolver.h"
|
#include "Luau/ModuleResolver.h"
|
||||||
#include "Luau/NotNull.h"
|
#include "Luau/NotNull.h"
|
||||||
@ -25,6 +26,7 @@ static const char* mainModuleName = "MainModule";
|
|||||||
LUAU_FASTFLAG(LuauSolverV2);
|
LUAU_FASTFLAG(LuauSolverV2);
|
||||||
LUAU_FASTFLAG(DebugLuauFreezeArena);
|
LUAU_FASTFLAG(DebugLuauFreezeArena);
|
||||||
LUAU_FASTFLAG(DebugLuauLogSolverToJsonFile)
|
LUAU_FASTFLAG(DebugLuauLogSolverToJsonFile)
|
||||||
|
LUAU_FASTFLAG(LuauDCRMagicFunctionTypeChecker);
|
||||||
|
|
||||||
extern std::optional<unsigned> randomSeed; // tests/main.cpp
|
extern std::optional<unsigned> randomSeed; // tests/main.cpp
|
||||||
|
|
||||||
@ -150,6 +152,8 @@ const Config& TestConfigResolver::getConfig(const ModuleName& name) const
|
|||||||
|
|
||||||
Fixture::Fixture(bool freeze, bool prepareAutocomplete)
|
Fixture::Fixture(bool freeze, bool prepareAutocomplete)
|
||||||
: sff_DebugLuauFreezeArena(FFlag::DebugLuauFreezeArena, freeze)
|
: sff_DebugLuauFreezeArena(FFlag::DebugLuauFreezeArena, freeze)
|
||||||
|
// In tests, we *always* want to register the extra magic functions for typechecking `string.format`.
|
||||||
|
, sff_LuauDCRMagicFunctionTypeChecker(FFlag::LuauDCRMagicFunctionTypeChecker, true)
|
||||||
, frontend(
|
, frontend(
|
||||||
&fileResolver,
|
&fileResolver,
|
||||||
&configResolver,
|
&configResolver,
|
||||||
|
@ -99,6 +99,7 @@ struct Fixture
|
|||||||
TypeId requireExportedType(const ModuleName& moduleName, const std::string& name);
|
TypeId requireExportedType(const ModuleName& moduleName, const std::string& name);
|
||||||
|
|
||||||
ScopedFastFlag sff_DebugLuauFreezeArena;
|
ScopedFastFlag sff_DebugLuauFreezeArena;
|
||||||
|
ScopedFastFlag sff_LuauDCRMagicFunctionTypeChecker;
|
||||||
|
|
||||||
TestFileResolver fileResolver;
|
TestFileResolver fileResolver;
|
||||||
TestConfigResolver configResolver;
|
TestConfigResolver configResolver;
|
||||||
|
@ -937,6 +937,7 @@ bb_bytecode_0:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LUA_VECTOR_SIZE == 3
|
||||||
TEST_CASE("FastcallTypeInferThroughLocal")
|
TEST_CASE("FastcallTypeInferThroughLocal")
|
||||||
{
|
{
|
||||||
CHECK_EQ(
|
CHECK_EQ(
|
||||||
@ -1045,6 +1046,7 @@ bb_bytecode_1:
|
|||||||
)"
|
)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_CASE("LoadAndMoveTypePropagation")
|
TEST_CASE("LoadAndMoveTypePropagation")
|
||||||
{
|
{
|
||||||
@ -1115,6 +1117,7 @@ bb_bytecode_4:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LUA_VECTOR_SIZE == 3
|
||||||
TEST_CASE("ArgumentTypeRefinement")
|
TEST_CASE("ArgumentTypeRefinement")
|
||||||
{
|
{
|
||||||
CHECK_EQ(
|
CHECK_EQ(
|
||||||
@ -1152,6 +1155,7 @@ bb_bytecode_0:
|
|||||||
)"
|
)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_CASE("InlineFunctionType")
|
TEST_CASE("InlineFunctionType")
|
||||||
{
|
{
|
||||||
@ -1422,6 +1426,7 @@ bb_2:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LUA_VECTOR_SIZE == 3
|
||||||
TEST_CASE("UnaryTypeResolve")
|
TEST_CASE("UnaryTypeResolve")
|
||||||
{
|
{
|
||||||
CHECK_EQ(
|
CHECK_EQ(
|
||||||
@ -1443,6 +1448,7 @@ end
|
|||||||
)"
|
)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_CASE("ForInManualAnnotation")
|
TEST_CASE("ForInManualAnnotation")
|
||||||
{
|
{
|
||||||
|
@ -436,6 +436,12 @@ TEST_CASE_FIXTURE(ReplWithPathFixture, "RequirePathWithParentAlias")
|
|||||||
assertOutputContainsAll({"true", "result from other_dependency"});
|
assertOutputContainsAll({"true", "result from other_dependency"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(ReplWithPathFixture, "RequirePathWithAliasPointingToDirectory")
|
||||||
|
{
|
||||||
|
std::string path = getLuauDirectory(PathType::Relative) + "/tests/require/with_config/src/directory_alias_requirer";
|
||||||
|
runProtectedRequire(path);
|
||||||
|
assertOutputContainsAll({"true", "result from subdirectory_dependency"});
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(ReplWithPathFixture, "RequireAliasThatDoesNotExist")
|
TEST_CASE_FIXTURE(ReplWithPathFixture, "RequireAliasThatDoesNotExist")
|
||||||
{
|
{
|
||||||
|
@ -843,7 +843,7 @@ TEST_CASE_FIXTURE(Fixture, "pick_distinct_names_for_mixed_explicit_and_implicit_
|
|||||||
|
|
||||||
if (FFlag::LuauSolverV2)
|
if (FFlag::LuauSolverV2)
|
||||||
{
|
{
|
||||||
CHECK("<a>(a, 'b) -> ()" == toString(requireType("foo")));
|
CHECK("<a>(a, unknown) -> ()" == toString(requireType("foo")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CHECK("<a, b>(a, b) -> ()" == toString(requireType("foo")));
|
CHECK("<a, b>(a, b) -> ()" == toString(requireType("foo")));
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
using namespace Luau;
|
using namespace Luau;
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauSolverV2);
|
LUAU_FASTFLAG(LuauSolverV2);
|
||||||
LUAU_FASTFLAG(LuauDCRMagicFunctionTypeChecker);
|
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("BuiltinTests");
|
TEST_SUITE_BEGIN("BuiltinTests");
|
||||||
|
|
||||||
@ -793,8 +792,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "select_with_variadic_typepack_tail_and_strin
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "string_format_as_method")
|
TEST_CASE_FIXTURE(Fixture, "string_format_as_method")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauDCRMagicFunctionTypeChecker, true};
|
|
||||||
|
|
||||||
CheckResult result = check("local _ = ('%s'):format(5)");
|
CheckResult result = check("local _ = ('%s'):format(5)");
|
||||||
|
|
||||||
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
LUAU_REQUIRE_ERROR_COUNT(1, result);
|
||||||
@ -807,7 +804,6 @@ TEST_CASE_FIXTURE(Fixture, "string_format_as_method")
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "string_format_use_correct_argument")
|
TEST_CASE_FIXTURE(Fixture, "string_format_use_correct_argument")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauDCRMagicFunctionTypeChecker, true};
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local _ = ("%s"):format("%d", "hello")
|
local _ = ("%s"):format("%d", "hello")
|
||||||
)");
|
)");
|
||||||
@ -819,7 +815,6 @@ TEST_CASE_FIXTURE(Fixture, "string_format_use_correct_argument")
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "string_format_use_correct_argument2")
|
TEST_CASE_FIXTURE(Fixture, "string_format_use_correct_argument2")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauDCRMagicFunctionTypeChecker, true};
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local _ = ("%s %d").format("%d %s", "A type error", 2)
|
local _ = ("%s %d").format("%d %s", "A type error", 2)
|
||||||
)");
|
)");
|
||||||
@ -878,7 +873,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "debug_info_is_crazy")
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "aliased_string_format")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "aliased_string_format")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauDCRMagicFunctionTypeChecker, true};
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
local fmt = string.format
|
local fmt = string.format
|
||||||
local s = fmt("%d", "oops")
|
local s = fmt("%d", "oops")
|
||||||
@ -938,7 +932,6 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "select_on_variadic")
|
|||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "string_format_report_all_type_errors_at_correct_positions")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "string_format_report_all_type_errors_at_correct_positions")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauDCRMagicFunctionTypeChecker, true};
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
("%s%d%s"):format(1, "hello", true)
|
("%s%d%s"):format(1, "hello", true)
|
||||||
string.format("%s%d%s", 1, "hello", true)
|
string.format("%s%d%s", 1, "hello", true)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "Fixture.h"
|
#include "Fixture.h"
|
||||||
|
|
||||||
|
#include "ScopedFlags.h"
|
||||||
#include "doctest.h"
|
#include "doctest.h"
|
||||||
|
|
||||||
LUAU_FASTFLAG(LuauInstantiateInSubtyping);
|
LUAU_FASTFLAG(LuauInstantiateInSubtyping);
|
||||||
@ -1419,10 +1420,19 @@ TEST_CASE_FIXTURE(Fixture, "apply_type_function_nested_generics3")
|
|||||||
LUAU_REQUIRE_NO_ERRORS(result);
|
LUAU_REQUIRE_NO_ERRORS(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "quantify_functions_with_no_generics")
|
||||||
|
{
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
function foo(f, x)
|
||||||
|
return f(x)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
CHECK("<a, b...>((a) -> (b...), a) -> (b...)" == toString(requireType("foo")));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "quantify_functions_even_if_they_have_an_explicit_generic")
|
TEST_CASE_FIXTURE(Fixture, "quantify_functions_even_if_they_have_an_explicit_generic")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauSolverV2, false};
|
|
||||||
|
|
||||||
CheckResult result = check(R"(
|
CheckResult result = check(R"(
|
||||||
function foo<X>(f, x: X)
|
function foo<X>(f, x: X)
|
||||||
return f(x)
|
return f(x)
|
||||||
@ -1432,6 +1442,17 @@ TEST_CASE_FIXTURE(Fixture, "quantify_functions_even_if_they_have_an_explicit_gen
|
|||||||
CHECK("<X, a...>((X) -> (a...), X) -> (a...)" == toString(requireType("foo")));
|
CHECK("<X, a...>((X) -> (a...), X) -> (a...)" == toString(requireType("foo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "no_extra_quantification_for_generic_functions")
|
||||||
|
{
|
||||||
|
CheckResult result = check(R"(
|
||||||
|
function foo<X, Y>(f : (X) -> Y, x: X)
|
||||||
|
return f(x)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
CHECK("<X, Y>((X) -> Y, X) -> Y" == toString(requireType("foo")));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(Fixture, "do_not_always_instantiate_generic_intersection_types")
|
TEST_CASE_FIXTURE(Fixture, "do_not_always_instantiate_generic_intersection_types")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauSolverV2, false};
|
ScopedFastFlag sff{FFlag::LuauSolverV2, false};
|
||||||
@ -1535,6 +1556,19 @@ TEST_CASE_FIXTURE(Fixture, "missing_generic_type_parameter")
|
|||||||
REQUIRE(get<UnknownSymbol>(result.errors[1]));
|
REQUIRE(get<UnknownSymbol>(result.errors[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_FIXTURE(Fixture, "generic_implicit_explicit_name_clash")
|
||||||
|
{
|
||||||
|
ScopedFastFlag _{FFlag::LuauSolverV2, true};
|
||||||
|
|
||||||
|
auto result = check(R"(
|
||||||
|
function apply<a>(func, argument: a)
|
||||||
|
return func(argument)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
CHECK("<a, b...>((a) -> (b...), a) -> (b...)" == toString(requireType("apply")));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(BuiltinsFixture, "generic_type_functions_work_in_subtyping")
|
TEST_CASE_FIXTURE(BuiltinsFixture, "generic_type_functions_work_in_subtyping")
|
||||||
{
|
{
|
||||||
ScopedFastFlag sff{FFlag::LuauSolverV2, false};
|
ScopedFastFlag sff{FFlag::LuauSolverV2, false};
|
||||||
|
@ -1310,9 +1310,7 @@ TEST_CASE_FIXTURE(Fixture, "we_cannot_infer_functions_that_return_inconsistently
|
|||||||
if (FFlag::LuauSolverV2)
|
if (FFlag::LuauSolverV2)
|
||||||
{
|
{
|
||||||
LUAU_CHECK_ERROR_COUNT(2, result);
|
LUAU_CHECK_ERROR_COUNT(2, result);
|
||||||
|
CHECK("<T>({T}, unknown) -> number" == toString(requireType("find_first")));
|
||||||
// The second argument should be unknown. CLI-111111
|
|
||||||
CHECK("<T>({T}, 'b) -> number" == toString(requireType("find_first")));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"paths": ["../ProjectLuauLibraries"],
|
"paths": ["../ProjectLuauLibraries"],
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"dep": "dependency"
|
"dep": "dependency",
|
||||||
|
"subdir": "subdirectory"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
return(require("@subdir/subdirectory_dependency"))
|
@ -0,0 +1 @@
|
|||||||
|
return {"result from subdirectory_dependency"}
|
Loading…
Reference in New Issue
Block a user