Skip to content

Commit 37bbba9

Browse files
committed
Document map_get behaviour, do not split term types, closes #15209
1 parent 2a7a37f commit 37bbba9

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

lib/elixir/lib/module/types/apply.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2090,7 +2090,8 @@ defmodule Module.Types.Apply do
20902090
defp args_to_quoted_string(args_types, domain, converter) do
20912091
docs =
20922092
Enum.zip_with(args_types, domain, fn actual, expected ->
2093-
if compatible?(actual, expected) or not has_simple_difference?(actual, expected) do
2093+
if compatible?(actual, expected) or not has_simple_difference?(actual, expected) or
2094+
term_type?(actual) do
20942095
actual |> to_quoted() |> Code.Formatter.to_algebra()
20952096
else
20962097
common = intersection(actual, expected)

lib/elixir/test/elixir/module/types/pattern_test.exs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,42 @@ defmodule Module.Types.PatternTest do
726726
"""
727727
end
728728

729+
test "map_get" do
730+
# Below we have a precision warning because the map key is term.
731+
# We could solve this in the same we say solved hd/tl in guards,
732+
# but we explicitly chose not to (for now) for the following reasons:
733+
#
734+
# 1. We don't expose `:erlang.map_get` in Elixir, only `map.foo`,
735+
# which is an atom key and will be precise
736+
#
737+
# 2. The typing violation below will also happen once we add type
738+
# signatures and `%{x => v}` returns anything but a `boolean()`
739+
# (but it will work if you declare the value type only as boolean())
740+
#
741+
# 3. It also works if you explicitly match on `== true`, which
742+
# effectively forces the return given to `not` to be boolean
743+
#
744+
# Furthermore, we currently use it to test we don't split term types
745+
# in error messages (as we don't have type signatures).
746+
assert typeerror!([key, map], not :erlang.map_get(key, map), map) =~ """
747+
incompatible types given to Kernel.not/1:
748+
749+
not :erlang.map_get(key, map)
750+
751+
given types:
752+
753+
term()
754+
755+
but expected one of:
756+
757+
#1
758+
true
759+
760+
#2
761+
false
762+
"""
763+
end
764+
729765
test "when checks" do
730766
assert typecheck!([x], is_binary(x) when is_atom(x), x) == dynamic(union(binary(), atom()))
731767

0 commit comments

Comments
 (0)