Fix indexing table intersections using x["prop"] syntax (#971)

Right now, you can index an intersection of tables fine when using
`x.prop` syntax, but not when using `x["prop"]` syntax.
This fixes it for the latter case

```lua
type Foo = {
	Bar: string,
} & { Baz: number }

local x: Foo = { Bar = "1", Baz = 2 }
local y = x["Bar"] -- TypeError: Expected type table, got '{| Bar: string |} & {| Baz: number |}' instead
```

Part of a fix to
https://github.com/Roblox/luau/issues/533#issuecomment-1291779353
This commit is contained in:
JohnnyMorganz 2023-07-05 22:32:51 +01:00 committed by GitHub
parent 76bea81a7b
commit a02eb78c96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 0 deletions

View File

@ -41,6 +41,7 @@ LUAU_FASTFLAGVARIABLE(LuauTinyControlFlowAnalysis, false)
LUAU_FASTFLAGVARIABLE(LuauTypecheckClassTypeIndexers, false)
LUAU_FASTFLAGVARIABLE(LuauAlwaysCommitInferencesOfFunctionCalls, false)
LUAU_FASTFLAG(LuauParseDeclareClassIndexer)
LUAU_FASTFLAGVARIABLE(LuauIndexTableIntersectionStringExpr, false)
namespace Luau
{
@ -3412,6 +3413,20 @@ TypeId TypeChecker::checkLValueBinding(const ScopePtr& scope, const AstExprIndex
return prop->type();
}
}
else if (FFlag::LuauIndexTableIntersectionStringExpr && get<IntersectionType>(exprType))
{
Name name = std::string(value->value.data, value->value.size);
if (std::optional<TypeId> ty = getIndexTypeFromType(scope, exprType, name, expr.location, /* addErrors= */ false))
return *ty;
// If intersection has a table part, report that it cannot be extended just as a sealed table
if (isTableIntersection(exprType))
{
reportError(TypeError{expr.location, CannotExtendTable{exprType, CannotExtendTable::Property, name}});
return errorRecoveryType(scope);
}
}
}
else
{

View File

@ -880,4 +880,34 @@ TEST_CASE_FIXTURE(Fixture, "less_greedy_unification_with_intersection_types_2")
CHECK_EQ("({| x: number |} & {| x: string |}) -> never", toString(requireType("f")));
}
TEST_CASE_FIXTURE(BuiltinsFixture, "index_property_table_intersection_1")
{
CheckResult result = check(R"(
type Foo = {
Bar: string,
} & { Baz: number }
local x: Foo = { Bar = "1", Baz = 2 }
local y = x.Bar
)");
LUAU_REQUIRE_NO_ERRORS(result);
}
TEST_CASE_FIXTURE(BuiltinsFixture, "index_property_table_intersection_2")
{
ScopedFastFlag sff{"LuauIndexTableIntersectionStringExpr", true};
CheckResult result = check(R"(
type Foo = {
Bar: string,
} & { Baz: number }
local x: Foo = { Bar = "1", Baz = 2 }
local y = x["Bar"]
)");
LUAU_REQUIRE_NO_ERRORS(result);
}
TEST_SUITE_END();