From 9a102e2aff99ecaf2ad1e5ca59fc1c893d5e9b7c Mon Sep 17 00:00:00 2001 From: vegorov-rbx <75688451+vegorov-rbx@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:30:43 -0800 Subject: [PATCH] Fix negation type 'inner' method in user-defined type functions (#1582) Fixes #1580 --- Analysis/src/TypeFunctionRuntime.cpp | 18 +++++++++++++++--- tests/TypeFunction.user.test.cpp | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Analysis/src/TypeFunctionRuntime.cpp b/Analysis/src/TypeFunctionRuntime.cpp index 24c75a510..bb0309fc3 100644 --- a/Analysis/src/TypeFunctionRuntime.cpp +++ b/Analysis/src/TypeFunctionRuntime.cpp @@ -14,6 +14,7 @@ #include LUAU_DYNAMIC_FASTINT(LuauTypeFunctionSerdeIterationLimit) +LUAU_FASTFLAGVARIABLE(LuauUserTypeFunFixInner) LUAU_FASTFLAGVARIABLE(LuauUserTypeFunPrintToError) LUAU_FASTFLAGVARIABLE(LuauUserTypeFunFixNoReadWrite) LUAU_FASTFLAGVARIABLE(LuauUserTypeFunThreadBuffer) @@ -413,10 +414,21 @@ static int getNegatedValue(lua_State* L) luaL_error(L, "type.inner: expected 1 argument, but got %d", argumentCount); TypeFunctionTypeId self = getTypeUserData(L, 1); - if (auto tfnt = get(self); !tfnt) - allocTypeUserData(L, tfnt->type->type); + + if (FFlag::LuauUserTypeFunFixInner) + { + if (auto tfnt = get(self); tfnt) + allocTypeUserData(L, tfnt->type->type); + else + luaL_error(L, "type.inner: cannot call inner method on non-negation type: `%s` type", getTag(L, self).c_str()); + } else - luaL_error(L, "type.inner: cannot call inner method on non-negation type: `%s` type", getTag(L, self).c_str()); + { + if (auto tfnt = get(self); !tfnt) + allocTypeUserData(L, tfnt->type->type); + else + luaL_error(L, "type.inner: cannot call inner method on non-negation type: `%s` type", getTag(L, self).c_str()); + } return 1; } diff --git a/tests/TypeFunction.user.test.cpp b/tests/TypeFunction.user.test.cpp index a5af44fba..281c73c72 100644 --- a/tests/TypeFunction.user.test.cpp +++ b/tests/TypeFunction.user.test.cpp @@ -9,6 +9,7 @@ using namespace Luau; LUAU_FASTFLAG(LuauSolverV2) LUAU_FASTFLAG(LuauUserTypeFunFixNoReadWrite) +LUAU_FASTFLAG(LuauUserTypeFunFixInner) LUAU_FASTFLAG(LuauUserTypeFunPrintToError) LUAU_FASTFLAG(LuauUserTypeFunExportedAndLocal) LUAU_FASTFLAG(LuauUserDefinedTypeFunParseExport) @@ -475,6 +476,28 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "udtf_negation_methods_work") CHECK(toString(tpm->givenTp) == "~string"); } +TEST_CASE_FIXTURE(ClassFixture, "udtf_negation_inner") +{ + ScopedFastFlag newSolver{FFlag::LuauSolverV2, true}; + ScopedFastFlag luauUserTypeFunFixInner{FFlag::LuauUserTypeFunFixInner, true}; + + CheckResult result = check(R"( +type function pass(t) + return types.negationof(t):inner() +end + +type function fail(t) + return t:inner() +end + +local function ok(idx: pass): number return idx end +local function notok(idx: fail): never return idx end + )"); + + LUAU_REQUIRE_ERROR_COUNT(4, result); + CHECK(toString(result.errors[0]) == R"('fail' type function errored at runtime: [string "fail"]:7: type.inner: cannot call inner method on non-negation type: `number` type)"); +} + TEST_CASE_FIXTURE(BuiltinsFixture, "udtf_table_serialization_works") { ScopedFastFlag newSolver{FFlag::LuauSolverV2, true};