Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions lib/elixir/lib/module/types/apply.ex
Original file line number Diff line number Diff line change
Expand Up @@ -590,17 +590,29 @@ defmodule Module.Types.Apply do

{expected, precise?} =
case fun do
:length when :erlang.xor(polarity, literal > 0) ->
{@empty_list, literal == 0}
:length when polarity and literal == 0 ->
{@empty_list, true}

:length when not polarity and literal == 0 ->
{@non_empty_list, true}

:length when polarity ->
{@non_empty_list, false}

:length ->
{@non_empty_list, literal == 0}
{@list, false}

:map_size when polarity and literal == 0 ->
{@empty_map, true}

:map_size when not polarity and literal == 0 ->
{@non_empty_map, true}

:map_size when :erlang.xor(polarity, literal > 0) ->
{@empty_map, literal == 0}
:map_size when polarity ->
{@non_empty_map, false}

:map_size ->
{@non_empty_map, literal == 0}
{open_map(), false}

:tuple_size when polarity ->
{tuple(List.duplicate(term(), literal)), true}
Expand Down
35 changes: 35 additions & 0 deletions lib/elixir/test/elixir/module/types/pattern_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,17 @@ defmodule Module.Types.PatternTest do

assert typecheck!([x], 0 != length(x), x) == dynamic(non_empty_list(term()))
assert typecheck!([x], not (0 != length(x)), x) == dynamic(empty_list())

assert typecheck!([x], length(x) == 1, x) == dynamic(non_empty_list(term()))
assert typecheck!([x], not (length(x) != 1), x) == dynamic(non_empty_list(term()))
assert typecheck!([x], 1 == length(x), x) == dynamic(non_empty_list(term()))

assert typecheck!([x], length(x) != 1, x) == dynamic(list(term()))
assert typecheck!([x], not (length(x) == 1), x) == dynamic(list(term()))
assert typecheck!([x], 1 != length(x), x) == dynamic(list(term()))

assert typecheck!([x], is_list(x) and length(x) != 1 and x != [], hd(x)) ==
dynamic(term())
end

test "length ordered" do
Expand Down Expand Up @@ -1206,6 +1217,20 @@ defmodule Module.Types.PatternTest do
assert typecheck!([x], 0 != map_size(x), x) == dynamic(@non_empty_map)
assert typecheck!([x], not (0 == map_size(x)), x) == dynamic(@non_empty_map)
assert typecheck!([x], not (0 != map_size(x)), x) == dynamic(empty_map())

assert typecheck!([x], map_size(x) == 1, x) == dynamic(@non_empty_map)
assert typecheck!([x], not (map_size(x) != 1), x) == dynamic(@non_empty_map)
assert typecheck!([x], 1 == map_size(x), x) == dynamic(@non_empty_map)

assert typecheck!([x], map_size(x) != 1, x) == dynamic(open_map())
assert typecheck!([x], not (map_size(x) == 1), x) == dynamic(open_map())
assert typecheck!([x], 1 != map_size(x), x) == dynamic(open_map())

assert typecheck!(
[x],
is_map(x) and map_size(x) != 1 and is_map_key(x, :a) and is_map_key(x, :b),
x
) == dynamic(open_map(a: term(), b: term()))
end

test "map_size ordered" do
Expand Down Expand Up @@ -1270,6 +1295,16 @@ defmodule Module.Types.PatternTest do
assert typecheck!([x], 2 != tuple_size(x), x) == dynamic(@non_binary_tuple)
assert typecheck!([x], not (2 == tuple_size(x)), x) == dynamic(@non_binary_tuple)
assert typecheck!([x], not (2 != tuple_size(x)), x) == dynamic(tuple([term(), term()]))

assert typecheck!([x], tuple_size(x) != 1, x) ==
dynamic(difference(open_tuple([]), tuple([term()])))

assert typecheck!(
[x],
is_tuple(x) and tuple_size(x) != 1 and tuple_size(x) != 0,
x
)
|> equal?(dynamic(open_tuple([term(), term()])))
end

test "tuple_size ordered" do
Expand Down
Loading