Fix values preserving nil in iterators

This commit is contained in:
Kampfkarren 2024-11-28 22:34:35 -08:00
parent 8cc289fae4
commit 97db8166a5
2 changed files with 44 additions and 1 deletions

View file

@ -34,6 +34,7 @@ LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification)
LUAU_FASTFLAG(LuauInstantiateInSubtyping)
LUAU_FASTFLAGVARIABLE(LuauMetatableFollow)
LUAU_FASTFLAGVARIABLE(LuauRequireCyclesDontAlwaysReturnAny)
LUAU_FASTFLAGVARIABLE(LuauNilInForLoops)
namespace Luau
{
@ -1285,7 +1286,18 @@ ControlFlow TypeChecker::check(const ScopePtr& scope, const AstStatForIn& forin)
unify(iterTable->indexer->indexType, varTypes[0], scope, forin.location);
if (varTypes.size() > 1)
unify(iterTable->indexer->indexResultType, varTypes[1], scope, forin.location);
{
if (FFlag::LuauNilInForLoops)
{
std::optional<TypeId> withoutNilTy = tryStripUnionFromNil(iterTable->indexer->indexResultType);
unify(withoutNilTy ? *withoutNilTy : iterTable->indexer->indexResultType, varTypes[1], scope, forin.location);
}
else
{
unify(iterTable->indexer->indexResultType, varTypes[1], scope, forin.location);
}
}
for (size_t i = 2; i < varTypes.size(); ++i)
unify(nilType, varTypes[i], scope, forin.location);

View file

@ -15,6 +15,7 @@
using namespace Luau;
LUAU_FASTFLAG(LuauSolverV2)
LUAU_FASTFLAG(LuauNilInForLoops)
TEST_SUITE_BEGIN("TypeInferLoops");
@ -1255,4 +1256,34 @@ end
)");
}
TEST_CASE_FIXTURE(Fixture, "nil_in_for_loops")
{
ScopedFastFlag sff = {FFlag::LuauNilInForLoops, true};
LUAU_REQUIRE_NO_ERRORS(check(R"(
--!strict
local function f(x: { [string]: string? })
for key, value in x do
local v: string = value
end
end
)"));
}
// Custom iterators can return nil, just not without
TEST_CASE_FIXTURE(BuiltinsFixture, "nil_in_for_loops_iter")
{
LUAU_REQUIRE_NO_ERRORS(check(R"(
--!strict
type T = typeof(setmetatable({}, {} :: {
__iter: (any) -> () -> (boolean, string?)
}))
local function f(x: T)
for a: boolean, b: string? in x do
end
end
)"));
}
TEST_SUITE_END();