Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 6 additions & 69 deletions lib/elixir/lib/module/types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule Module.Types do
end

import Module.Types.Helpers
alias Module.Types.{Expr, Pattern}
alias Module.Types.{Expr, Pattern, Infer}

@doc false
def warnings(module, file, defs, no_warn_undefined, cache) do
Expand Down Expand Up @@ -179,9 +179,9 @@ defmodule Module.Types do
end
end

defp do_lift_type({:tuple, types}, context) do
defp do_lift_type({:tuple, n, types}, context) do
{types, context} = Enum.map_reduce(types, context, &do_lift_type/2)
{{:tuple, types}, context}
{{:tuple, n, types}, context}
end

defp do_lift_type({:map, pairs}, context) do
Expand Down Expand Up @@ -300,9 +300,9 @@ defmodule Module.Types do

[
"incompatible types:\n\n ",
format_type(left, simplify_left?),
Infer.format_type(left, simplify_left?),
" !~ ",
format_type(right, simplify_right?),
Infer.format_type(right, simplify_right?),
"\n\n",
format_expr(expr, location),
traces,
Expand Down Expand Up @@ -352,7 +352,7 @@ defmodule Module.Types do
"where \"",
Macro.to_string(var),
"\" was given the type ",
format_type(type, simplify?),
Infer.format_type(type, simplify?),
hint,
" in:\n\n # ",
format_location(location),
Expand Down Expand Up @@ -390,73 +390,10 @@ defmodule Module.Types do
[file, ?:, line, ?\n]
end

## TYPE FORMATTING

defp simplify_type?(type, other) do
map_type?(type) and not map_type?(other)
end

@doc false
def format_type({:map, pairs}, true) do
case List.keyfind(pairs, {:atom, :__struct__}, 1) do
{:required, {:atom, :__struct__}, {:atom, struct}} ->
"%#{inspect(struct)}{}"

_ ->
"map()"
end
end

def format_type({:union, types}, simplify?) do
"#{Enum.map_join(types, " | ", &format_type(&1, simplify?))}"
end

def format_type({:tuple, types}, simplify?) do
"{#{Enum.map_join(types, ", ", &format_type(&1, simplify?))}}"
end

def format_type({:list, type}, simplify?) do
"[#{format_type(type, simplify?)}]"
end

def format_type({:map, pairs}, false) do
case List.keytake(pairs, {:atom, :__struct__}, 1) do
{{:required, {:atom, :__struct__}, {:atom, struct}}, pairs} ->
"%#{inspect(struct)}{#{format_map_pairs(pairs)}}"

_ ->
"%{#{format_map_pairs(pairs)}}"
end
end

def format_type({:atom, literal}, _simplify?) do
inspect(literal)
end

def format_type({:var, index}, _simplify?) do
"var#{index}"
end

def format_type(atom, _simplify?) when is_atom(atom) do
"#{atom}()"
end

defp format_map_pairs(pairs) do
{atoms, others} = Enum.split_with(pairs, &match?({:required, {:atom, _}, _}, &1))
{required, optional} = Enum.split_with(others, &match?({:required, _, _}, &1))

Enum.map_join(atoms ++ required ++ optional, ", ", fn
{:required, {:atom, atom}, right} ->
"#{atom}: #{format_type(right, false)}"

{:required, left, right} ->
"#{format_type(left, false)} => #{format_type(right, false)}"

{:optional, left, right} ->
"optional(#{format_type(left, false)}) => #{format_type(right, false)}"
end)
end

## EXPRESSION FORMATTING

defp format_expr(nil, _location) do
Expand Down
8 changes: 4 additions & 4 deletions lib/elixir/lib/module/types/expr.ex
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ defmodule Module.Types.Expr do

# __STACKTRACE__
def of_expr({:__STACKTRACE__, _meta, var_context}, _stack, context) when is_atom(var_context) do
file = {:tuple, [{:atom, :file}, {:list, :integer}]}
line = {:tuple, [{:atom, :line}, :integer]}
file = {:tuple, 2, [{:atom, :file}, {:list, :integer}]}
line = {:tuple, 2, [{:atom, :line}, :integer]}
file_line = {:list, {:union, [file, line]}}
type = {:list, {:tuple, [:atom, :atom, :integer, file_line]}}
type = {:list, {:tuple, 4, [:atom, :atom, :integer, file_line]}}
{:ok, type, context}
end

Expand All @@ -123,7 +123,7 @@ defmodule Module.Types.Expr do
stack = push_expr_stack(expr, stack)

case map_reduce_ok(exprs, context, &of_expr(&1, stack, &2)) do
{:ok, types, context} -> {:ok, {:tuple, types}, context}
{:ok, types, context} -> {:ok, {:tuple, length(types), types}, context}
{:error, reason} -> {:error, reason}
end
end
Expand Down
Loading