Skip to content

Commit dfb5bb8

Browse files
committed
Optimize subtype? by aborting early
In the same way we introduced non_disjoint_intersection to optimize compatibility, we introduce empty_difference to optimize subtyping.
1 parent b1053b7 commit dfb5bb8

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,26 @@ 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)
468+
469+
defp empty_difference_static?(left, right) do
470+
iterator_empty_difference_static?(:maps.next(:maps.iterator(unfold(left))), unfold(right))
471+
end
472+
473+
defp iterator_empty_difference_static?({key, v1, iterator}, map) do
474+
case map do
475+
%{^key => v2} ->
476+
value = difference(key, v1, v2)
477+
value in @empty_difference or empty_key?(key, value)
478+
479+
%{} ->
480+
empty_key?(key, v1)
481+
end and
482+
iterator_empty_difference_static?(:maps.next(iterator), map)
483+
end
484+
485+
defp iterator_empty_difference_static?(:none, _map), do: true
486+
467487
# Returning 0 from the callback is taken as none() for that subtype.
468488
defp difference(:atom, v1, v2), do: atom_difference(v1, v2)
469489
defp difference(:bitmap, v1, v2), do: v1 - (v1 &&& v2)
@@ -491,7 +511,7 @@ defmodule Module.Types.Descr do
491511
def empty?(:term), do: false
492512

493513
def empty?(%{} = descr) do
494-
case :maps.get(:dynamic, descr, _default = descr) do
514+
case :maps.get(:dynamic, descr, descr) do
495515
:term ->
496516
false
497517

@@ -511,9 +531,11 @@ defmodule Module.Types.Descr do
511531

512532
# For atom, bitmap, and optional, if the key is present,
513533
# then they are not empty,
534+
defp empty_key?(:fun, value), do: fun_empty?(value)
514535
defp empty_key?(:map, value), do: map_empty?(value)
515536
defp empty_key?(:list, value), do: list_empty?(value)
516537
defp empty_key?(:tuple, value), do: tuple_empty?(value)
538+
defp empty_key?(:dynamic, value), do: empty?(value)
517539
defp empty_key?(_, _value), do: false
518540

519541
@doc """
@@ -640,7 +662,7 @@ defmodule Module.Types.Descr do
640662
end
641663

642664
defp subtype_static?(same, same), do: true
643-
defp subtype_static?(left, right), do: empty?(difference_static(left, right))
665+
defp subtype_static?(left, right), do: empty_difference_static?(left, right)
644666

645667
@doc """
646668
Check if a type is equal to another.

0 commit comments

Comments
 (0)