Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion Analysis/src/TypeFunctionRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

LUAU_DYNAMIC_FASTINT(LuauTypeFunctionSerdeIterationLimit)
LUAU_FASTFLAGVARIABLE(LuauTypeFunOptional)
LUAU_FASTFLAGVARIABLE(DebugLuauRenameClassToExtern)

namespace Luau
{
Expand All @@ -38,11 +39,22 @@ LuauTempThreadPopper::~LuauTempThreadPopper()

static void dummyStateClose(lua_State*) {}

static std::string getTag_DEPRECATED(lua_State* L, TypeFunctionTypeId ty);
static std::string getTag_NEW(lua_State* L, TypeFunctionTypeId ty);

// Original function is named "getTag"
using GetTagFunc = std::string (*)(lua_State*, TypeFunctionTypeId);
static GetTagFunc getTag = getTag_DEPRECATED;

TypeFunctionRuntime::TypeFunctionRuntime(NotNull<InternalErrorReporter> ice, NotNull<TypeCheckLimits> limits)
: ice(ice)
, limits(limits)
, state(nullptr, dummyStateClose)
{
if (FFlag::DebugLuauRenameClassToExtern)
{
getTag = getTag_NEW;
}
}

TypeFunctionRuntime::~TypeFunctionRuntime() {}
Expand Down Expand Up @@ -256,7 +268,7 @@ std::optional<TypeFunctionTypeId> optionalTypeUserData(lua_State* L, int idx)
}

// returns a string tag of TypeFunctionTypeId
static std::string getTag(lua_State* L, TypeFunctionTypeId ty)
static std::string getTag_DEPRECATED(lua_State* L, TypeFunctionTypeId ty)
{
if (auto n = get<TypeFunctionPrimitiveType>(ty); n && n->type == TypeFunctionPrimitiveType::Type::NilType)
return "nil";
Expand Down Expand Up @@ -297,6 +309,48 @@ static std::string getTag(lua_State* L, TypeFunctionTypeId ty)
luaL_error(L, "VM encountered unexpected type variant when determining tag");
}

// returns a string tag of TypeFunctionTypeId
static std::string getTag_NEW(lua_State* L, TypeFunctionTypeId ty)
{
if (auto n = get<TypeFunctionPrimitiveType>(ty); n && n->type == TypeFunctionPrimitiveType::Type::NilType)
return "nil";
else if (auto b = get<TypeFunctionPrimitiveType>(ty); b && b->type == TypeFunctionPrimitiveType::Type::Boolean)
return "boolean";
else if (auto n = get<TypeFunctionPrimitiveType>(ty); n && n->type == TypeFunctionPrimitiveType::Type::Number)
return "number";
else if (auto s = get<TypeFunctionPrimitiveType>(ty); s && s->type == TypeFunctionPrimitiveType::Type::String)
return "string";
else if (auto s = get<TypeFunctionPrimitiveType>(ty); s && s->type == TypeFunctionPrimitiveType::Type::Thread)
return "thread";
else if (auto s = get<TypeFunctionPrimitiveType>(ty); s && s->type == TypeFunctionPrimitiveType::Type::Buffer)
return "buffer";
else if (get<TypeFunctionUnknownType>(ty))
return "unknown";
else if (get<TypeFunctionNeverType>(ty))
return "never";
else if (get<TypeFunctionAnyType>(ty))
return "any";
else if (auto s = get<TypeFunctionSingletonType>(ty))
return "singleton";
else if (get<TypeFunctionNegationType>(ty))
return "negation";
else if (get<TypeFunctionUnionType>(ty))
return "union";
else if (get<TypeFunctionIntersectionType>(ty))
return "intersection";
else if (get<TypeFunctionTableType>(ty))
return "table";
else if (get<TypeFunctionFunctionType>(ty))
return "function";
else if (get<TypeFunctionExternType>(ty))
return "extern";
else if (get<TypeFunctionGenericType>(ty))
return "generic";

LUAU_UNREACHABLE();
luaL_error(L, "VM encountered unexpected type variant when determining tag");
}

// Luau: `type.unknown`
// Returns the type instance representing unknown
static int createUnknown(lua_State* L)
Expand Down
36 changes: 36 additions & 0 deletions tests/TypeFunction.user.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ LUAU_FASTFLAG(LuauEagerGeneralization4)
LUAU_FASTFLAG(LuauTableLiteralSubtypeSpecificCheck2)
LUAU_FASTFLAG(LuauStuckTypeFunctionsStillDispatch)
LUAU_FASTFLAG(LuauTypeFunctionSerializeFollowMetatable)
LUAU_FASTFLAG(LuauDeclareExternType)
LUAU_FASTFLAG(DebugLuauRenameClassToExtern)

TEST_SUITE_BEGIN("UserDefinedTypeFunctionTests");

Expand Down Expand Up @@ -2486,4 +2488,38 @@ end
CHECK(toString(result.errors[0]) == R"(Redefinition of type 't0', previously defined at line 2)");
}

TEST_CASE_FIXTURE(BuiltinsFixture, "udtf_extern_tag")
{
ScopedFastFlag sff[]{
{FFlag::LuauSolverV2, true},
{FFlag::LuauDeclareExternType, true},
{FFlag::DebugLuauRenameClassToExtern, true}
};

loadDefinition(R"(
declare extern type CustomExternType with
function testFunc(self): number
end
)");

CheckResult result = check(R"(
--!strict
type function tyFunc(arg: type)
if (arg:is("extern")) then
return arg
end
-- this should never be returned
return types.boolean
end

type a = tyFunc<CustomExternType>
)");

auto test = requireTypeAlias("a");
// If it's not an ExternType it will fail.
LUAU_ASSERT( test->ty.get_if<ExternType>() );

LUAU_REQUIRE_NO_ERRORS(result);
}

TEST_SUITE_END();
Loading