Skip to content

Commit 92e1830

Browse files
committed
Continue traversing tuple leafs only if subtyping is a possibility
1 parent 4468a12 commit 92e1830

1 file changed

Lines changed: 27 additions & 34 deletions

File tree

lib/elixir/lib/module/types/descr.ex

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4791,31 +4791,29 @@ defmodule Module.Types.Descr do
47914791
defp tuple_literal_intersection(:open, [], tag, elements), do: {tag, elements}
47924792

47934793
defp tuple_literal_intersection(tag1, elements1, tag2, elements2) do
4794-
if mismatched_tuple_sizes?(tag1, elements1, tag2, elements2) do
4795-
:empty
4796-
else
4797-
try do
4798-
zip_non_empty_intersection!(elements1, elements2, [])
4799-
catch
4800-
:empty -> :empty
4801-
else
4802-
elements when tag1 == :open and tag2 == :open -> {:open, elements}
4803-
elements -> {:closed, elements}
4804-
end
4794+
case tuple_sizes_strategy(tag1, length(elements1), tag2, length(elements2)) do
4795+
:disjoint ->
4796+
:empty
4797+
4798+
_ ->
4799+
try do
4800+
zip_non_empty_intersection!(elements1, elements2, [])
4801+
catch
4802+
:empty -> :empty
4803+
else
4804+
elements when tag1 == :open and tag2 == :open -> {:open, elements}
4805+
elements -> {:closed, elements}
4806+
end
48054807
end
48064808
end
48074809

4808-
defp mismatched_tuple_sizes?(:closed, elems1, :closed, elems2),
4809-
do: length(elems1) != length(elems2)
4810-
4811-
defp mismatched_tuple_sizes?(:closed, elems1, :open, elems2),
4812-
do: length(elems1) < length(elems2)
4813-
4814-
defp mismatched_tuple_sizes?(:open, elems1, :closed, elems2),
4815-
do: length(elems2) < length(elems1)
4816-
4817-
defp mismatched_tuple_sizes?(:open, _, :open, _),
4818-
do: false
4810+
defp tuple_sizes_strategy(:closed, n1, :closed, n2) when n1 != n2, do: :disjoint
4811+
defp tuple_sizes_strategy(:closed, n1, _, n2) when n1 == n2, do: :maybe_subtype
4812+
defp tuple_sizes_strategy(:closed, n1, :open, n2) when n1 < n2, do: :disjoint
4813+
defp tuple_sizes_strategy(_, n1, :open, n2) when n1 == n2, do: :maybe_subtype
4814+
defp tuple_sizes_strategy(_, n1, :open, n2) when n1 > n2, do: :maybe_subtype
4815+
defp tuple_sizes_strategy(:open, n1, :closed, n2) when n1 > n2, do: :disjoint
4816+
defp tuple_sizes_strategy(_, _, _, _), do: :none
48194817

48204818
# Intersects two lists of types, and _appends_ the extra elements to the result.
48214819
defp zip_non_empty_intersection!([], types2, acc), do: Enum.reverse(acc, types2)
@@ -4845,27 +4843,22 @@ defmodule Module.Types.Descr do
48454843
do: bdd_difference(bdd1, bdd2, &tuple_leaf_compare/2)
48464844

48474845
defp tuple_leaf_compare(bdd_leaf(tag1, elements1), bdd_leaf(tag2, elements2)) do
4848-
if mismatched_tuple_sizes?(tag1, elements1, tag2, elements2) do
4849-
:disjoint
4850-
else
4851-
tuple_leaf_compare(elements1, elements2, tag1, tag2)
4846+
case tuple_sizes_strategy(tag1, length(elements1), tag2, length(elements2)) do
4847+
:disjoint -> :disjoint
4848+
other -> tuple_leaf_compare(elements1, elements2, other == :maybe_subtype)
48524849
end
48534850
end
48544851

4855-
defp tuple_leaf_compare([head1 | tail1], [head2 | tail2], tag1, tag2) do
4852+
defp tuple_leaf_compare([head1 | tail1], [head2 | tail2], subtype?) do
48564853
cond do
48574854
disjoint?(head1, head2) -> :disjoint
4858-
subtype?(head1, head2) -> tuple_leaf_compare(tail1, tail2, tag1, tag2)
4855+
subtype? and subtype?(head1, head2) -> tuple_leaf_compare(tail1, tail2, subtype?)
48594856
true -> :none
48604857
end
48614858
end
48624859

4863-
defp tuple_leaf_compare(tail1, tail2, tag1, tag2) do
4864-
cond do
4865-
tail1 == [] and tail2 == [] and (tag1 == :closed or tag1 == tag2) -> :subtype
4866-
tail1 != [] and tag2 == :open -> :subtype
4867-
true -> :none
4868-
end
4860+
defp tuple_leaf_compare(_tail1, _tail2, subtype?) do
4861+
if subtype?, do: :subtype, else: :none
48694862
end
48704863

48714864
defp non_empty_tuple_literals_intersection(tuples) do

0 commit comments

Comments
 (0)