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