From f2488bdfa4986f55c84d4f07246c3fe8bfdd6608 Mon Sep 17 00:00:00 2001 From: karl-police Date: Fri, 13 Sep 2024 19:16:30 +0200 Subject: [PATCH] Fix crash with the index type function, where it would stack overflow due to not waiting for a pending-expansion (#1407) Fix for https://github.com/luau-lang/luau/issues/1406 While it is good to let ``index`` wait for the pending-expansion. To re-produce the issue you need more than just this code: https://i.imgur.com/b3OmUGF.png It needs this, else it won't crash. ```lua local function ProblemCauser(key: Keys, value) PlayerData[key] = value end ```   But regarding "pending things", I'd recommend **generalized functions** for sanity checks like these, since there will be more cases of similar issues I believe. But I am 100% sure that eventually this issue here can maybe be prevented if looking at the Constraints. _(And optimization)_ Not sure if ``index`` needs the table fully completed, or if it is preferred that the info is available based on **how much info is available at the current position in the code**. But if this gets done, I hope that they'll be connected to the Solver Logger, because I actually refined mine with colors and more info _(yet need to finish that)_ to understand the Luau Source Code more and to debug issues. --------- Co-authored-by: aaron --- Analysis/src/TypeFunction.cpp | 6 ++++++ tests/TypeFunction.test.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/Analysis/src/TypeFunction.cpp b/Analysis/src/TypeFunction.cpp index 205d0fc4..9ae57fd1 100644 --- a/Analysis/src/TypeFunction.cpp +++ b/Analysis/src/TypeFunction.cpp @@ -2206,6 +2206,12 @@ TypeFunctionReductionResult indexFunctionImpl( return {std::nullopt, true, {}, {}}; TypeId indexerTy = follow(typeParams.at(1)); + + if (isPending(indexerTy, ctx->solver)) + { + return {std::nullopt, false, {indexerTy}, {}}; + } + std::shared_ptr indexerNormTy = ctx->normalizer->normalize(indexerTy); // if the indexer failed to normalize, we can't reduce, but know nothing about inhabitance. diff --git a/tests/TypeFunction.test.cpp b/tests/TypeFunction.test.cpp index 1f8d7d66..2b7b40a3 100644 --- a/tests/TypeFunction.test.cpp +++ b/tests/TypeFunction.test.cpp @@ -927,6 +927,32 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works") CHECK_EQ("string", toString(tpm->givenTp)); } +TEST_CASE_FIXTURE(BuiltinsFixture, "index_wait_for_pending_no_crash") +{ + if (!FFlag::LuauSolverV2) + return; + + CheckResult result = check(R"( + local PlayerData = { + Coins = 0, + Level = 1, + Exp = 0, + MaxExp = 100 + } + + type Keys = index> + + -- This function makes it think that there's going to be a pending expansion + local function UpdateData(key: Keys, value) + PlayerData[key] = value + end + + UpdateData("Coins", 2) + )"); + + // Should not crash! +} + TEST_CASE_FIXTURE(BuiltinsFixture, "index_type_function_works_w_array") { if (!FFlag::LuauSolverV2)