diff --git a/lib/elixir/lib/module/types/of.ex b/lib/elixir/lib/module/types/of.ex index 98daa6a6544..270d29c2e93 100644 --- a/lib/elixir/lib/module/types/of.ex +++ b/lib/elixir/lib/module/types/of.ex @@ -132,7 +132,7 @@ defmodule Module.Types.Of do {Float, float()}, {Function, fun()}, {Integer, integer()}, - {List, list(term())}, + {List, union(empty_list(), non_empty_list(term(), term()))}, {Map, open_map(__struct__: if_set(negation(atom())))}, {Port, port()}, {PID, pid()}, diff --git a/lib/elixir/test/elixir/module/types/integration_test.exs b/lib/elixir/test/elixir/module/types/integration_test.exs index 8e67051f251..fee8509e39c 100644 --- a/lib/elixir/test/elixir/module/types/integration_test.exs +++ b/lib/elixir/test/elixir/module/types/integration_test.exs @@ -206,7 +206,10 @@ defmodule Module.Types.IntegrationTest do assert itself_arg.(Itself.Float) == dynamic(float()) assert itself_arg.(Itself.Function) == dynamic(fun()) assert itself_arg.(Itself.Integer) == dynamic(integer()) - assert itself_arg.(Itself.List) == dynamic(list(term())) + + assert itself_arg.(Itself.List) == + dynamic(union(empty_list(), non_empty_list(term(), term()))) + assert itself_arg.(Itself.Map) == dynamic(open_map(__struct__: if_set(negation(atom())))) assert itself_arg.(Itself.Port) == dynamic(port()) assert itself_arg.(Itself.PID) == dynamic(pid()) @@ -483,7 +486,7 @@ defmodule Module.Types.IntegrationTest do dynamic( %Date{} or %DateTime{} or %NaiveDateTime{} or %Time{} or %URI{} or %Version{} or %Version.Requirement{} - ) or atom() or binary() or float() or integer() or list(term()) + ) or atom() or binary() or empty_list() or float() or integer() or non_empty_list(term(), term()) where "data" was given the type: @@ -507,7 +510,7 @@ defmodule Module.Types.IntegrationTest do dynamic( %Date{} or %DateTime{} or %NaiveDateTime{} or %Time{} or %URI{} or %Version{} or %Version.Requirement{} - ) or atom() or binary() or float() or integer() or list(term()) + ) or atom() or binary() or empty_list() or float() or integer() or non_empty_list(term(), term()) where "data" was given the type: @@ -520,6 +523,18 @@ defmodule Module.Types.IntegrationTest do assert_warnings(files, warnings, consolidate_protocols: true) end + test "String.Chars protocol dispatch on improper lists" do + files = %{ + "a.ex" => """ + defmodule FooBar do + def example1, do: to_string([?a, ?b | "!"]) + end + """ + } + + assert_no_warnings(files, consolidate_protocols: true) + end + test "Enumerable protocol dispatch" do files = %{ "a.ex" => """ @@ -546,7 +561,7 @@ defmodule Module.Types.IntegrationTest do dynamic( %Date.Range{} or %File.Stream{} or %GenEvent.Stream{} or %HashDict{} or %HashSet{} or %IO.Stream{} or %MapSet{} or %Range{} or %Stream{} - ) or fun() or list(term()) or non_struct_map() + ) or empty_list() or fun() or non_empty_list(term(), term()) or non_struct_map() where "date" was given the type: @@ -575,7 +590,7 @@ defmodule Module.Types.IntegrationTest do but expected a type that implements the Collectable protocol, it must be one of: dynamic(%File.Stream{} or %HashDict{} or %HashSet{} or %IO.Stream{} or %MapSet{}) or binary() or - list(term()) or non_struct_map() + empty_list() or non_empty_list(term(), term()) or non_struct_map() hint: the :into option in for-comprehensions use the Collectable protocol to build its result. Either pass a valid data type or implement the protocol accordingly """ @@ -1378,8 +1393,8 @@ defmodule Module.Types.IntegrationTest do end) end - defp assert_no_warnings(files) do - assert capture_compile_warnings(files, []) == "" + defp assert_no_warnings(files, opts \\ []) do + assert capture_compile_warnings(files, opts) == "" end defp capture_compile_warnings(files, opts) do