Skip to content

Commit 0dbdada

Browse files
committed
Revert previous strategy to use multiple differences
1 parent d4495ae commit 0dbdada

3 files changed

Lines changed: 65 additions & 19 deletions

File tree

lib/elixir/lib/module/types/pattern.ex

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,44 @@ defmodule Module.Types.Pattern do
1212
Returns the initial value for previous clause information.
1313
"""
1414
def init_previous do
15-
{[], none()}
15+
[]
1616
end
1717

18-
defp empty_previous?({list, _descr}), do: list == []
18+
defp empty_previous?([]), do: true
19+
defp empty_previous?([_ | _]), do: false
1920

20-
defp previous_subtype?(_, {[], _}), do: false
21+
defp previous_subtype?(_, []), do: false
2122
defp previous_subtype?([], _), do: true
22-
defp previous_subtype?([type], {_, descr}), do: subtype?(type, descr)
23-
defp previous_subtype?(args, {_, descr}), do: subtype?(args_to_domain(args), descr)
23+
24+
defp previous_subtype?([type], previous),
25+
do: subtype?(type, Enum.reduce(previous, none(), &union(&2, hd(&1))))
26+
27+
defp previous_subtype?(args, previous) do
28+
subtype?(
29+
args_to_domain(args),
30+
Enum.reduce(previous, none(), &union(&2, args_to_domain(&1)))
31+
)
32+
end
2433

2534
defp concat_previous([], previous),
2635
do: previous
2736

28-
defp concat_previous([type], {list, descr}),
29-
do: {[[type] | list], union(type, descr)}
30-
31-
defp concat_previous(types, {list, descr}),
32-
do: {[types | list], union(args_to_domain(types), descr)}
37+
defp concat_previous(types, previous),
38+
do: [types | previous]
3339

34-
defp of_pattern_previous(types, {[], _}, _trees, _pattern_info, _tag, _stack, _context) do
40+
defp of_pattern_previous(types, [], _trees, _pattern_info, _tag, _stack, _context) do
3541
{:ok, types}
3642
end
3743

38-
defp of_pattern_previous(types, {_, descr}, trees, pattern_info, tag, stack, context) do
44+
defp of_pattern_previous(types, previous, trees, pattern_info, tag, stack, context) do
3945
types =
4046
case types do
4147
[type] ->
42-
[difference(type, descr)]
48+
[Enum.reduce(previous, type, &difference(&2, hd(&1)))]
4349

4450
[_ | _] ->
45-
types
46-
|> args_to_domain()
47-
|> difference(descr)
51+
previous
52+
|> Enum.reduce(args_to_domain(types), &difference(&2, args_to_domain(&1)))
4853
|> domain_to_flat_args(types)
4954
end
5055

@@ -57,7 +62,7 @@ defmodule Module.Types.Pattern do
5762
end
5863
end
5964

60-
defp previous_to_string({previous, _}) do
65+
defp previous_to_string(previous) do
6166
Enum.map_join(previous, "\n ", fn types ->
6267
types
6368
|> Enum.map_join(", ", &to_quoted_string/1)

lib/elixir/test/elixir/module/types/integration_test.exs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,47 @@ defmodule Module.Types.IntegrationTest do
887887
assert_no_warnings(files)
888888
end
889889

890+
test "redundant clause checking with nested open maps" do
891+
files = %{
892+
"nested_maps.ex" => """
893+
defmodule NestedMapsIssue do
894+
def foo(%{a: nil, b: %{c: true}}), do: :ok
895+
def foo(%{a: nil, b: %{c: false}}), do: :ok
896+
def foo(%{a: nil, b: %{d: x}}) when is_list(x), do: :ok
897+
def foo(%{a: nil, b: %{e: x}}) when is_list(x), do: :ok
898+
def foo(%{a: nil, b: %{f: x}}) when is_list(x), do: :ok
899+
def foo(%{a: nil}), do: :ok
900+
def foo(%{b: %{g: :one, h: x}}) when is_map(x), do: :ok
901+
def foo(%{b: %{g: _, i: x}}) when is_list(x), do: :ok
902+
def foo(%{b: %{g: _, j: x}}) when is_list(x), do: :ok
903+
def foo(%{b: %{g: _, k: x}}) when is_list(x), do: :ok
904+
def foo(%{b: %{g: :one}}), do: :ok
905+
def foo(%{b: %{g: :two}}), do: :ok
906+
def foo(%{b: %{g: :three}}), do: :ok
907+
def foo(%{b: %{g: :four}}), do: :ok
908+
def foo(%{b: %{g: :five}}), do: :ok
909+
def foo(%{b: %{g: :six}}), do: :ok
910+
def foo(%{b: %{l: x}}) when is_list(x), do: :ok
911+
def foo(%{b: %{m: x}}) when is_list(x), do: :ok
912+
def foo(%{b: %{n: x}}) when is_list(x), do: :ok
913+
def foo(%{b: %{o: x}}) when is_list(x), do: :ok
914+
def foo(%{b: %{p: x, q: y}}) when is_number(x) and is_number(y), do: :ok
915+
def foo(%{b: %{p: x}}) when is_number(x), do: :ok
916+
def foo(%{b: %{q: x}}) when is_number(x), do: :ok
917+
def foo(%{b: %{r: x}}) when is_integer(x), do: :ok
918+
def foo(%{b: %{s: x}}) when is_integer(x), do: :ok
919+
def foo(%{b: %{t: x}}) when is_binary(x), do: :ok
920+
def foo(%{b: %{u: x}}) when is_atom(x), do: :ok
921+
def foo(%{b: %{v: x}}) when is_integer(x), do: :ok
922+
def foo(%{b: %{w: x}}) when is_integer(x), do: :ok
923+
def foo(_), do: :ok
924+
end
925+
"""
926+
}
927+
928+
assert_no_warnings(files)
929+
end
930+
890931
test "unions and intersections of open maps" do
891932
files = %{
892933
"large_head.ex" => """

lib/elixir/test/elixir/module/types/type_helper.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,10 @@ defmodule TypeHelper do
156156
previous = Pattern.init_previous()
157157
tag = {:fn, patterns}
158158

159-
{_trees, {previous, _}, _context} =
159+
{_trees, previous, _context} =
160160
Pattern.of_head(patterns, guards, expected, previous, tag, [], stack, new_context())
161161

162-
previous != []
162+
not match?([], previous)
163163
end
164164

165165
def __typecheck__(mode, patterns, guards, body) do

0 commit comments

Comments
 (0)