Existing issue
Elixir and Erlang/OTP versions
1.21.0-dev@87af1e34e
Operating system
any
Current behavior
Map domain entries are documented to be implicitly optional - a domain value none() means that the map contains no entries whose keys belong to that domain. It does not make the entire map type empty yet the current implementation breaks this assumption and loses precision of the static part:
Repro:
import Module.Types.Descr
static =
closed_map([
{[:integer], none()},
{:b, {integer(), false}}
])
gradual =
closed_map([
{[:integer], dynamic()},
{:b, {integer(), false}}
])
IO.puts("actual: #{to_quoted_string(lower_bound(gradual))}")
IO.puts("expected: #{to_quoted_string(static)}")
IO.inspect(lower_bound(gradual) == static, label: "equal?")
result:
actual: none()
expected: %{integer() => not_set(), b: integer()}
equal?: false
The same static part loss through contravariant argument handling
actual_fun = upper_bound(fun([gradual], atom()))
expected_fun = fun([static], atom())
IO.puts("actual fun: #{to_quoted_string(actual_fun)}")
IO.puts("expected fun: #{to_quoted_string(expected_fun)}")
IO.inspect(actual_fun == expected_fun, label: "fun equal?")
result:
actual fun: (none() -> atom())
expected fun: (%{integer() => not_set(), b: integer()} -> atom())
fun equal?: false
Another example
static =
open_map([
{[:tuple], none()},
{:b, {integer(), true}}
])
gradual =
open_map([
{[:tuple], none()},
{:b, {opt_union(integer(), dynamic(float())), true}}
])
IO.inspect(lower_bound(gradual) == static)
# Current: false
# Expected: true
Expected behavior
No precision loss
Existing issue
Elixir and Erlang/OTP versions
1.21.0-dev@87af1e34e
Operating system
any
Current behavior
Map domain entries are documented to be implicitly optional - a domain value
none()means that the map contains no entries whose keys belong to that domain. It does not make the entire map type empty yet the current implementation breaks this assumption and loses precision of the static part:Repro:
result:
The same static part loss through contravariant argument handling
result:
Another example
Expected behavior
No precision loss