# Compiler/Optimizer Type Inference Bug with Recursive, Nested Types (in v1.12.6)

**URL:** https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526
**Category:** Internals & Design
**Tags:** bug, compiler, type-inference
**Created:** [July 29, 2026, 11:21am UTC](https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526 "2026-07-29T11:21:12Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![skraemer](https://avatars.discourse-cdn.com/v4/letter/s/4bbf92/32.png) [@skraemer](https://discourse.julialang.org/u/skraemer)
#### Post date: [July 29, 2026, 11:21am UTC](https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526/1 "2026-07-29T11:21:12Z")

</div>

The following two examples each produce supposedly impossible results or crash the repl entirely, even though the code is pure Julia. I did not manage to reduce the examples further, at least not by simplifying single lines:

For instance, in the first example, at line 17, changing `Vector{Tuple{T,T}}` to just `Vector{T}` fixes the output. In the second example, removing the first field `x::UInt` from `Between` so far leads to correct results.

Maybe I am still overlooking something, but as far as I can tell, there is nothing wrong with the code itself.

#### First example:

```julia-auto
mutable struct Bottom{Val_T}
    const val::Val_T
    Bottom{Val_T}() where Val_T = new{Val_T}(Val_T())
end

struct Mid{Val_T}
    val::Val_T
    bottom::Bottom{Val_T}
end

function Mid{Val_T}() where Val_T
    bottom = Bottom{Val_T}()
    Mid(bottom.val, bottom)
end

mutable struct Val{T}
    tuple_TT::Vector{Tuple{T,T}}
    Val{T}() where T = new{T}()
end

struct TopLevel
    mid::Union{Nothing,Mid{Val{TopLevel}}}
end

TopLevel() = TopLevel(Mid{Val{TopLevel}}())
foo(x::Mid) = x

function test()
    x = TopLevel()
    v = TopLevel[x, x]
    y = v[1]

    println(typeof(y) === typeof(x)) # true

    x_mid = getfield(x, :mid)
    println(typeof(x_mid)) # Mid{Val{TopLevel}}
    foo(x_mid)

    y_mid = getfield(y, :mid)
    println(typeof(y_mid)) # TopLevel
    try
        foo(y_mid)
    catch err
        println(err) # MethodError(Main.foo, (TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef)))),), h*) (*for some UInt h)
    end
end
test()

```

#### Second example:

```julia-auto
struct Between{Val_T}
    x::UInt
    y::Val_T
    Between{Val_T}() where Val_T = new{Val_T}(UInt(0), Val_T())
end

mutable struct Bottom{Val_T} 
    const val::Val_T
    Bottom{Val_T}() where Val_T = new{Val_T}(Val_T()) 
end

struct Mid{Val_T} 
    val::Val_T
    bottom::Bottom{Val_T}
end

function Mid{Val_T}() where Val_T
    bottom = Bottom{Val_T}()
    Mid(bottom.val, bottom)
end

mutable struct Val{T}
    tuple_TT::Vector{Tuple{T,T}}
    Val{T}() where T = new{T}()
end

struct TopLevel
    mid::Mid{Between{Val{TopLevel}}}
end

TopLevel() = TopLevel(Mid{Between{Val{TopLevel}}}())

function test()
    x = TopLevel()
    v = [x, x]
    y = v[1]

    println("types start equal: $(typeof(y) === typeof(x)) \n") 
    println(y.mid.bottom) # prints ReentrantLock()

    x = TopLevel()
    v = Any[x, x]
    y = v[1]

    println("types start equal: $(typeof(y) === typeof(x)) \n") 
    # println(y.mid) # when uncommented, the repl crashes seemingly randomly sometimes directly, sometimes after rerunning the script several times
end
test()

```

---

<div class="post-metadata">

### Author: ![Tortar](https://avatars.discourse-cdn.com/v4/letter/t/6bbea6/32.png) [@Tortar](https://discourse.julialang.org/u/Tortar)
#### Post date: [July 29, 2026, 1:34pm UTC](https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526/2 "2026-07-29T13:34:36Z")

</div>

This seems a bug report you should send on the Julia issue tracker here: [Issues · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues)

---

<div class="post-metadata">

### Author: ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)
#### Post date: [July 29, 2026, 1:52pm UTC](https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526/3 "2026-07-29T13:52:27Z")

</div>

I suspect this is a duplicate of [Partially initialized datatypes are prone to crashes · Issue #60919 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/60919), which was fixed (very) recently by [Use typegroup mechanism for ordinary structs - Pull Request #61306 - JuliaLang/julia - GitHub](https://github.com/JuliaLang/julia/pull/61306), and will land in 1.14

---

<div class="post-metadata">

### Author: ![skraemer](https://avatars.discourse-cdn.com/v4/letter/s/4bbf92/32.png) [@skraemer](https://discourse.julialang.org/u/skraemer)
#### Post date: [July 30, 2026, 10:00am UTC](https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526/4 "2026-07-30T10:00:02Z")

</div>

Whether duplicate or not, it seems to me that the typegroup mechanic in v1.14 is going to change handling of recursive types fundamentally, such that it also covers these cases.

---

<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: [July 30, 2026, 11:13am UTC](https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526/5 "2026-07-30T11:13:16Z")

</div>

This is pretty odd, does 1.14 fix this bit? Even if fixed by then, it could be worth its own bug report for potentially earlier patches.

```julia-auto
julia> x = TopLevel()
TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef))))

julia> v = TopLevel[x, x] # impossible 2 instances
2-element Vector{TopLevel}:
 TopLevel(TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef)))))
 TopLevel(TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef)))))

julia> TopLevel[x] # fine at 1
1-element Vector{TopLevel}:
 TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef))))

julia> TopLevel[x,x,x] # fine at 3
3-element Vector{TopLevel}:
 TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef))))
 TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef))))
 TopLevel(Mid{Val{TopLevel}}(Val{TopLevel}(#undef), Bottom{Val{TopLevel}}(Val{TopLevel}(#undef))))

```

---

<div class="post-metadata">

### Author: ![skraemer](https://avatars.discourse-cdn.com/v4/letter/s/4bbf92/32.png) [@skraemer](https://discourse.julialang.org/u/skraemer)
#### Post date: [July 30, 2026, 1:30pm UTC](https://discourse.julialang.org/t/compiler-optimizer-type-inference-bug-with-recursive-nested-types-in-v1-12-6/138526/6 "2026-07-30T13:30:44Z")

</div>

I did not realize that the first example specifically fails for a vector of length 2. Seems however that the second example fails (still somewhat randomly) for any length.

In any case, if someone considers this worth reporting as its own bug, please feel free to do so if you want.
