Skip to content

Commit c8c7abc

Browse files
committed
Do not check previous if we know args types and previous are disjoint
1 parent 690323e commit c8c7abc

1 file changed

Lines changed: 14 additions & 11 deletions

File tree

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ defmodule Module.Types.Pattern do
3434
defp args_to_previous(types), do: args_to_static_domain(types)
3535

3636
defp of_pattern_previous(types, [], _trees, _pattern_info, _tag, _stack, _context) do
37-
{:ok, types}
37+
{:ok, types, false}
3838
end
3939

4040
defp of_pattern_previous(types, previous, trees, pattern_info, tag, stack, context) do
41-
types =
41+
refined_types =
4242
case types do
4343
[type] ->
4444
[Enum.reduce(previous, type, &difference(&2, elem(&1, 1)))]
@@ -54,7 +54,10 @@ defmodule Module.Types.Pattern do
5454
context = badpattern_error(pattern, index, tag, stack, context)
5555
{:error, error_vars(pattern_info, context)}
5656
else
57-
{:ok, types}
57+
# check_previous? is an optimization. If types have not changed,
58+
# it means args_types and previous are disjoint, and any further
59+
# refinement will keep them disjoint, so no need to check for previous.
60+
{:ok, refined_types, stack.mode != :infer and types != refined_types}
5861
end
5962
end
6063

@@ -190,18 +193,18 @@ defmodule Module.Types.Pattern do
190193
def of_head(patterns, guards, expected, previous, tag, meta, stack, original) do
191194
stack = %{stack | meta: meta}
192195

193-
{trees, precise?, args_types, context} =
196+
{trees, precise?, check_previous?, args_types, context} =
194197
of_precise_head(patterns, guards, expected, previous, tag, stack, original)
195198

196199
if context.failed and stack.mode != :infer and not empty_previous?(previous) and
197200
Keyword.get(meta, :generated, false) != true do
198201
# If it failed, let's try to break it down to a better error message.
199202
# First we check if it fails without previous, if it doesn't, check if it is redundant.
200203
case of_precise_head(patterns, guards, expected, init_previous(), tag, stack, original) do
201-
{other_trees, _, _, %{failed: true} = other_context} ->
204+
{other_trees, _, _, _, %{failed: true} = other_context} ->
202205
{other_trees, previous, other_context}
203206

204-
{other_trees, _, args_types, other_context} ->
207+
{other_trees, _, _, args_types, other_context} ->
205208
if previous_subtype?(args_types, previous) do
206209
warning = {:redundant, tag, expected, args_types, previous, other_context}
207210
{other_trees, previous, warn(__MODULE__, warning, meta, stack, other_context)}
@@ -211,7 +214,7 @@ defmodule Module.Types.Pattern do
211214
end
212215
else
213216
cond do
214-
stack.mode != :infer and previous_subtype?(args_types, previous) ->
217+
check_previous? and previous_subtype?(args_types, previous) ->
215218
warning = {:redundant, tag, expected, args_types, previous, context}
216219
{trees, previous, warn(__MODULE__, warning, meta, stack, context)}
217220

@@ -227,7 +230,7 @@ defmodule Module.Types.Pattern do
227230
defp of_precise_head([], guards, _expected, _previous, _tag, stack, context) do
228231
%{vars: vars} = context
229232
{guard_precise?, changed, context} = of_guards(guards, vars, stack, context)
230-
{[], guard_precise?, [], of_changed(Map.keys(changed), stack, context)}
233+
{[], guard_precise?, false, [], of_changed(Map.keys(changed), stack, context)}
231234
end
232235

233236
defp of_precise_head(patterns, guards, expected, previous, tag, stack, context) do
@@ -251,15 +254,15 @@ defmodule Module.Types.Pattern do
251254
else
252255
_ -> nil
253256
end),
254-
{:ok, types} <-
257+
{:ok, types, check_previous?} <-
255258
of_pattern_previous(types, previous, trees, pattern_info, tag, stack, context),
256259
{:ok, _types, context} <-
257260
of_pattern_refine(types, changed, pattern_info, tag, stack, context) do
258-
{trees, pattern_precise? and guard_precise?,
261+
{trees, pattern_precise? and guard_precise?, check_previous?,
259262
args_types || trees_to_args_types(trees, stack, context), context}
260263
else
261264
{:error, context} ->
262-
{trees, false, trees_to_args_types(trees, stack, context), context}
265+
{trees, false, false, trees_to_args_types(trees, stack, context), context}
263266
end
264267
end
265268

0 commit comments

Comments
 (0)