Existing issue
Elixir and Erlang/OTP versions
> elixir --version
Erlang/OTP 29 [erts-17.0.5] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]
Elixir 1.20.3 (compiled with Erlang/OTP 29)
Operating system
macos
Current behavior
If pattern matching on a nested map, and nested calls to :erlang.map_get/2 are used to fetch nested values, the type checker is giving false warnings for code that should be valid.
Using same code outside of a guard seems to be OK.
Following code reproduces:
defmodule MapGetExampleTest do
use ExUnit.Case
test "single works as positive guard" do
some_record = {:ok, %{"foo" => 123}}
result =
case some_record do
{:ok, data} when :erlang.map_get("foo", data) == 123 -> :ok
_ -> :error
end
assert result == :ok
end
test "single works as negative guard" do
some_record = {:ok, %{"foo" => 123}}
result =
case some_record do
# fine. no type warning
{:ok, data} when :erlang.map_get("z", data) == 123 -> :ok
_ -> :error
end
assert result == :error
end
test "non-guard positive gets work ok" do
some_record = {:ok, %{"foo" => %{"bar" => 123}}}
{:ok, data} = some_record
# fine. no type warning
assert :erlang.map_get("bar", :erlang.map_get("foo", data)) == 123
end
test "non-guard negative gets raise" do
some_record = {:ok, %{"foo" => %{"bar" => 123}}}
{:ok, data} = some_record
# fine. no type warning
assert_raise KeyError, fn -> :erlang.map_get("zz", :erlang.map_get("z", data)) == 123 end
end
test "nesting works as positive guard" do
some_record = {:ok, %{"foo" => %{"bar" => 123}}}
result =
case some_record do
# invalid, false-positive type warning
{:ok, data} when :erlang.map_get("bar", :erlang.map_get("foo", data)) == 123 -> :ok
_ -> :error
end
assert result == :ok
end
test "nesting works as negative guard" do
some_record = {:ok, %{"foo" => %{"bar" => 123}}}
result =
case some_record do
# invalid, false-positive type warning
{:ok, data} when :erlang.map_get("zz", :erlang.map_get("z", data)) == 123 -> :ok
_ -> :error
end
assert result == :error
end
end
> mix test
Running ExUnit with seed: 869956, max_cases: 20
warning: incompatible types given to :erlang.map_get/2:
:erlang.map_get("bar", :erlang.map_get("foo", data))
given types:
binary(), term()
but expected one of:
term(), map()
where "data" was given the type:
# type: map()
# from: test/map_get_example_test.exs:49:57
:erlang.map_get("foo", data)
type warning found at:
│
49 │ {:ok, data} when :erlang.map_get("bar", :erlang.map_get("foo", data)) == 123 -> :ok
│ ~
│
└─ test/map_get_example_test.exs:49:34: MapGetExampleTest."test nesting works as positive guard"/1
warning: incompatible types given to :erlang.map_get/2:
:erlang.map_get("zz", :erlang.map_get("z", data))
given types:
binary(), term()
but expected one of:
term(), map()
where "data" was given the type:
# type: map()
# from: test/map_get_example_test.exs:62:56
:erlang.map_get("z", data)
type warning found at:
│
62 │ {:ok, data} when :erlang.map_get("zz", :erlang.map_get("z", data)) == 123 -> :ok
│ ~
│
└─ test/map_get_example_test.exs:62:34: MapGetExampleTest."test nesting works as negative guard"/1
......
Finished in 0.01 seconds (0.00s async, 0.01s sync)
Result: 6 passed
Could see a few map related open issues, but wasn't sure if this is part of the same overall issue.
Expected behavior
Test code above compiles and runs without type checker warnings.
Existing issue
Elixir and Erlang/OTP versions
Operating system
macos
Current behavior
If pattern matching on a nested map, and nested calls to
:erlang.map_get/2are used to fetch nested values, the type checker is giving false warnings for code that should be valid.Using same code outside of a guard seems to be OK.
Following code reproduces:
Could see a few map related open issues, but wasn't sure if this is part of the same overall issue.
Expected behavior
Test code above compiles and runs without type checker warnings.