Skip to content

Self-recursive type definition with a Union segfaults #33709

@Liozou

Description

@Liozou

Hi everyone! I just noticed that defining such a type segfaults:

struct Foo
   x::Union{Foo, Nothing}
end

yields

signal (11): Segmentation fault
in expression starting at REPL[1]:1
union_isbits at /home/liozou/julia/src/datatype.c:260
union_isbits at /home/liozou/julia/src/datatype.c:253
jl_islayout_inline at /home/liozou/julia/src/datatype.c:272
jl_compute_field_offsets at /home/liozou/julia/src/datatype.c:320
eval_structtype at /home/liozou/julia/src/interpreter.c:277
eval_body at /home/liozou/julia/src/interpreter.c:746
jl_interpret_toplevel_thunk_callback at /home/liozou/julia/src/interpreter.c:888
unknown function (ip: 0x7f617b33702b)
jl_interpret_toplevel_thunk at /home/liozou/julia/src/interpreter.c:897
jl_toplevel_eval_flex at /home/liozou/julia/src/toplevel.c:814
jl_toplevel_eval_flex at /home/liozou/julia/src/toplevel.c:764
jl_toplevel_eval at /home/liozou/julia/src/toplevel.c:823
jl_toplevel_eval_in at /home/liozou/julia/src/toplevel.c:843
eval at ./boot.jl:331
jl_fptr_args at /home/liozou/julia/src/gf.c:1910
_jl_invoke at /home/liozou/julia/src/gf.c:2130
jl_apply_generic at /home/liozou/julia/src/gf.c:2300
eval_user_input at /home/liozou/julia/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
macro expansion at /home/liozou/julia/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:118 [inlined]
#26 at ./task.jl:333
jl_fptr_args at /home/liozou/julia/src/gf.c:1910
_jl_invoke at /home/liozou/julia/src/gf.c:2130
jl_apply_generic at /home/liozou/julia/src/gf.c:2300
jl_apply at /home/liozou/julia/src/julia.h:1647
start_task at /home/liozou/julia/src/task.c:687
unknown function (ip: (nil))
Allocations: 934653 (Pool: 934420; Big: 233); GC: 1
Segmentation fault (core dumped)

I don't have a particular use case for this but I believe this should at most error instead of segfaulting. Git-bisection shows that #32448 introduced this behaviour. This code for instance used to work (and is now broken):

julia> struct Foo
          x::Union{Foo, Nothing}
       end

julia> function foo(x,n)
           for _ in 1:n
               x = Foo(x)
           end
           return x
       end
foo (generic function with 1 method)

julia> Base.length(f::Foo) = isnothing(f.x) ? 1 : 1 + length(f.x)

julia> length(foo(nothing, 1000))
1000

Version info:

julia> versioninfo()
Julia Version 1.4.0-DEV.379
Commit 88c34fc51d (2019-10-28 14:08 UTC)
DEBUG build
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, skylake)

Metadata

Metadata

Assignees

No one assigned

    Labels

    regressionRegression in behavior compared to a previous version

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions