Skip to content

Commit

Permalink
Sync to upstream/release/643 (#1408)
Browse files Browse the repository at this point in the history
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 <[email protected]>
Co-authored-by: James McNellis <[email protected]>
Co-authored-by: Vighnesh Vijay <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

---------

Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Alexander McCord <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: David Cope <[email protected]>
Co-authored-by: Lily Brown <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>
Co-authored-by: Junseo Yoo <[email protected]>
  • Loading branch information
9 people authored Sep 13, 2024
1 parent f2488bd commit b765d7b
Show file tree
Hide file tree
Showing 23 changed files with 132 additions and 29 deletions.
16 changes: 11 additions & 5 deletions Analysis/src/Generalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -887,9 +887,6 @@ std::optional<TypeId> generalize(
if (ty->owningArena != arena || ty->persistent)
return ty;

if (const FunctionType* ft = get<FunctionType>(ty); ft && (!ft->generics.empty() || !ft->genericPacks.empty()))
return ty;

FreeTypeSearcher fts{scope, cachedTypes};
fts.traverse(ty);

Expand All @@ -912,8 +909,17 @@ std::optional<TypeId> generalize(
FunctionType* ftv = getMutable<FunctionType>(ty);
if (ftv)
{
ftv->generics = std::move(gen.generics);
ftv->genericPacks = std::move(gen.genericPacks);
// If we're generalizing a function type, add any of the newly inferred
// 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;
Expand Down
3 changes: 3 additions & 0 deletions Analysis/src/OverloadResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ std::optional<ErrorVec> OverloadResolver::testIsSubtype(const Location& location
case ErrorSuppression::NormalizationFailed:
errors.emplace_back(location, NormalizationTooComplex{});
// intentionally fallthrough here since we couldn't prove this was error-suppressing
[[fallthrough]];
case ErrorSuppression::DoNotSuppress:
errors.emplace_back(location, TypeMismatch{superTy, subTy});
break;
Expand Down Expand Up @@ -136,6 +137,7 @@ std::optional<ErrorVec> OverloadResolver::testIsSubtype(const Location& location
case ErrorSuppression::NormalizationFailed:
errors.emplace_back(location, NormalizationTooComplex{});
// intentionally fallthrough here since we couldn't prove this was error-suppressing
[[fallthrough]];
case ErrorSuppression::DoNotSuppress:
errors.emplace_back(location, TypePackMismatch{superTy, subTy});
break;
Expand Down Expand Up @@ -301,6 +303,7 @@ std::pair<OverloadResolver::Analysis, ErrorVec> OverloadResolver::checkOverload_
case ErrorSuppression::NormalizationFailed:
errors.emplace_back(argLocation, NormalizationTooComplex{});
// intentionally fallthrough here since we couldn't prove this was error-suppressing
[[fallthrough]];
case ErrorSuppression::DoNotSuppress:
// TODO extract location from the SubtypingResult path and argExprs
switch (reason.variance)
Expand Down
5 changes: 5 additions & 0 deletions Analysis/src/Simplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ Relation combine(Relation a, Relation b)
case Relation::Superset:
return Relation::Intersects;
}
break;
case Relation::Coincident:
switch (b)
{
Expand All @@ -155,6 +156,7 @@ Relation combine(Relation a, Relation b)
case Relation::Superset:
return Relation::Intersects;
}
break;
case Relation::Superset:
switch (b)
{
Expand All @@ -169,6 +171,7 @@ Relation combine(Relation a, Relation b)
case Relation::Superset:
return Relation::Superset;
}
break;
case Relation::Subset:
switch (b)
{
Expand All @@ -183,6 +186,7 @@ Relation combine(Relation a, Relation b)
case Relation::Superset:
return Relation::Intersects;
}
break;
case Relation::Intersects:
switch (b)
{
Expand All @@ -197,6 +201,7 @@ Relation combine(Relation a, Relation b)
case Relation::Superset:
return Relation::Intersects;
}
break;
}

LUAU_UNREACHABLE();
Expand Down
8 changes: 5 additions & 3 deletions Analysis/src/TypeChecker2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1378,7 +1378,7 @@ void TypeChecker2::visitCall(AstExprCall* call)
break;
case ErrorSuppression::NormalizationFailed:
reportError(NormalizationTooComplex{}, call->func->location);
// fallthrough intentional
[[fallthrough]];
case ErrorSuppression::DoNotSuppress:
reportError(OptionalValueAccess{fnTy}, call->func->location);
}
Expand Down Expand Up @@ -1582,7 +1582,7 @@ TypeId TypeChecker2::stripFromNilAndReport(TypeId ty, const Location& location)
break;
case ErrorSuppression::NormalizationFailed:
reportError(NormalizationTooComplex{}, location);
// fallthrough intentional
[[fallthrough]];
case ErrorSuppression::DoNotSuppress:
reportError(OptionalValueAccess{ty}, location);
}
Expand Down Expand Up @@ -1666,7 +1666,7 @@ void TypeChecker2::visit(AstExprIndexExpr* indexExpr, ValueContext context)
break;
case ErrorSuppression::NormalizationFailed:
reportError(NormalizationTooComplex{}, indexExpr->location);
// fallthrough intentional
[[fallthrough]];
case ErrorSuppression::DoNotSuppress:
reportError(OptionalValueAccess{exprType}, indexExpr->location);
}
Expand Down Expand Up @@ -2723,6 +2723,7 @@ void TypeChecker2::explainError(TypeId subTy, TypeId superTy, Location location,
return;
case ErrorSuppression::NormalizationFailed:
reportError(NormalizationTooComplex{}, location);
break;
case ErrorSuppression::DoNotSuppress:
break;
}
Expand All @@ -2741,6 +2742,7 @@ void TypeChecker2::explainError(TypePackId subTy, TypePackId superTy, Location l
return;
case ErrorSuppression::NormalizationFailed:
reportError(NormalizationTooComplex{}, location);
break;
case ErrorSuppression::DoNotSuppress:
break;
}
Expand Down
2 changes: 1 addition & 1 deletion Analysis/src/TypeInfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2751,7 +2751,7 @@ TypeId TypeChecker::checkRelationalOperation(
if (lhsIsAny || rhsIsAny)
return booleanType;

// Fallthrough here is intentional
[[fallthrough]];
}
case AstExprBinary::CompareLt:
case AstExprBinary::CompareGt:
Expand Down
1 change: 1 addition & 0 deletions Ast/src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ AstStat* Parser::parseAttributeStat()
AstExpr* expr = parsePrimaryExpr(/* asStatement= */ true);
return parseDeclaration(expr->location, attributes);
}
[[fallthrough]];
default:
return reportStatError(
lexer.current().location,
Expand Down
13 changes: 12 additions & 1 deletion CLI/Require.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,18 @@ void RequireResolver::substituteAliasIfPresent(std::string& path)
{
if (path.size() < 1 || path[0] != '@')
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
if (!Luau::isValidAlias(potentialAlias))
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ if(MSVC)
list(APPEND LUAU_OPTIONS "/we4388") # Also signed/unsigned mismatch
else()
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
endif()

Expand Down
13 changes: 13 additions & 0 deletions Common/include/Luau/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@
#define LUAU_DEBUGBREAK() __builtin_trap()
#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__
#define LUAU_BIG_ENDIAN
#endif
Expand Down
9 changes: 5 additions & 4 deletions VM/src/lstrlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,9 +552,9 @@ static const char* match(MatchState* ms, const char* s, const char* p)
}
break;
}
case '+': // 1 or more repetitions
s++; // 1 match already done
// go through
case '+': // 1 or more repetitions
s++; // 1 match already done
LUAU_FALLTHROUGH; // go through
case '*': // 0 or more repetitions
s = max_expand(ms, s, p, ep);
break;
Expand Down Expand Up @@ -1480,7 +1480,8 @@ static int str_pack(lua_State* L)
break;
}
case Kpadding:
luaL_addchar(&b, LUAL_PACKPADBYTE); // FALLTHROUGH
luaL_addchar(&b, LUAL_PACKPADBYTE);
LUAU_FALLTHROUGH;
case Kpaddalign:
case Knop:
arg--; // undo increment
Expand Down
2 changes: 1 addition & 1 deletion VM/src/ltable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ const TValue* luaH_get(Table* t, const TValue* key)
luai_num2int(k, n);
if (luai_numeq(cast_num(k), nvalue(key))) // index is int?
return luaH_getnum(t, k); // use specialized version
// else go through
LUAU_FALLTHROUGH; // else go through
}
default:
{
Expand Down
15 changes: 15 additions & 0 deletions tests/Conformance.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@ static int lua_vector_cross(lua_State* L)
const float* a = luaL_checkvector(L, 1);
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]);
#endif

return 1;
}

Expand All @@ -144,15 +149,25 @@ static int lua_vector_index(lua_State* L)

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]));
#endif
return 1;
}

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]);

lua_pushvector(L, v[0] * invSqrt, v[1] * invSqrt, v[2] * invSqrt);
#endif
return 1;
}

Expand Down
4 changes: 4 additions & 0 deletions tests/Fixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "Luau/AstQuery.h"
#include "Luau/BuiltinDefinitions.h"
#include "Luau/Common.h"
#include "Luau/Constraint.h"
#include "Luau/ModuleResolver.h"
#include "Luau/NotNull.h"
Expand All @@ -25,6 +26,7 @@ static const char* mainModuleName = "MainModule";
LUAU_FASTFLAG(LuauSolverV2);
LUAU_FASTFLAG(DebugLuauFreezeArena);
LUAU_FASTFLAG(DebugLuauLogSolverToJsonFile)
LUAU_FASTFLAG(LuauDCRMagicFunctionTypeChecker);

extern std::optional<unsigned> randomSeed; // tests/main.cpp

Expand Down Expand Up @@ -150,6 +152,8 @@ const Config& TestConfigResolver::getConfig(const ModuleName& name) const

Fixture::Fixture(bool freeze, bool prepareAutocomplete)
: 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(
&fileResolver,
&configResolver,
Expand Down
1 change: 1 addition & 0 deletions tests/Fixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct Fixture
TypeId requireExportedType(const ModuleName& moduleName, const std::string& name);

ScopedFastFlag sff_DebugLuauFreezeArena;
ScopedFastFlag sff_LuauDCRMagicFunctionTypeChecker;

TestFileResolver fileResolver;
TestConfigResolver configResolver;
Expand Down
6 changes: 6 additions & 0 deletions tests/IrLowering.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,7 @@ end
);
}

#if LUA_VECTOR_SIZE == 3
TEST_CASE("FastcallTypeInferThroughLocal")
{
CHECK_EQ(
Expand Down Expand Up @@ -1045,6 +1046,7 @@ end
)"
);
}
#endif

TEST_CASE("LoadAndMoveTypePropagation")
{
Expand Down Expand Up @@ -1115,6 +1117,7 @@ end
);
}

#if LUA_VECTOR_SIZE == 3
TEST_CASE("ArgumentTypeRefinement")
{
CHECK_EQ(
Expand Down Expand Up @@ -1152,6 +1155,7 @@ end
)"
);
}
#endif

TEST_CASE("InlineFunctionType")
{
Expand Down Expand Up @@ -1422,6 +1426,7 @@ end
);
}

#if LUA_VECTOR_SIZE == 3
TEST_CASE("UnaryTypeResolve")
{
CHECK_EQ(
Expand All @@ -1443,6 +1448,7 @@ end
)"
);
}
#endif

TEST_CASE("ForInManualAnnotation")
{
Expand Down
6 changes: 6 additions & 0 deletions tests/RequireByString.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,12 @@ TEST_CASE_FIXTURE(ReplWithPathFixture, "RequirePathWithParentAlias")
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")
{
Expand Down
2 changes: 1 addition & 1 deletion tests/ToString.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ TEST_CASE_FIXTURE(Fixture, "pick_distinct_names_for_mixed_explicit_and_implicit_

if (FFlag::LuauSolverV2)
{
CHECK("<a>(a, 'b) -> ()" == toString(requireType("foo")));
CHECK("<a>(a, unknown) -> ()" == toString(requireType("foo")));
}
else
CHECK("<a, b>(a, b) -> ()" == toString(requireType("foo")));
Expand Down
Loading

0 comments on commit b765d7b

Please sign in to comment.