summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2019-08-21 17:56:23 -0700
committerEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2019-08-21 17:56:51 -0700
commit49014f5834dce974f7be5d28ade8a9d8cfd684e6 (patch)
treecb0b8524b36825954ac9ec78389c3496bbc504ff
parent71dc1a564a3b52bff37a3c68a820d76473619f81 (diff)
downloadelixir-49014f5834dce974f7be5d28ade8a9d8cfd684e6.tar.gz
Fix <<"x"::utf8>> false positive in clause check
-rw-r--r--lib/elixir/lib/module/types/infer.ex16
-rw-r--r--lib/elixir/test/elixir/module/types/infer_test.exs3
2 files changed, 16 insertions, 3 deletions
diff --git a/lib/elixir/lib/module/types/infer.ex b/lib/elixir/lib/module/types/infer.ex
index 02f87deb8..3a6299779 100644
--- a/lib/elixir/lib/module/types/infer.ex
+++ b/lib/elixir/lib/module/types/infer.ex
@@ -264,9 +264,15 @@ defmodule Module.Types.Infer do
end
expr_stack(full_expr, context, fn context ->
- with {:ok, type, context} <- of_pattern(expr, context),
- {:ok, _type, context} <- unify(type, expected_type, context),
- do: {:ok, context}
+ # Special case utf specifiers with binary literals since they allow
+ # both integer and binary literals but variables are always integer
+ if is_binary(expr) and utf_specifier?(specifiers) do
+ {:ok, context}
+ else
+ with {:ok, type, context} <- of_pattern(expr, context),
+ {:ok, _type, context} <- unify(type, expected_type, context),
+ do: {:ok, context}
+ end
end)
end
@@ -284,6 +290,10 @@ defmodule Module.Types.Infer do
end
end
+ defp utf_specifier?(specifiers) do
+ :utf8 in specifiers or :utf16 in specifiers or :utf32 in specifiers
+ end
+
# Collect binary type specifiers,
# from `<<pattern::integer-size(10)>>` collect `integer`
defp collect_specifiers({:-, _meta, [left, right]}) do
diff --git a/lib/elixir/test/elixir/module/types/infer_test.exs b/lib/elixir/test/elixir/module/types/infer_test.exs
index 71bb5c697..61820cdf2 100644
--- a/lib/elixir/test/elixir/module/types/infer_test.exs
+++ b/lib/elixir/test/elixir/module/types/infer_test.exs
@@ -124,9 +124,12 @@ defmodule Module.Types.InferTest do
assert quoted_pattern(<<"foo"::binary>>) == {:ok, :binary}
assert quoted_pattern(<<123::integer>>) == {:ok, :binary}
assert quoted_pattern(<<foo::integer>>) == {:ok, :binary}
+ assert quoted_pattern(<<123::utf8>>) == {:ok, :binary}
+ assert quoted_pattern(<<"foo"::utf8>>) == {:ok, :binary}
assert quoted_pattern({<<foo::integer>>, foo}) == {:ok, {:tuple, [:binary, :integer]}}
assert quoted_pattern({<<foo::binary>>, foo}) == {:ok, {:tuple, [:binary, :binary]}}
+ assert quoted_pattern({<<foo::utf8>>, foo}) == {:ok, {:tuple, [:binary, :integer]}}
assert {:error, {{:unable_unify, :integer, :binary, _, _}, _}} =
quoted_pattern(<<123::binary>>)