Skip to content

Commit c16befc

Browse files
committed
More optimizations
1 parent dcaea8f commit c16befc

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

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

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ defmodule Module.Types.Descr do
428428
## Funs
429429

430430
@doc """
431-
Checks there is precisely one function with said arity.
431+
Checks there is a function type (and only functions) with said arity.
432432
"""
433433
def fun_fetch(:term, _arity), do: :error
434434

@@ -752,8 +752,14 @@ defmodule Module.Types.Descr do
752752

753753
defp map_fetch_static(descr, key) when is_atom(key) do
754754
case descr do
755-
%{map: [{:open, fields, []}]} when fields == %{} ->
756-
{true, term()}
755+
# Optimization: if the key does not exist in the map,
756+
# avoid building if_set/not_set pairs and return the
757+
# popped value directly.
758+
%{map: [{tag, fields, []}]} when not is_map_key(fields, key) ->
759+
case tag do
760+
:open -> {true, term()}
761+
:closed -> {true, none()}
762+
end
757763

758764
%{map: map} ->
759765
map_split_on_key(map, key)
@@ -930,19 +936,24 @@ defmodule Module.Types.Descr do
930936
# Takes a map dnf and a key and returns a list of unions of types
931937
# for that key. It has to traverse both fields and negative entries.
932938
defp map_split_on_key(dnf, key) do
933-
Enum.flat_map(dnf, fn {tag, fields, negs} ->
934-
# %{...} the open map in a positive intersection can be ignored
935-
{fst, snd} =
936-
if tag == :open and fields == %{} do
937-
{term_or_optional(), term_or_optional()}
938-
else
939-
map_pop_key(tag, fields, key)
939+
Enum.flat_map(dnf, fn
940+
# Optimization: if there are no negatives,
941+
# we can return the value directly.
942+
{_tag, %{^key => value}, []} ->
943+
[value]
944+
945+
# Optimization: if there are no negatives
946+
# and the key does not exist, return the default one.
947+
{tag, %{}, []} ->
948+
[map_tag_to_type(tag)]
949+
950+
{tag, fields, negs} ->
951+
{fst, snd} = map_pop_key(tag, fields, key)
952+
953+
case map_split_negative(negs, key, []) do
954+
:empty -> []
955+
negative -> negative |> pair_make_disjoint() |> pair_eliminate_negations(fst, snd)
940956
end
941-
942-
case map_split_negative(negs, key, []) do
943-
:empty -> []
944-
negative -> negative |> pair_make_disjoint() |> pair_eliminate_negations(fst, snd)
945-
end
946957
end)
947958
end
948959

0 commit comments

Comments
 (0)