Skip to content

Support recursive type descriptors#15530

Draft
gldubc wants to merge 1 commit into
elixir-lang:mainfrom
gldubc:recursive-types-pr
Draft

Support recursive type descriptors#15530
gldubc wants to merge 1 commit into
elixir-lang:mainfrom
gldubc:recursive-types-pr

Conversation

@gldubc

@gldubc gldubc commented Jun 26, 2026

Copy link
Copy Markdown
Member

Summary

  • add recursive descriptor nodes and unfolding support in descriptor operations
  • add recursive descriptor tests
  • keep recursive map-domain if_set lazy to avoid infinite unfolding during construction

Validation

  • make compile
  • make test_stdlib TEST_FILES="module/types/recursive_test.exs"
  • make test_stdlib TEST_FILES="module/types/descr_test.exs"

Some extra information

This PR adds a new main data-structure: a type node, which essentially encodes a way to unfold a recursive type and lives next to the descr structure. For instance, int_list = {integer(), int_list} or nil will be encoded using a node that can produce the Descr representing {integer(), int_list} or nil.

Emptiness detection is done using a simple algorith, with no memoization, that keeps track of which bdds have been encountered before. A memoizing algorith is possible, and could be implemented too if performances becomes an issue, notably when instantiating polymorphic types.

Limitation

Currently, recursive types don't support opt_*. An easy way to loop: build

X = nil | {integer(), X}

and try to compute opt_intersection(<node X>, <node X>).

<node X> unfolds to the descr

 nil | {integer(), <node X>}

So when opt_intersection/2 intersects tuple fields individually, it eventually asks:

opt_intersection(<node X>, <node X>)

which unfolds to the same thing again.

Assisted-by: Codex:GPT-5 (writing tests)

defp map_put_domain(domain, [], _initial, _value), do: domain

# Map domains store if_set(value). For recursive nodes, keep that application lazy
# so constructing the descriptor does not unfold the same map domain forever.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants