diff --git a/lib/elixir/lib/module/types/apply.ex b/lib/elixir/lib/module/types/apply.ex index 9dffd1e28f9..c6a18b93cf3 100644 --- a/lib/elixir/lib/module/types/apply.ex +++ b/lib/elixir/lib/module/types/apply.ex @@ -254,7 +254,7 @@ defmodule Module.Types.Apply do {Map, :fetch, [{[open_map(), term()], tuple([atom([:ok]), term()]) |> opt_union(atom([:error]))}]}, {Map, :fetch!, [{[open_map(), term()], term()}]}, - {Map, :from_struct, [{[open_map()], open_map(__struct__: not_set())}]}, + {Map, :from_struct, [{[open_map(__struct__: atom())], open_map(__struct__: not_set())}]}, {Map, :get, [{[open_map(), term()], term()}]}, {Map, :get, [{[open_map(), term(), term()], term()}]}, {Map, :get_lazy, [{[open_map(), term(), fun(0)], term()}]}, @@ -1129,11 +1129,19 @@ defmodule Module.Types.Apply do @struct_key atom([:__struct__]) @nil_atom atom([nil]) - defp remote_apply(Map, :from_struct, _info, [map] = args_types, stack) do - case map_update(map, @struct_key, not_set(), false, true) do - {_value, descr, _errors} -> {:ok, return(descr, args_types, stack)} - :badmap -> {:error, badremote(Map, :from_struct, args_types)} - {:error, _errors} -> {:ok, map} + defp remote_apply(Map, :from_struct, info, [map] = args_types, stack) do + case remote_apply(info, args_types, stack) do + {:ok, _type} -> + case map_update(map, @struct_key, not_set(), false, true) do + {_value, descr, _errors} -> + {:ok, return(descr, args_types, stack)} + + _ -> + {:error, badremote(Map, :from_struct, args_types)} + end + + other -> + other end end diff --git a/lib/elixir/test/elixir/module/types/map_test.exs b/lib/elixir/test/elixir/module/types/map_test.exs index e0cc57c24c9..24b0df12d74 100644 --- a/lib/elixir/test/elixir/module/types/map_test.exs +++ b/lib/elixir/test/elixir/module/types/map_test.exs @@ -330,11 +330,8 @@ defmodule Module.Types.MapTest do describe "Map.from_struct/1" do test "checking" do - assert typecheck!(Map.from_struct(%{})) == - empty_map() - - assert typecheck!(Map.from_struct(%{key: 123})) == - closed_map(key: integer()) + assert typecheck!(Map.from_struct(%{__struct__: URI, port: 433})) == + closed_map(port: integer()) assert typecheck!(Map.from_struct(%URI{})) == closed_map( @@ -359,12 +356,15 @@ defmodule Module.Types.MapTest do _ = Map.from_struct(x) x ) - ) == dynamic(open_map()) + ) == dynamic(open_map(__struct__: atom())) end test "errors" do assert typeerror!([x = []], Map.from_struct(x)) =~ "incompatible types given to Map.from_struct/1" + + assert typeerror!(Map.from_struct(%{})) =~ + "incompatible types given to Map.from_struct/1" end end