Skip to content

Commit

Permalink
Fix binary typespecs
Browse files Browse the repository at this point in the history
  * Removes <<_::size*unit>>
  * Adds <<_::size, _::_*unit>>
  • Loading branch information
ericmj committed May 23, 2016
1 parent 97fb96a commit 05eb347
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 17 deletions.
20 changes: 10 additions & 10 deletions lib/elixir/lib/kernel/typespec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,13 @@ defmodule Kernel.Typespec do

defp typespec_to_ast({:type, line, :binary, [arg1, arg2]}) do
[arg1, arg2] = for arg <- [arg1, arg2], do: typespec_to_ast(arg)
cond do
arg2 == 0 ->
case {typespec_to_ast(arg1), typespec_to_ast(arg2)} do
{arg1, 0} ->
quote line: line, do: <<_ :: unquote(arg1)>>
arg1 == 0 ->
{0, arg2} ->
quote line: line, do: <<_ :: _ * unquote(arg2)>>
true ->
quote line: line, do: <<_ :: unquote(arg1) * unquote(arg2)>>
{arg1, arg2} ->
quote line: line, do: <<_ :: unquote(arg1), _ :: _ * unquote(arg2)>>
end
end

Expand Down Expand Up @@ -719,16 +719,16 @@ defmodule Kernel.Typespec do
{:type, line(meta), :binary, [{:integer, line(meta), 0}, {:integer, line(unit_meta), unit}]}
end

defp typespec({:<<>>, meta, [{:::, shared_meta, [{:_, _, ctx}, {:*, _, [size, unit]}]}]}, _, _)
when is_atom(ctx) and is_integer(unit) and is_integer(size) do
{:type, line(meta), :binary, [{:integer, line(shared_meta), size}, {:integer, line(shared_meta), unit}]}
end

defp typespec({:<<>>, meta, [{:::, size_meta, [{:_, _, ctx}, size]}]}, _, _)
when is_atom(ctx) and is_integer(size) do
{:type, line(meta), :binary, [{:integer, line(size_meta), size}, {:integer, line(meta), 0}]}
end

defp typespec({:<<>>, meta, [{:::, size_meta, [{:_, _, ctx1}, size]}, {:::, unit_meta, [{:_, _, ctx2}, {:*, _, [{:_, _, ctx3}, unit]}]}]}, _, _)
when is_atom(ctx1) and is_atom(ctx2) and is_atom(ctx3) and is_integer(size) and is_integer(unit) do
{:type, line(meta), :binary, [{:integer, line(size_meta), size}, {:integer, line(unit_meta), unit}]}
end

## Handle maps and structs
defp typespec({:map, meta, args}, _vars, _caller) when args == [] or is_atom(args) do
{:type, line(meta), :map, :any}
Expand Down
6 changes: 3 additions & 3 deletions lib/elixir/pages/Typespecs.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ The following literals are also supported in typespecs:
| 1.0 ## Floats

| <<>> ## Bitstrings
| <<_::size>> # size is 0 or a positive integer
| <<_::_ * unit>> # unit is an integer from 1 to 256
| <<_::size * unit>>
| <<_::size>> # size is 0 or a positive integer
| <<_::_*unit>> # unit is an integer from 1 to 256
| <<_::size, _::_*unit>>

| [type] ## Lists
| [] # empty list
Expand Down
25 changes: 21 additions & 4 deletions lib/elixir/test/elixir/kernel/typespec_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ defmodule Kernel.TypespecTest do

test "@type with a binary with a base size" do
module = test_module do
@type mytype :: <<_ :: 3>>
@type mytype :: <<_::3>>
end

assert [type: {:mytype, {:type, _, :binary, [{:integer, _, 3}, {:integer, _, 0}]}, []}] =
Expand All @@ -160,6 +160,23 @@ defmodule Kernel.TypespecTest do
types(module)
end

test "@type with a binary with a size and unit size" do
module = test_module do
@type mytype :: <<_::3, _::_*8>>
end

assert [type: {:mytype, {:type, _, :binary, [{:integer, _, 3}, {:integer, _, 8}]}, []}] =
types(module)
end

test "@type with invalid binary spec" do
assert_raise CompileError, fn ->
test_module do
@type mytype :: <<_::3*8>>
end
end
end

test "@type with a range op" do
module = test_module do
@type mytype :: 1..10
Expand Down Expand Up @@ -545,9 +562,9 @@ defmodule Kernel.TypespecTest do
(quote do: @type simple_type() :: integer()),
(quote do: @type param_type(p) :: [p]),
(quote do: @type union_type() :: integer() | binary() | boolean()),
(quote do: @type binary_type1() :: <<_ :: _ * 8>>),
(quote do: @type binary_type2() :: <<_ :: 3 * 8>>),
(quote do: @type binary_type3() :: <<_ :: 3>>),
(quote do: @type binary_type1() :: <<_::_*8>>),
(quote do: @type binary_type2() :: <<_::3>>),
(quote do: @type binary_type3() :: <<_::3, _::_*8>>),
(quote do: @type tuple_type() :: {integer()}),
(quote do: @type ftype() :: (() -> any()) | (() -> integer()) | ((integer() -> integer()))),
(quote do: @type cl() :: charlist()),
Expand Down

0 comments on commit 05eb347

Please sign in to comment.