Existing issue
Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.4.0.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]
Interactive Elixir (1.21.0-dev)
Operating system
any
Current behavior
Map literal expressions with variable keys produce too small types that do not contain observed runtime values and result in false positive warnings.
Issue 1: Map literal whose key is :a or integer() records :a as required
Repro:
defmodule P22 do
def fin_dom(c) do
k = if c, do: :a, else: 5
m = %{k => 1}
case m do
%{a: _} -> :has_a
_ -> :no
end
end
end
Result:
warning: the following clause cannot match because the previous clauses already matched all possible values:
_ ->
it attempts to match on the result of:
m
which has the already matched type:
dynamic(%{integer() => integer(), a: integer()})
└─ iex:8: P22.fin_dom/1
Likely reason: closed_map/5 adds finite atoms as required keys even when domain_keys != []
Issue 2:
Map literals with a negated atom variable key mark the negated atom as not_set()
Repro:
defmodule P21 do
def neg_key(s1, s2) do
k1 = String.to_atom(s1)
k2 = case String.to_atom(s2) do :foo -> :not_foo; o -> o end
m = %{k1 => :baz, k2 => :baz2}
case m do
%{foo: _} -> :has_foo
_ -> :no
end
end
def neg2(s1, s2) do
k1 = case String.to_atom(s1) do :a -> :na; o -> o end
k2 = case String.to_atom(s2) do :b -> :nb; o -> o end
m = %{k1 => 1, k2 => 2}
case m do
%{b: _} -> :has_b
_ -> :no
end
end
end
Result:
warning: the following clause will never match:
%{foo: _} ->
because it attempts to match on the result of:
m
which has type:
dynamic(%{atom() => :baz or :baz2, foo: not_set()})
└─ iex:9: P21.neg_key/2
warning: the following clause will never match:
%{b: _} ->
because it attempts to match on the result of:
m
which has type:
dynamic(%{atom() => integer(), a: if_set(integer()), b: not_set()})
└─ iex:19: P21.neg2/2
IO.inspect({P21.neg_key("foo","bar"), P21.neg2("b","c")}) # {:has_foo, :has_b}
Note neg2 also shows the asymmetry: a is if_set (correct) but b is not_set (wrong)
Likely reason: closed_map/5 and union_negated/4 make every negated atom not_set() without consulting the :atom domain
Expected behavior
Proper types constructed, no warnings
Existing issue
Elixir and Erlang/OTP versions
Erlang/OTP 28 [erts-16.4.0.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]
Interactive Elixir (1.21.0-dev)
Operating system
any
Current behavior
Map literal expressions with variable keys produce too small types that do not contain observed runtime values and result in false positive warnings.
Issue 1: Map literal whose key is
:a or integer()records :a as requiredRepro:
Result:
Likely reason:
closed_map/5adds finite atoms as required keys even when domain_keys != []Issue 2:
Map literals with a negated atom variable key mark the negated atom as
not_set()Repro:
Result:
Note
neg2also shows the asymmetry:aisif_set(correct) butbisnot_set(wrong)Likely reason:
closed_map/5andunion_negated/4make every negated atomnot_set()without consulting the:atomdomainExpected behavior
Proper types constructed, no warnings