From 43c03168ea90d21ffea519ff4c094b00bc579d4b Mon Sep 17 00:00:00 2001 From: nothing1649 <65153224+nothing1649@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:02:52 +1100 Subject: [PATCH] Analysis: Make typeof on a type userdata return "type" This change introduces a flag (LuauUserTypeFunTypeofReturnsType) that, when enabled, sets __type on the type userdata's metatable to "type". This behaviour was described in the user-defined type function RFC (https://rfcs.luau.org/user-defined-type-functions.html), but seems to have been missed; this change implements that behaviour. --- Analysis/src/TypeFunctionRuntime.cpp | 7 +++++++ tests/TypeFunction.user.test.cpp | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Analysis/src/TypeFunctionRuntime.cpp b/Analysis/src/TypeFunctionRuntime.cpp index 24c75a510..ffb4cf0e6 100644 --- a/Analysis/src/TypeFunctionRuntime.cpp +++ b/Analysis/src/TypeFunctionRuntime.cpp @@ -17,6 +17,7 @@ LUAU_DYNAMIC_FASTINT(LuauTypeFunctionSerdeIterationLimit) LUAU_FASTFLAGVARIABLE(LuauUserTypeFunPrintToError) LUAU_FASTFLAGVARIABLE(LuauUserTypeFunFixNoReadWrite) LUAU_FASTFLAGVARIABLE(LuauUserTypeFunThreadBuffer) +LUAU_FASTFLAGVARIABLE(LuauUserTypeFunTypeofReturnsType) namespace Luau { @@ -1504,6 +1505,12 @@ void registerTypeUserData(lua_State* L) // Create and register metatable for type userdata luaL_newmetatable(L, "type"); + + if (FFlag::LuauUserTypeFunTypeofReturnsType) + { + lua_pushstring(L, "type"); + lua_setfield(L, -2, "__type"); + } // Protect metatable from being changed lua_pushstring(L, "The metatable is locked"); diff --git a/tests/TypeFunction.user.test.cpp b/tests/TypeFunction.user.test.cpp index a5af44fba..e493e2c17 100644 --- a/tests/TypeFunction.user.test.cpp +++ b/tests/TypeFunction.user.test.cpp @@ -14,6 +14,7 @@ LUAU_FASTFLAG(LuauUserTypeFunExportedAndLocal) LUAU_FASTFLAG(LuauUserDefinedTypeFunParseExport) LUAU_FASTFLAG(LuauUserTypeFunThreadBuffer) LUAU_FASTFLAG(LuauUserTypeFunUpdateAllEnvs) +LUAU_FASTFLAG(LuauUserTypeFunTypeofReturnsType) TEST_SUITE_BEGIN("UserDefinedTypeFunctionTests"); @@ -1393,4 +1394,23 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "print_to_error_plus_no_result") CHECK(toString(result.errors[3]) == R"(Type function instance t0 is uninhabited)"); } +TEST_CASE_FIXTURE(BuiltinsFixture, "typeof_type_userdata_returns_type") +{ + ScopedFastFlag solverV2{FFlag::LuauSolverV2, true}; + ScopedFastFlag luauUserTypeFunPrintToError{FFlag::LuauUserTypeFunPrintToError, true}; + ScopedFastFlag luauUserTypeFunTypeofReturnsType{FFlag::LuauUserTypeFunTypeofReturnsType, true}; + + CheckResult result = check(R"( +type function test(t) + print(typeof(t)) + return t +end + +local _:test + )"); + + LUAU_REQUIRE_ERROR_COUNT(1, result); + CHECK(toString(result.errors[0]) == R"(type)"); +} + TEST_SUITE_END();