Skip to content

Commit 30cbdb8

Browse files
ericmjJosé Valim
authored andcommitted
Fix binary typespecs
* Removes <<_::size*unit>> * Adds <<_::size, _::_*unit>> Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
1 parent d1773cf commit 30cbdb8

File tree

3 files changed

+34
-17
lines changed

3 files changed

+34
-17
lines changed

lib/elixir/lib/kernel/typespec.ex

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -580,13 +580,13 @@ defmodule Kernel.Typespec do
580580

581581
defp typespec_to_ast({:type, line, :binary, [arg1, arg2]}) do
582582
[arg1, arg2] = for arg <- [arg1, arg2], do: typespec_to_ast(arg)
583-
cond do
584-
arg2 == 0 ->
583+
case {typespec_to_ast(arg1), typespec_to_ast(arg2)} do
584+
{arg1, 0} ->
585585
quote line: line, do: <<_ :: unquote(arg1)>>
586-
arg1 == 0 ->
586+
{0, arg2} ->
587587
quote line: line, do: <<_ :: _ * unquote(arg2)>>
588-
true ->
589-
quote line: line, do: <<_ :: unquote(arg1) * unquote(arg2)>>
588+
{arg1, arg2} ->
589+
quote line: line, do: <<_ :: unquote(arg1), _ :: _ * unquote(arg2)>>
590590
end
591591
end
592592

@@ -707,16 +707,16 @@ defmodule Kernel.Typespec do
707707
{:type, line(meta), :binary, [{:integer, line(meta), 0}, {:integer, line(unit_meta), unit}]}
708708
end
709709

710-
defp typespec({:<<>>, meta, [{:::, shared_meta, [{:_, _, ctx}, {:*, _, [size, unit]}]}]}, _, _)
711-
when is_atom(ctx) and is_integer(unit) and is_integer(size) do
712-
{:type, line(meta), :binary, [{:integer, line(shared_meta), size}, {:integer, line(shared_meta), unit}]}
713-
end
714-
715710
defp typespec({:<<>>, meta, [{:::, size_meta, [{:_, _, ctx}, size]}]}, _, _)
716711
when is_atom(ctx) and is_integer(size) do
717712
{:type, line(meta), :binary, [{:integer, line(size_meta), size}, {:integer, line(meta), 0}]}
718713
end
719714

715+
defp typespec({:<<>>, meta, [{:::, size_meta, [{:_, _, ctx1}, size]}, {:::, unit_meta, [{:_, _, ctx2}, {:*, _, [{:_, _, ctx3}, unit]}]}]}, _, _)
716+
when is_atom(ctx1) and is_atom(ctx2) and is_atom(ctx3) and is_integer(size) and is_integer(unit) do
717+
{:type, line(meta), :binary, [{:integer, line(size_meta), size}, {:integer, line(unit_meta), unit}]}
718+
end
719+
720720
## Handle maps and structs
721721
defp typespec({:map, meta, args}, _vars, _caller) when args == [] or is_atom(args) do
722722
{:type, line(meta), :map, :any}

lib/elixir/pages/Typespecs.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ The following literals are also supported in typespecs:
5858
| 1.0 ## Floats
5959

6060
| <<>> ## Bitstrings
61-
| <<_::size>> # size is 0 or a positive integer
62-
| <<_::_ * unit>> # unit is an integer from 1 to 256
63-
| <<_::size * unit>>
61+
| <<_::size>> # size is 0 or a positive integer
62+
| <<_::_*unit>> # unit is an integer from 1 to 256
63+
| <<_::size, _::_*unit>>
6464

6565
| [type] ## Lists
6666
| [] # empty list

lib/elixir/test/elixir/kernel/typespec_test.exs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ defmodule Kernel.TypespecTest do
144144

145145
test "@type with a binary with a base size" do
146146
module = test_module do
147-
@type mytype :: <<_ :: 3>>
147+
@type mytype :: <<_::3>>
148148
end
149149

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

163+
test "@type with a binary with a size and unit size" do
164+
module = test_module do
165+
@type mytype :: <<_::3, _::_*8>>
166+
end
167+
168+
assert [type: {:mytype, {:type, _, :binary, [{:integer, _, 3}, {:integer, _, 8}]}, []}] =
169+
types(module)
170+
end
171+
172+
test "@type with invalid binary spec" do
173+
assert_raise CompileError, fn ->
174+
test_module do
175+
@type mytype :: <<_::3*8>>
176+
end
177+
end
178+
end
179+
163180
test "@type with a range op" do
164181
module = test_module do
165182
@type mytype :: 1..10
@@ -545,9 +562,9 @@ defmodule Kernel.TypespecTest do
545562
(quote do: @type simple_type() :: integer()),
546563
(quote do: @type param_type(p) :: [p]),
547564
(quote do: @type union_type() :: integer() | binary() | boolean()),
548-
(quote do: @type binary_type1() :: <<_ :: _ * 8>>),
549-
(quote do: @type binary_type2() :: <<_ :: 3 * 8>>),
550-
(quote do: @type binary_type3() :: <<_ :: 3>>),
565+
(quote do: @type binary_type1() :: <<_::_*8>>),
566+
(quote do: @type binary_type2() :: <<_::3>>),
567+
(quote do: @type binary_type3() :: <<_::3, _::_*8>>),
551568
(quote do: @type tuple_type() :: {integer()}),
552569
(quote do: @type ftype() :: (() -> any()) | (() -> integer()) | ((integer() -> integer()))),
553570
(quote do: @type cl() :: char_list()),

0 commit comments

Comments
 (0)