Skip to content

Commit 42e2456

Browse files
committed
Move of_head to Pattern
1 parent 2de183e commit 42e2456

File tree

4 files changed

+41
-40
lines changed

4 files changed

+41
-40
lines changed

lib/elixir/lib/module/types.ex

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ defmodule Module.Types do
88
Infer function definitions' types.
99
"""
1010
def infer_definitions(file, module, defs, no_warn_undefined, cache) do
11+
stack = stack()
12+
1113
Enum.flat_map(defs, fn {{fun, _arity} = function, kind, meta, clauses} ->
1214
context = context(with_file_meta(meta, file), module, function, no_warn_undefined, cache)
1315

14-
Enum.flat_map(clauses, fn {_meta, params, guards, body} ->
15-
def_expr = {kind, meta, [guards_to_expr(guards, {fun, [], params})]}
16-
infer_clause(params, guards, body, def_expr, context)
16+
Enum.flat_map(clauses, fn {_meta, args, guards, body} ->
17+
def_expr = {kind, meta, [guards_to_expr(guards, {fun, [], args})]}
18+
infer_definition(args, guards, body, def_expr, stack, context)
1719
end)
1820
end)
1921
end
@@ -25,33 +27,18 @@ defmodule Module.Types do
2527
end
2628
end
2729

28-
@doc false
29-
def infer_clause(params, guards, body, def_expr, context) do
30-
with {:ok, _types, context} <- of_head(params, guards, def_expr, context),
31-
{:ok, _type, context} <- of_body(body, context) do
30+
defp infer_definition(args, guards, body, def_expr, stack, context) do
31+
head_stack = push_expr_stack(def_expr, stack)
32+
33+
with {:ok, _types, context} <- Pattern.of_head(args, guards, head_stack, context),
34+
{:ok, _type, context} <- Expr.of_expr(body, stack, context) do
3235
context.warnings
3336
else
3437
{:error, {type, error, context}} ->
3538
[error_to_warning(type, error, context) | context.warnings]
3639
end
3740
end
3841

39-
@doc false
40-
def of_head(params, guards, def_expr, context) do
41-
stack = push_expr_stack(def_expr, stack())
42-
43-
with {:ok, types, context} <-
44-
map_reduce_ok(params, context, &Pattern.of_pattern(&1, stack, &2)),
45-
# TODO: Check that of_guard/3 returns boolean() | :fail
46-
{:ok, _, context} <- Pattern.of_guard(guards_to_or(guards), stack, context),
47-
do: {:ok, types, context}
48-
end
49-
50-
@doc false
51-
def of_body(body, context) do
52-
Expr.of_expr(body, stack(), context)
53-
end
54-
5542
@doc false
5643
def context(file, module, function, no_warn_undefined, cache) do
5744
%{

lib/elixir/lib/module/types/expr.ex

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,7 @@ defmodule Module.Types.Expr do
469469
each_ok(clauses, fn {:->, _meta, [head, body]} ->
470470
{patterns, guards} = extract_head(head)
471471

472-
with {:ok, _pattern_types, context} <-
473-
map_reduce_ok(patterns, context, &Pattern.of_pattern(&1, stack, &2)),
474-
# TODO: Check that of_guard/3 returns a boolean
475-
{:ok, _guard_type, context} <- Pattern.of_guard(guards_to_or(guards), stack, context),
472+
with {:ok, _, context} <- Pattern.of_head(patterns, guards, stack, context),
476473
{:ok, _expr_type, _context} <- of_expr(body, stack, context),
477474
do: :ok
478475
end)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ defmodule Module.Types.Pattern do
44
alias Module.Types.Remote
55
import Module.Types.{Helpers, Infer}
66

7+
@doc """
8+
Handles patterns and guards at once.
9+
"""
10+
def of_head(patterns, guards, stack, context) do
11+
with {:ok, types, context} <-
12+
map_reduce_ok(patterns, context, &of_pattern(&1, stack, &2)),
13+
# TODO: Check that of_guard/3 returns boolean() | :fail
14+
{:ok, _, context} <- of_guard(guards_to_or(guards), stack, context),
15+
do: {:ok, types, context}
16+
end
17+
718
@doc """
819
Return the type and typing context of a pattern expression or an error
920
in case of a typing conflict.

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

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ Code.require_file("../../test_helper.exs", __DIR__)
33
defmodule Module.Types.PatternTest do
44
use ExUnit.Case, async: true
55
import Module.Types.Infer, only: [new_var: 2]
6-
import Module.Types.Pattern
6+
77
alias Module.Types
8+
alias Module.Types.Pattern
89

910
defmacrop quoted_pattern(patterns) do
1011
quote do
1112
{patterns, true} = unquote(Macro.escape(expand_head(patterns, true)))
1213

13-
of_pattern(patterns, new_stack(), new_context())
14+
Pattern.of_pattern(patterns, new_stack(), new_context())
1415
|> lift_result()
1516
end
1617
end
@@ -20,7 +21,7 @@ defmodule Module.Types.PatternTest do
2021
{vars, guards} = unquote(Macro.escape(expand_head(vars, guards)))
2122
context = Enum.reduce(vars, new_context(), &(new_var(&1, &2) |> elem(1)))
2223

23-
of_guard(guards, new_stack(), context)
24+
Pattern.of_guard(guards, new_stack(), context)
2425
end
2526
end
2627

@@ -242,16 +243,18 @@ end
242243
defmodule Module.Types.TempTypesTest do
243244
use ExUnit.Case, async: true
244245
import Bitwise, warn: false
246+
245247
alias Module.Types
248+
alias Module.Types.{Expr, Pattern}
246249

247250
defmacrop quoted_head(patterns, guards \\ [true]) do
248251
quote do
249252
{patterns, guards} = unquote(Macro.escape(expand_head(patterns, guards)))
250253

251-
Types.of_head(
254+
Pattern.of_head(
252255
patterns,
253256
guards,
254-
def_expr(),
257+
new_stack(),
255258
new_context()
256259
)
257260
|> lift_result()
@@ -262,8 +265,8 @@ defmodule Module.Types.TempTypesTest do
262265
quote do
263266
{patterns, guards, body} = unquote(Macro.escape(expand_expr(patterns, guards, body)))
264267

265-
with {:ok, _types, context} <- Types.of_head(patterns, guards, def_expr(), new_context()),
266-
{:ok, type, context} <- Types.of_body(body, context) do
268+
with {:ok, _types, context} <- Pattern.of_head(patterns, guards, new_stack(), new_context()),
269+
{:ok, type, context} <- Expr.of_expr(body, new_stack(), context) do
267270
{:ok, Types.lift_type(type, context)}
268271
else
269272
{:error, {type, reason, _context}} ->
@@ -304,8 +307,11 @@ defmodule Module.Types.TempTypesTest do
304307
Types.context("types_test.ex", TypesTest, {:test, 0}, [], Module.ParallelChecker.test_cache())
305308
end
306309

307-
defp def_expr() do
308-
{:def, [], {:test, [], []}}
310+
defp new_stack() do
311+
%{
312+
Types.stack()
313+
| last_expr: {:foo, [], nil}
314+
}
309315
end
310316

311317
defp lift_result({:ok, types, context}) when is_list(types) do
@@ -323,18 +329,18 @@ defmodule Module.Types.TempTypesTest do
323329
assert quoted_head([a, a]) == {:ok, [{:var, 0}, {:var, 0}]}
324330

325331
assert {:ok, [{:var, 0}, {:var, 0}], _} =
326-
Types.of_head(
332+
Pattern.of_head(
327333
[{:a, [version: 0], :foo}, {:a, [version: 0], :foo}],
328334
[],
329-
def_expr(),
335+
new_stack(),
330336
new_context()
331337
)
332338

333339
assert {:ok, [{:var, 0}, {:var, 1}], _} =
334-
Types.of_head(
340+
Pattern.of_head(
335341
[{:a, [version: 0], :foo}, {:a, [version: 1], :foo}],
336342
[],
337-
def_expr(),
343+
new_stack(),
338344
new_context()
339345
)
340346
end

0 commit comments

Comments
 (0)