Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion Analysis/src/Subtyping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ LUAU_FASTFLAG(LuauRefactorStringSemanticSubtyping)
LUAU_FASTFLAG(DebugLuauExactTableTypes)
LUAU_FASTFLAGVARIABLE(LuauFixSuperNegationTypePaths)
LUAU_FASTFLAGVARIABLE(LuauDoNotIceForBindingGeneric)
LUAU_FASTFLAGVARIABLE(LuauSubtypingSkipUnreadReasoning)


namespace Luau
Expand Down Expand Up @@ -304,6 +305,11 @@ SubtypingResult& SubtypingResult::withBothComponent(TypePath::Component componen

SubtypingResult& SubtypingResult::withSubComponent(TypePath::Component component)
{
// Nothing reads the reasoning of a successful result: andAlso and orElse drop it, and negate
// discards it.
if (FFlag::LuauSubtypingSkipUnreadReasoning && isSubtype)
return *this;

if (reasoning.empty())
reasoning.insert(SubtypingReasoning{Path(std::move(component)), TypePath::kEmpty});
else
Expand All @@ -317,6 +323,9 @@ SubtypingResult& SubtypingResult::withSubComponent(TypePath::Component component

SubtypingResult& SubtypingResult::withSuperComponent(TypePath::Component component)
{
if (FFlag::LuauSubtypingSkipUnreadReasoning && isSubtype)
return *this;

if (reasoning.empty())
reasoning.insert(SubtypingReasoning{TypePath::kEmpty, Path(std::move(component))});
else
Expand All @@ -335,6 +344,9 @@ SubtypingResult& SubtypingResult::withBothPath(TypePath::Path path)

SubtypingResult& SubtypingResult::withSubPath(TypePath::Path path)
{
if (FFlag::LuauSubtypingSkipUnreadReasoning && isSubtype)
return *this;

if (reasoning.empty())
reasoning.insert(SubtypingReasoning{std::move(path), TypePath::kEmpty});
else
Expand All @@ -348,6 +360,9 @@ SubtypingResult& SubtypingResult::withSubPath(TypePath::Path path)

SubtypingResult& SubtypingResult::withSuperPath(TypePath::Path path)
{
if (FFlag::LuauSubtypingSkipUnreadReasoning && isSubtype)
return *this;

if (reasoning.empty())
reasoning.insert(SubtypingReasoning{TypePath::kEmpty, std::move(path)});
else
Expand Down Expand Up @@ -1532,6 +1547,9 @@ template<typename SubTy, typename SuperTy>
SubtypingResult Subtyping::isContravariantWith(SubtypingEnvironment& env, SubTy subTy, SuperTy superTy, NotNull<Scope> scope)
{
SubtypingResult result = isCovariantWith(env, superTy, subTy, scope);
if (FFlag::LuauSubtypingSkipUnreadReasoning && result.isSubtype)
return result;

if (result.reasoning.empty())
result.reasoning.insert(SubtypingReasoning{TypePath::kEmpty, TypePath::kEmpty, SubtypingVariance::Contravariant});
else
Expand Down Expand Up @@ -1564,6 +1582,9 @@ SubtypingResult Subtyping::isInvariantWith(SubtypingEnvironment& env, SubTy subT
SubtypingResult result = isCovariantWith(env, subTy, superTy, scope);
result.andAlso(isContravariantWith(env, subTy, superTy, scope));

if (FFlag::LuauSubtypingSkipUnreadReasoning && result.isSubtype)
return result;

if (result.reasoning.empty())
result.reasoning.insert(SubtypingReasoning{TypePath::kEmpty, TypePath::kEmpty, SubtypingVariance::Invariant});
else
Expand Down Expand Up @@ -1651,7 +1672,14 @@ SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, TypeId sub
if (next.isSubtype)
return next;

result.andAlso(next.withSuperComponent(TypePath::Index{index, TypePath::Index::Variant::Union}));
if (FFlag::LuauSubtypingSkipUnreadReasoning)
{
// The failed reasoning emitted when subtyping `T <: A | B | C` is always cleared before returning, so we can simply skip its inclusion.
next.reasoning.clear();
result.andAlso(std::move(next));
}
else
result.andAlso(next.withSuperComponent(TypePath::Index{index, TypePath::Index::Variant::Union}));
++index;
}

Expand Down
10 changes: 10 additions & 0 deletions tests/Subtyping.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ LUAU_FASTFLAG(LuauNewTypePathErrorMessages)
LUAU_FASTFLAG(LuauRefactorStringSemanticSubtyping)
LUAU_FASTFLAG(DebugLuauParseExactTables)
LUAU_FASTFLAG(DebugLuauExactTableTypes)
LUAU_FASTFLAG(LuauSubtypingSkipUnreadReasoning)

using namespace Luau;

Expand Down Expand Up @@ -2251,6 +2252,15 @@ TEST_CASE_FIXTURE(SubtypeFixture, "multiple_reasonings")
);
}

TEST_CASE_FIXTURE(SubtypeFixture, "successful_subtyping_has_no_reasoning")
{
ScopedFastFlag sff{FFlag::LuauSubtypingSkipUnreadReasoning, true};

SubtypingResult result = isSubtype(getBuiltins()->numberType, negate(getBuiltins()->stringType));
CHECK(result.isSubtype);
CHECK(result.reasoning.empty());
}

TEST_CASE_FIXTURE(SubtypeFixture, "substitute_a_generic_for_a_negation")
{
// <A, B>(x: A, y: B) -> (A & ~(false?)) | B
Expand Down
Loading