diff --git a/lib/elixir/lib/module/types/apply.ex b/lib/elixir/lib/module/types/apply.ex index 4d88bb617e..0fad6ca98a 100644 --- a/lib/elixir/lib/module/types/apply.ex +++ b/lib/elixir/lib/module/types/apply.ex @@ -1169,6 +1169,19 @@ defmodule Module.Types.Apply do end end + defp remote_apply(:erlang, :--, _info, [left, right], stack) do + # TODO: remove once we add parametric types, this will just be: + # list(a), list(term()) -> list(a) + case {list_of(left), list_of(right)} do + {{_, list_of}, {_, _}} -> + result = if list_of, do: list(list_of), else: empty_list() + {:ok, return(result, [left, right], stack)} + + _ -> + {:error, badremote(:erlang, :--, [left, right])} + end + end + defp remote_apply(Kernel, :elem, info, [tuple, _index] = args_types, stack) do remote_apply_tuple_element(info, args_types, tuple, stack) end diff --git a/lib/elixir/test/elixir/module/types/expr_test.exs b/lib/elixir/test/elixir/module/types/expr_test.exs index 3ac67bc28f..aec4f79fab 100644 --- a/lib/elixir/test/elixir/module/types/expr_test.exs +++ b/lib/elixir/test/elixir/module/types/expr_test.exs @@ -173,6 +173,15 @@ defmodule Module.Types.ExprTest do non_empty_list(term()), term() """ end + + test "--" do + assert typecheck!([x], [1, 2, 3] -- x) == list(integer()) + assert typecheck!([1] -- [1]) == list(integer()) + assert typecheck!([x], [] -- x) == empty_list() + + assert typeerror!([x], [1, 2, 3] -- String.to_integer(x)) |> strip_ansi() =~ + "incompatible types given to Kernel.--/2" + end end describe "funs" do