Skip to content

Commit 215a3ee

Browse files
committed
Remove none clauses if there are non empty clauses, closes #15777
1 parent f17ff48 commit 215a3ee

2 files changed

Lines changed: 52 additions & 8 deletions

File tree

lib/elixir/lib/module/types.ex

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -441,24 +441,51 @@ defmodule Module.Types do
441441
end
442442

443443
defp group_clauses(clauses) do
444-
[{{args, _head_args, _head_no_previous_args}, _return, _precise?} | clauses_tail] = clauses
444+
{_, all_clauses, filtered_clauses, non_empty?} =
445+
Enum.reduce(clauses, {0, [], [], false}, fn
446+
{_args_triplet, return, precise?} = clause,
447+
{index, all_clauses, filtered_clauses, non_empty?} ->
448+
empty? = Descr.empty?(return)
449+
indexed_clause = {clause, index}
450+
451+
filtered_clauses =
452+
if precise? and empty? do
453+
filtered_clauses
454+
else
455+
[indexed_clause | filtered_clauses]
456+
end
457+
458+
{index + 1, [indexed_clause | all_clauses], filtered_clauses, non_empty? or not empty?}
459+
end)
460+
461+
clauses =
462+
if non_empty? do
463+
Enum.reverse(filtered_clauses)
464+
else
465+
Enum.reverse(all_clauses)
466+
end
467+
468+
[
469+
{{{args, _head_args, _head_no_previous_args}, _return, _precise?}, _index}
470+
| clauses_tail
471+
] = clauses
445472

446473
domain =
447474
Enum.reduce(clauses_tail, args, fn
448-
{{args, head_args, head_no_previous_args}, _return, _precise?}, domain ->
475+
{{{args, head_args, head_no_previous_args}, _return, _precise?}, _index}, domain ->
449476
compute_domain(args, head_args, head_no_previous_args, domain)
450477
end)
451478

452-
{_, _, mapping, inferred} =
453-
Enum.reduce(clauses, {0, 0, [], []}, fn
454-
{{args, _head_args, _head_no_previous_args}, return, _precise?},
455-
{index, total, mapping, inferred} ->
479+
{_, mapping, inferred} =
480+
Enum.reduce(clauses, {0, [], []}, fn
481+
{{{args, _head_args, _head_no_previous_args}, return, _precise?}, index},
482+
{total, mapping, inferred} ->
456483
{type_index, inferred} = add_inferred(inferred, args, return, total - 1, [])
457484

458485
if type_index == -1 do
459-
{index + 1, total + 1, [{index, total} | mapping], inferred}
486+
{total + 1, [{index, total} | mapping], inferred}
460487
else
461-
{index + 1, total, [{index, type_index} | mapping], inferred}
488+
{total, [{index, type_index} | mapping], inferred}
462489
end
463490
end)
464491

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@ defmodule Module.Types.InferTest do
124124
assert length(clauses) == 2
125125
end
126126

127+
test "from patterns (with empty return type)", config do
128+
types =
129+
infer config do
130+
def all_empty(:ok), do: raise("oops")
131+
def all_empty(:error), do: raise("oops")
132+
133+
def mixed({:ok, value}), do: value
134+
def mixed(value), do: raise("oops: #{inspect(value)}")
135+
end
136+
137+
assert types[{:all_empty, 1}] ==
138+
{:infer, [atom([:ok, :error])], [{[atom([:ok, :error])], dynamic(none())}]}
139+
140+
assert types[{:mixed, 1}] ==
141+
{:infer, nil, [{[tuple([atom([:ok]), term()])], dynamic()}]}
142+
end
143+
127144
test "from expressions", config do
128145
types =
129146
infer config do

0 commit comments

Comments
 (0)