Skip to content

types: compute self-referential supertypes lazily - #62847

Open
Keno wants to merge 1 commit into
JuliaLang:masterfrom
KenoAIStaging:kf/lazy-super
Open

types: compute self-referential supertypes lazily#62847
Keno wants to merge 1 commit into
JuliaLang:masterfrom
KenoAIStaging:kf/lazy-super

Conversation

@Keno

@Keno Keno commented Aug 21, 2026

Copy link
Copy Markdown
Member

🤖 A struct definition whose supertype declaration recursively applies the type being defined at structurally increasing parameters, such as

struct S{T} <: A{S{Tuple{T}}} end

has an infinite supertype graph: eagerly instantiating each level's supertype creates the next level. Today the definition-time partial fixup truncates that recursion by silently caching wrong supertypes — the same interned type can permanently report Any or its true supertype depending on which expression happened to construct it first, and supertype disagrees with <:.

With this PR, an instantiation created while another instantiation of the same (supertype-self-referential) typename is in flight now defers its supertype and completes it lazily, one level per demand (jl_datatype_compute_super). Every level of the graph is correct and independent of instantiation order. Same-parameter self-references still tie their knot through the instantiation stack, so ordinary recursive types are unaffected, and field types stay eager — a concrete type must publish with its layout, so the field-type analogue of this recursion (the S1 case of #61347) is left for a follow-up.

Addresses the supertype half of #61347.

Assisted-by: Claude Code (Fable 5)

Comment thread src/ast.c
{
jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v);
for (; t->super != t; t = t->super)
while (t != NULL && t != jl_any_type) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This doesn't care about parameters, so this seems like it could go via typename (not that it really matters)

@Keno

Keno commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

Probably should overload getproperty to make this fill in the cache on access.

A struct definition whose supertype declaration recursively applies the
type being defined at structurally increasing parameters, such as

    struct S{T} <: A{S{Tuple{T}}} end

has an infinite supertype graph: eagerly instantiating each level's
supertype creates the next level. Today the definition-time partial fixup
truncates that recursion by silently caching wrong supertypes — the same
interned type can permanently report `Any` or its true supertype
depending on which expression happened to construct it first, and
`supertype` disagrees with `<:`.

An instantiation created while another instantiation of the same
(supertype-self-referential) typename is in flight now defers its
supertype and completes it lazily, one level per demand
(`jl_datatype_compute_super`). Every level of the graph is correct and
independent of instantiation order. Same-parameter self-references still
tie their knot through the instantiation stack, so ordinary recursive
types are unaffected, and field types stay eager — a concrete type must
publish with its layout, so the field-type analogue of this recursion
(the `S1` case of JuliaLang#61347) is left for a follow-up.

The object-model metadata tells the truth about the deferred slot:
`DataType.super` is declared maybe-undefined, non-const, and atomic, so a
raw `getfield`/`isdefined` on an unfilled slot behaves identically in
compiled and interpreted code (undefined field), never yielding a stray
NULL. `supertype` forces the computation before the field read, keeping
`getfield`'s inference precision, and constant folding of a defined
`super` remains sound because the field is write-once (mirroring the
existing `types` handling). C supertype-chain walks that can encounter a
deferred instantiation force it in place; display-path helpers that must
not reach a safepoint stay null-tolerant.

Addresses the supertype half of JuliaLang#61347.

Assisted-by: Claude Code (Fable 5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant