diff options
author | Eric Meadows-Jönsson <eric.meadows.jonsson@gmail.com> | 2019-08-21 17:56:23 -0700 |
---|---|---|
committer | Eric Meadows-Jönsson <eric.meadows.jonsson@gmail.com> | 2019-08-21 17:56:51 -0700 |
commit | 49014f5834dce974f7be5d28ade8a9d8cfd684e6 (patch) | |
tree | cb0b8524b36825954ac9ec78389c3496bbc504ff | |
parent | 71dc1a564a3b52bff37a3c68a820d76473619f81 (diff) | |
download | elixir-49014f5834dce974f7be5d28ade8a9d8cfd684e6.tar.gz |
Fix <<"x"::utf8>> false positive in clause check
-rw-r--r-- | lib/elixir/lib/module/types/infer.ex | 16 | ||||
-rw-r--r-- | lib/elixir/test/elixir/module/types/infer_test.exs | 3 |
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>>) |