A parametric-type related crash on Julia 1.7+

I discovered a very strange crash scenario while developing my package. It seems to only happen on Julia 1.7+. For example, 1.6 runs perfectly well. It took me some time to create this “MWE” from my code base and I hope someone can look into the Julia source code to see what’s going on. Thanks!

struct T1{T}
    m::T
end

struct T2{L}
    tuple::NTuple{3, Int}

    function T2{L}(t::NTuple{3, Int}) where {L}
        new{sum(t)}(t)
    end
end

struct T3{L, N}
    a::Tuple{T2{L}}
    param::NTuple{N, T1}
    function T3(a::Tuple{T2{L}}, pars::NTuple{N, T1}) where {L, N}
        new{L, N}(a, pars)
    end
end

function f(ts)
    pars = []
    for t in ts
        append!(pars, t.param)
    end
    pars
end

t1_1 = ((T1{Float64}(1.0), T1{Int}(2)))

t1_2 = ((T1{Float64}(1.2), T1{Int}(1)))

t2_1 = (T2{1}((1,0,0)),)

t2_2 = (T2{2}((2,0,0)),)

[T3(t2_1, t1_1), T3(t2_2, t1_2)] |> f

After some debugging, I find out that this is because Julia tries to become smarter in Julia 1.7 and unfortunately miscalculates field offset.

The core problem is t.param, here t is inferred as an abstract type T3{L, 2} where L. But since L is only used for T2 and it doesn’t actually impact the size of T2 (I think you do this deliberately), the size of field a is always 24 (3 Int) and stored inline in T3, so a simple pointer arithmetic can be used to load the value of param.

In Julia 1.6 there’s no such optimization and Julia simply emits a dynamic call to jl_f_getfield and everything is fine. In Julia 1.7 the above optimization is applied and the field offset is wrongly calculated. It should be 24, but calculated as 8. It’s actually something like fieldoffset(T3{L,2},2), where L is a type variable. So it will instead load the second element of the field a. If you change t2_1 to t2_1 = (T2{1}((1,100,0)),) , then you can get a seg fault caused by dereferencing a 100(0x64) pointer. I think the logic is incorrect somewhere, but since I am not familiar with Julia’s type system so I simply left it here for further exploration.

4 Likes

@frankwswang Have you opened an issue on github? This is definitely a bug needed to be fixed.

2 Likes

No. I will file one now. Thanks for the explanation!

2 Likes