Skip to content

Descr.tuple_fetch returns :badindex for valid access on difference types #15491

Description

@lukaszsamson

Existing issue

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

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

The following code shows the bug:

# create a set of all tupels of size >= 1
t = opt_difference(open_tuple([]), tuple([]))
%{
  tuple: {3186801813, {-113427502, :closed, []}, :bdd_bot, :bdd_bot,
   {61102469, :open, []}}
}

# which is equal to open tuple of size 1
equal?(t, open_tuple([term()]))
true

# the representation is different though
open_tuple([term()])
%{tuple: {18315736, :open, [:term]}}

# and fetch is not working correctly on the difference type

tuple_fetch(t, 0)
:badindex

tuple_fetch(open_tuple([term()]), 0)
{false, :term}

Likely reason:

value =
if tuple_pair_projection_keeps_full_fst?(negative, bdd) do
value
else
negs
|> tuple_split_negative(index, value, bdd)
|> Enum.reduce(none(), fn {value, _}, acc -> opt_union(value, acc) end)
end
{optional?, descr} = pop_optional_static(value)
{optional? or acc_optional?, opt_union(descr, acc_descr)}

shortcut value returned from tuple_pair_projection_keeps_full_fst? is taken unconditionally and carries optional?. Negations that remove small arity tuples can never cancel it

Expected behavior

tuple_fetch should work correctly on difference type

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions