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)

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.

1 participant