Skip to content

map_update/map_put/map_get verdicts depend on type representation #15688

Description

@lukaszsamson

Existing issue

  • I have searched existing issues and could not find a duplicate.

Elixir and Erlang/OTP versions

main@745ee1d53

Operating system

any

Current behavior

Repro 1:
closed map with required key unioned with empty type

empty?(closed_map([{:a, {none(), false}}])) # true, correct

a = opt_union(closed_map([{:b, {term(), false}}]), closed_map([{:a, {none(), false}}]))
a1 = closed_map(b: {term(), false})

equal?(a, a1) # true, correct

map_update(a1, atom([:b]), atom([:x]), false)  |> elem(1) |> to_quoted_string # "%{b: :x}"
map_update(a, atom([:b]), atom([:x]), false) # {:error, [badkey: :b]}, wrong

Repro 2:
an empty open line fakes support for a key domain no member can carry

b = opt_union(closed_map([]), open_map([{:a, {none(), false}}]))
equal?(b, closed_map([])) # true, correct

map_update(b, integer(), atom([:x]), false) |> elem(1) |> to_quoted_string # "%{..., a: none()} or empty_map()", wrong, should error
map_update(empty_map(), integer(), atom([:x]), false) # {:error, [baddomain: %{bitmap: 8}]}, correct

Repro 3:

inconsistent errors returned

e = closed_map(a: {none(), false})
empty?(e) # true
equal?(e, none()) # true

# consistent
map_put(e, atom([:a]), atom([:x])) # :badmap
map_put(none(), atom([:a]), atom([:x])) # :badmap

# inconsistent
map_get(e, atom([:a])) # :error
map_get(none(), atom([:a])) # :badmap

# inconsistent
map_update(e, atom([:a]), atom([:x]), false) # {:error, [badkey: :a]}
map_update(none(), atom([:a]), atom([:x]), false) # :badmap

Repro 4:
inconsistent oveapproximation in gradual path

e = open_map([{:a, {none(), false}}])
equal?(e, none()) # true

# consistent
map_put(e, atom(), integer()) # :badmap
map_put(none(), atom(), integer()) # :badmap

# inconsistent
map_put(e, atom(), dynamic()) # {:ok, %{dynamic: %{map: {98204482, :open, [a: {:term, false}]}}}}
map_put(none(), atom(), dynamic()) # :badmap

Related to #15592 and #15594
Note 745ee1d did not resolve any of those issues

Expected behavior

Operation result should be representation agnostic

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions