diff --git a/lib/elixir/lib/module/types/descr.ex b/lib/elixir/lib/module/types/descr.ex index bf3975db24..b5de633e53 100644 --- a/lib/elixir/lib/module/types/descr.ex +++ b/lib/elixir/lib/module/types/descr.ex @@ -334,6 +334,7 @@ defmodule Module.Types.Descr do keep_optional: 1, remove_optional: 1, remove_optional_static: 1, optional_to_term: 1} defp keep_optional(descr) do case descr do + %{dynamic: %{optional: 1}, optional: 1} -> %{dynamic: %{optional: 1}, optional: 1} %{dynamic: %{optional: 1}} -> %{dynamic: %{optional: 1}} %{optional: 1} -> %{optional: 1} _ -> @none diff --git a/lib/elixir/test/elixir/module/types/descr_test.exs b/lib/elixir/test/elixir/module/types/descr_test.exs index e798d3a15d..8db5300ed0 100644 --- a/lib/elixir/test/elixir/module/types/descr_test.exs +++ b/lib/elixir/test/elixir/module/types/descr_test.exs @@ -104,6 +104,14 @@ defmodule Module.Types.DescrTest do refute equal?(union(term(), dynamic(if_set(integer()))), dynamic(union(term(), not_set()))) end + test "optional" do + # Test that union preserves optional properties + t = union(term(), dynamic(not_set())) + assert subtype?(term(), t) + assert subtype?(dynamic(), t) + assert subtype?(dynamic(integer()), t) + end + test "tuple" do assert equal?(union(tuple(), tuple()), tuple()) @@ -585,6 +593,14 @@ defmodule Module.Types.DescrTest do assert empty?(difference(dynamic(integer()), integer())) end + test "optional" do + # Test that difference preserves optional properties + x = if_set(dynamic(integer())) + term_map = union(integer(), difference(term(), integer())) + assert equal?(term_map, term()) + assert equal?(difference(x, term()), difference(x, term_map)) + end + test "tuple" do assert empty?(difference(open_tuple([atom()]), open_tuple([term()]))) refute empty?(difference(tuple(), empty_tuple())) @@ -985,12 +1001,6 @@ defmodule Module.Types.DescrTest do refute subtype?(if_set(term()), term()) assert subtype?(if_set(term()), if_set(term())) refute subtype?(if_set(term()), if_set(dynamic(term()))) - - # Test that union+dynamic optimizations preserves properties - t = union(term(), dynamic(not_set())) - assert subtype?(term(), t) - assert subtype?(dynamic(), t) - assert subtype?(dynamic(integer()), t) end test "list" do