Skip to content

Commit f4bbf76

Browse files
committed
Optimize empty_difference_subtype? for dynamic parts
1 parent 9fdb835 commit f4bbf76

File tree

1 file changed

+16
-17
lines changed

1 file changed

+16
-17
lines changed

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

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ defmodule Module.Types.Descr do
257257
case descr do
258258
%{dynamic: %{optional: 1}} -> %{dynamic: %{optional: 1}}
259259
%{optional: 1} -> %{optional: 1}
260-
_ -> %{}
260+
_ -> @none
261261
end
262262
end
263263

@@ -464,13 +464,21 @@ defmodule Module.Types.Descr do
464464

465465
defp iterator_difference_static(:none, map), do: map
466466

467-
defp empty_difference_static?(left, :term), do: not Map.has_key?(left, :optional)
467+
# This function is designed to compute the difference during subtyping efficiently.
468+
# Do not use it for anything else.
469+
defp empty_difference_subtype?(%{dynamic: dyn_left} = left, %{dynamic: dyn_right} = right) do
470+
# Dynamic will either exist on both sides or on none
471+
empty_difference_subtype?(dyn_left, dyn_right) and
472+
empty_difference_subtype?(Map.delete(left, :dynamic), Map.delete(right, :dynamic))
473+
end
474+
475+
defp empty_difference_subtype?(left, :term), do: keep_optional(left) == @none
468476

469-
defp empty_difference_static?(left, right) do
470-
iterator_empty_difference_static?(:maps.next(:maps.iterator(unfold(left))), unfold(right))
477+
defp empty_difference_subtype?(left, right) do
478+
iterator_empty_difference_subtype?(:maps.next(:maps.iterator(unfold(left))), unfold(right))
471479
end
472480

473-
defp iterator_empty_difference_static?({key, v1, iterator}, map) do
481+
defp iterator_empty_difference_subtype?({key, v1, iterator}, map) do
474482
case map do
475483
%{^key => v2} ->
476484
value = difference(key, v1, v2)
@@ -479,15 +487,14 @@ defmodule Module.Types.Descr do
479487
%{} ->
480488
empty_key?(key, v1)
481489
end and
482-
iterator_empty_difference_static?(:maps.next(iterator), map)
490+
iterator_empty_difference_subtype?(:maps.next(iterator), map)
483491
end
484492

485-
defp iterator_empty_difference_static?(:none, _map), do: true
493+
defp iterator_empty_difference_subtype?(:none, _map), do: true
486494

487495
# Returning 0 from the callback is taken as none() for that subtype.
488496
defp difference(:atom, v1, v2), do: atom_difference(v1, v2)
489497
defp difference(:bitmap, v1, v2), do: v1 - (v1 &&& v2)
490-
defp difference(:dynamic, v1, v2), do: dynamic_difference(v1, v2)
491498
defp difference(:list, v1, v2), do: list_difference(v1, v2)
492499
defp difference(:map, v1, v2), do: map_difference(v1, v2)
493500
defp difference(:optional, 1, 1), do: 0
@@ -535,7 +542,6 @@ defmodule Module.Types.Descr do
535542
defp empty_key?(:map, value), do: map_empty?(value)
536543
defp empty_key?(:list, value), do: list_empty?(value)
537544
defp empty_key?(:tuple, value), do: tuple_empty?(value)
538-
defp empty_key?(:dynamic, value), do: empty?(value)
539545
defp empty_key?(_, _value), do: false
540546

541547
@doc """
@@ -662,7 +668,7 @@ defmodule Module.Types.Descr do
662668
end
663669

664670
defp subtype_static?(same, same), do: true
665-
defp subtype_static?(left, right), do: empty_difference_static?(left, right)
671+
defp subtype_static?(left, right), do: empty_difference_subtype?(left, right)
666672

667673
@doc """
668674
Check if a type is equal to another.
@@ -2116,13 +2122,6 @@ defmodule Module.Types.Descr do
21162122
defp dynamic_intersection(left, right),
21172123
do: symmetrical_intersection(unfold(left), unfold(right), &intersection/3)
21182124

2119-
defp dynamic_difference(left, right) do
2120-
case difference_static(left, right) do
2121-
value when value == @none -> 0
2122-
value -> value
2123-
end
2124-
end
2125-
21262125
defp dynamic_to_quoted(descr, opts) do
21272126
cond do
21282127
descr == %{} ->

0 commit comments

Comments
 (0)