# Why are self-referential struct parameters impossible?

**URL:** <https://discourse.julialang.org/t/why-are-self-referential-struct-parameters-impossible/110982>\
**Category:** Internals & Design\
**Tags:** type, parametric-types, recursion, parameters\
**Created:** [February 29, 2024, 11:18pm UTC](https://discourse.julialang.org/t/why-are-self-referential-struct-parameters-impossible/110982 "2024-02-29T23:18:12Z")\
**Posts on this page:** 1\
**Showing post:** 19

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 2, 2024, 4:18am UTC](https://discourse.julialang.org/t/why-are-self-referential-struct-parameters-impossible/110982/19 "2024-03-02T04:18:33Z")

</div>

I think the wider reason for global functions being recursive is that they don’t need to know anything about their global variables until they are compiled. The backedges help in the case that the global variable wasn’t defined by the time it’s compiled, which needs to be undone and retried after defining the variable. Locally scoped functions are implemented as callable instances instantiated at definition, so while they can be recursive, they can’t know [the type of the function in the recursive call](https://discourse.julialang.org/t/function-definition-inside-let-block-impacting-performance/110007), which really hurts performance. There too are ideas about how to rectify that.

Also I think it’s worth reiterating that this is about parameters constraints specifically. The earlier linked mutually recursive structs issue doesn’t address that directly AFAIK, but the forward declarations idea there could also help the undefined variable error here. Maybe this could be resolved without resolving that issue, as self-recursive structs are already possible:

```julia
julia> mutable struct Node1 next::Node1; Node1() = new() end

julia> let x = Node1(); x.next = x end
Node1(Node1(#= circular reference @-1 =#))

julia> mutable struct Node2{T} next::T; Node2{T}() where T = new() end

julia> let x = Node2{Node2}(); x.next = x end
Node2{Node2}(Node2{Node2}(#= circular reference @-1 =#))

```

Looking into `Meta.@lower mutable struct Node{T<:Node} next::T end`, it seems as if the undefined variable error is thrown by `Core.TypeVar(:T, Node)` before `Node` exists. I think `Node` starts existing at a `Core._structtype` call that takes the `TypeVar` as an input, and the result seems mutable based on subsequent calls, including `Core._typebody!` annotating fields. Unfortunately, I couldn’t begin to tinker because trying that call by itself in the REPL just crashed Julia.

---

_[View the full topic](https://discourse.julialang.org/t/why-are-self-referential-struct-parameters-impossible/110982)._
