summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2020-03-02 16:55:45 -0800
committerEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2020-03-02 16:55:45 -0800
commite7b590feb09e3c24ef69bdf953fb1cfaa51706aa (patch)
tree5c12aa699ea81bed43e8f43b2399daa7984f0ee2
parent95f18c6f515ef79dbc0922a15c76c1c969bd8d73 (diff)
downloadelixir-e7b590feb09e3c24ef69bdf953fb1cfaa51706aa.tar.gz
-rw-r--r--lib/elixir/test/elixir/module/types/expr_test.exs261
1 files changed, 150 insertions, 111 deletions
diff --git a/lib/elixir/test/elixir/module/types/expr_test.exs b/lib/elixir/test/elixir/module/types/expr_test.exs
index 7dfc8aec8..d1eaa96ef 100644
--- a/lib/elixir/test/elixir/module/types/expr_test.exs
+++ b/lib/elixir/test/elixir/module/types/expr_test.exs
@@ -55,78 +55,86 @@ defmodule Module.Types.ExprTest do
defstruct foo: :atom, bar: 123, baz: %{}
end
- describe "of_expr/3" do
- test "literal" do
- assert quoted_expr(true) == {:ok, {:atom, true}}
- assert quoted_expr(false) == {:ok, {:atom, false}}
- assert quoted_expr(:foo) == {:ok, {:atom, :foo}}
- assert quoted_expr(0) == {:ok, :integer}
- assert quoted_expr(0.0) == {:ok, :float}
- assert quoted_expr("foo") == {:ok, :binary}
- end
+ test "literal" do
+ assert quoted_expr(true) == {:ok, {:atom, true}}
+ assert quoted_expr(false) == {:ok, {:atom, false}}
+ assert quoted_expr(:foo) == {:ok, {:atom, :foo}}
+ assert quoted_expr(0) == {:ok, :integer}
+ assert quoted_expr(0.0) == {:ok, :float}
+ assert quoted_expr("foo") == {:ok, :binary}
+ end
- test "list" do
+ describe "list" do
+ test "proper" do
assert quoted_expr([]) == {:ok, {:list, :dynamic}}
assert quoted_expr([123]) == {:ok, {:list, :integer}}
assert quoted_expr([123, 456]) == {:ok, {:list, :integer}}
assert quoted_expr([123 | []]) == {:ok, {:list, :integer}}
assert quoted_expr([123, "foo"]) == {:ok, {:list, {:union, [:integer, :binary]}}}
assert quoted_expr([123 | ["foo"]]) == {:ok, {:list, {:union, [:integer, :binary]}}}
+ end
- # TODO: improper list?
+ test "improper" do
assert quoted_expr([123 | 456]) == {:ok, {:list, :integer}}
assert quoted_expr([123, 456 | 789]) == {:ok, {:list, :integer}}
assert quoted_expr([123 | "foo"]) == {:ok, {:list, {:union, [:integer, :binary]}}}
end
+ end
- test "tuple" do
- assert quoted_expr({}) == {:ok, {:tuple, []}}
- assert quoted_expr({:a}) == {:ok, {:tuple, [{:atom, :a}]}}
- assert quoted_expr({:a, 123}) == {:ok, {:tuple, [{:atom, :a}, :integer]}}
- end
+ test "tuple" do
+ assert quoted_expr({}) == {:ok, {:tuple, []}}
+ assert quoted_expr({:a}) == {:ok, {:tuple, [{:atom, :a}]}}
+ assert quoted_expr({:a, 123}) == {:ok, {:tuple, [{:atom, :a}, :integer]}}
+ end
- test "map" do
- assert quoted_expr(%{}) == {:ok, {:map, []}}
- assert quoted_expr(%{a: :b}) == {:ok, {:map, [{{:atom, :a}, {:atom, :b}}]}}
- assert quoted_expr([a], %{123 => a}) == {:ok, {:map, [{:integer, {:var, 0}}]}}
+ test "map" do
+ assert quoted_expr(%{}) == {:ok, {:map, []}}
+ assert quoted_expr(%{a: :b}) == {:ok, {:map, [{{:atom, :a}, {:atom, :b}}]}}
+ assert quoted_expr([a], %{123 => a}) == {:ok, {:map, [{:integer, {:var, 0}}]}}
- assert quoted_expr(%{123 => :foo, 456 => :bar}) ==
- {:ok, {:map, [{:integer, {:union, [{:atom, :bar}, {:atom, :foo}]}}]}}
- end
+ assert quoted_expr(%{123 => :foo, 456 => :bar}) ==
+ {:ok, {:map, [{:integer, {:union, [{:atom, :bar}, {:atom, :foo}]}}]}}
+ end
- test "struct" do
- assert quoted_expr(%:"Elixir.Module.Types.ExprTest.Struct"{}) ==
- {:ok,
- {:map,
- [
- {{:atom, :__struct__}, {:atom, Module.Types.ExprTest.Struct}},
- {{:atom, :bar}, :integer},
- {{:atom, :baz}, {:map, []}},
- {{:atom, :foo}, {:atom, :atom}}
- ]}}
-
- assert quoted_expr(%:"Elixir.Module.Types.ExprTest.Struct"{foo: 123, bar: :atom}) ==
- {:ok,
- {:map,
- [
- {{:atom, :__struct__}, {:atom, Module.Types.ExprTest.Struct}},
- {{:atom, :baz}, {:map, []}},
- {{:atom, :foo}, :integer},
- {{:atom, :bar}, {:atom, :atom}}
- ]}}
- end
+ test "struct" do
+ assert quoted_expr(%:"Elixir.Module.Types.ExprTest.Struct"{}) ==
+ {:ok,
+ {:map,
+ [
+ {{:atom, :__struct__}, {:atom, Module.Types.ExprTest.Struct}},
+ {{:atom, :bar}, :integer},
+ {{:atom, :baz}, {:map, []}},
+ {{:atom, :foo}, {:atom, :atom}}
+ ]}}
+
+ assert quoted_expr(%:"Elixir.Module.Types.ExprTest.Struct"{foo: 123, bar: :atom}) ==
+ {:ok,
+ {:map,
+ [
+ {{:atom, :__struct__}, {:atom, Module.Types.ExprTest.Struct}},
+ {{:atom, :baz}, {:map, []}},
+ {{:atom, :foo}, :integer},
+ {{:atom, :bar}, {:atom, :atom}}
+ ]}}
+ end
- test "binary" do
+ describe "binary" do
+ test "literal" do
assert quoted_expr(<<"foo"::binary>>) == {:ok, :binary}
assert quoted_expr(<<123::integer>>) == {:ok, :binary}
+ assert quoted_expr(<<123::utf8>>) == {:ok, :binary}
+ assert quoted_expr(<<"foo"::utf8>>) == {:ok, :binary}
+ end
+
+ test "variable" do
assert quoted_expr([foo], <<foo::little>>) == {:ok, :binary}
assert quoted_expr([foo], <<foo::integer>>) == {:ok, :binary}
assert quoted_expr([foo], <<foo::integer()>>) == {:ok, :binary}
assert quoted_expr([foo], <<foo::integer-little>>) == {:ok, :binary}
assert quoted_expr([foo], <<foo::little-integer>>) == {:ok, :binary}
- assert quoted_expr(<<123::utf8>>) == {:ok, :binary}
- assert quoted_expr(<<"foo"::utf8>>) == {:ok, :binary}
+ end
+ test "infer" do
assert quoted_expr(
(
foo = 0.0
@@ -158,50 +166,65 @@ defmodule Module.Types.ExprTest do
assert {:error, {{:unable_unify, :binary, :integer, _, _}, _}} =
quoted_expr([foo], <<foo::binary-0, foo::integer>>)
end
+ end
- test "variables" do
- assert quoted_expr([foo], foo) == {:ok, {:var, 0}}
- assert quoted_expr([foo], {foo}) == {:ok, {:tuple, [{:var, 0}]}}
- assert quoted_expr([foo, bar], {foo, bar}) == {:ok, {:tuple, [{:var, 0}, {:var, 1}]}}
- end
+ test "variables" do
+ assert quoted_expr([foo], foo) == {:ok, {:var, 0}}
+ assert quoted_expr([foo], {foo}) == {:ok, {:tuple, [{:var, 0}]}}
+ assert quoted_expr([foo, bar], {foo, bar}) == {:ok, {:tuple, [{:var, 0}, {:var, 1}]}}
+ end
- test "pattern match" do
- assert {:error, _} = quoted_expr(:foo = 1)
- assert {:error, _} = quoted_expr(1 = :foo)
+ test "pattern match" do
+ assert {:error, _} = quoted_expr(:foo = 1)
+ assert {:error, _} = quoted_expr(1 = :foo)
- assert quoted_expr(:foo = :foo) == {:ok, {:atom, :foo}}
- assert quoted_expr(1 = 1) == {:ok, :integer}
- end
+ assert quoted_expr(:foo = :foo) == {:ok, {:atom, :foo}}
+ assert quoted_expr(1 = 1) == {:ok, :integer}
+ end
- test "block" do
- assert quoted_expr(
+ test "block" do
+ assert quoted_expr(
+ (
+ a = 1
+ a
+ )
+ ) == {:ok, :integer}
+
+ assert quoted_expr(
+ (
+ a = :foo
+ a
+ )
+ ) == {:ok, {:atom, :foo}}
+
+ assert {:error, _} =
+ quoted_expr(
(
a = 1
- a
+ :foo = a
)
- ) == {:ok, :integer}
+ )
+ end
+ describe "case" do
+ test "infer pattern" do
assert quoted_expr(
- (
- a = :foo
- a
- )
- ) == {:ok, {:atom, :foo}}
+ [a],
+ case a do
+ :foo = b -> :foo = b
+ end
+ ) == {:ok, :dynamic}
assert {:error, _} =
quoted_expr(
- (
- a = 1
- :foo = a
- )
+ [a],
+ case a do
+ :foo = b -> :bar = b
+ end
)
end
- test "case" do
- assert {:error, _} = quoted_expr([a], case(a, do: (:foo = b -> :bar = b)))
-
- assert quoted_expr([a], case(a, do: (:foo = b -> :foo = b))) == {:ok, :dynamic}
-
+ test "do not leak pattern/guard inference between clauses" do
assert quoted_expr(
[a],
case a do
@@ -219,28 +242,15 @@ defmodule Module.Types.ExprTest do
) == {:ok, :dynamic}
assert quoted_expr(
- [a, b],
- case a do
- :foo when is_binary(b) -> b
- end
- ) == {:ok, :dynamic}
-
- assert quoted_expr(
- [a, b],
- case a do
- :foo when is_binary(b) -> b <> ""
- :foo when is_list(b) -> b
- end
- ) == {:ok, :dynamic}
-
- assert quoted_expr(
[a],
case a do
:foo = b -> :foo = b
:bar = b -> :bar = b
end
) == {:ok, :dynamic}
+ end
+ test "do not leak body inference between clauses" do
assert quoted_expr(
[a],
case a do
@@ -261,35 +271,64 @@ defmodule Module.Types.ExprTest do
:bar -> :bar = b
end
) == {:ok, :dynamic}
- end
-
- test "fn" do
- assert quoted_expr(fn :foo = b -> :foo = b end) == {:ok, :dynamic}
- assert {:error, _} = quoted_expr(fn :foo = b -> :bar = b end)
- end
-
- test "with" do
assert quoted_expr(
[a, b],
- with(
- :foo <- a,
- :bar <- b,
- c = :baz,
- do: c
- )
+ case a do
+ :foo when is_binary(b) -> b <> ""
+ :foo when is_list(b) -> b
+ end
) == {:ok, :dynamic}
end
+ end
- test "for" do
- assert quoted_expr(
- [list],
+ test "fn" do
+ assert quoted_expr(fn :foo = b -> :foo = b end) == {:ok, :dynamic}
+
+ assert {:error, _} = quoted_expr(fn :foo = b -> :bar = b end)
+ end
+
+ test "with" do
+ assert quoted_expr(
+ [a, b],
+ with(
+ :foo <- a,
+ :bar <- b,
+ c = :baz,
+ do: c
+ )
+ ) == {:ok, :dynamic}
+
+ assert quoted_expr(
+ [a],
+ (
+ with(a = :baz, do: a)
+ a
+ )
+ ) == {:ok, {:var, 0}}
+ end
+
+ test "for" do
+ assert quoted_expr(
+ [list],
+ for(
+ foo <- list,
+ is_integer(foo),
+ do: foo == 123
+ )
+ ) == {:ok, :dynamic}
+
+ assert quoted_expr(
+ [list, bar],
+ (
for(
foo <- list,
- is_integer(foo),
+ is_integer(bar),
do: foo == 123
)
- ) == {:ok, :dynamic}
- end
+
+ bar
+ )
+ ) == {:ok, {:var, 0}}
end
end