diff --git a/Analysis/src/TypeInfer.cpp b/Analysis/src/TypeInfer.cpp index d0ae4133..3b750070 100644 --- a/Analysis/src/TypeInfer.cpp +++ b/Analysis/src/TypeInfer.cpp @@ -43,12 +43,22 @@ LUAU_FASTFLAGVARIABLE(LuauTinyControlFlowAnalysis, false) LUAU_FASTFLAGVARIABLE(LuauAlwaysCommitInferencesOfFunctionCalls, false) LUAU_FASTFLAG(LuauParseDeclareClassIndexer) LUAU_FASTFLAGVARIABLE(LuauIndexTableIntersectionStringExpr, false) +LUAU_FASTFLAGVARIABLE(LuauIntersectedBinopOverloadFix, false) namespace Luau { static bool typeCouldHaveMetatable(TypeId ty) { + if (FFlag::LuauIntersectedBinopOverloadFix) { + if (auto itv = get(follow(ty))) + { + for (TypeId part : itv->parts) + if (typeCouldHaveMetatable(part)) + return true; + return false; + } + } return get(follow(ty)) || get(follow(ty)) || get(follow(ty)); } diff --git a/tests/TypeInfer.operators.test.cpp b/tests/TypeInfer.operators.test.cpp index 0b7a8311..b28140f4 100644 --- a/tests/TypeInfer.operators.test.cpp +++ b/tests/TypeInfer.operators.test.cpp @@ -438,6 +438,34 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "compound_assign_mismatch_metatable") CHECK("Type 'number' could not be converted into 'V2'" == toString(result.errors[0])); } +TEST_CASE_FIXTURE(BuiltinsFixture, "overloaded_op_accept_structured_subtype") +{ + ScopedFastFlag sff{"LuauIntersectedBinopOverloadFix", true}; + CheckResult result = check(R"( + --!strict + type BaseType = typeof(setmetatable( + {}, + ({} :: any) :: {__add: (BaseType, BaseType) -> BaseType}) + ) + type SubType = BaseType & {extraField: string} + + local function add1(x: BaseType, y: BaseType): BaseType + return x + y + end + local function add2(x: SubType, y: BaseType): BaseType + return x + y + end + local function add3(x: BaseType, y: SubType): BaseType + return x + y + end + local function add4(x: SubType, y: SubType): BaseType + return x + y + end + )"); + + LUAU_REQUIRE_ERROR_COUNT(0, result); +} + TEST_CASE_FIXTURE(Fixture, "CallOrOfFunctions") { CheckResult result = check(R"(