crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.36k stars 1.62k forks source link

`super` with implicit block argument will not call `initialize` #14768

Open chri-k opened 3 months ago

chri-k commented 3 months ago

Bug

if initialize of a class and it's parent have the same signature, super can be used without explicitly passing the arguments. However if they take only a block argument, and you do not pass it explicitly, initialize of the parent class is never called, which easily leads to a segfault.

Sample

class A
  @proc : ->
  @num : Int64

  def initialize(&b)
    puts "A initialised" # not executed
    @proc = ->{}
    @num = 123456789
  end
end

class B < A
  def initialize(&b)
    super  # adding &b here removes the issue
    puts @num  # @num is 0
    @proc.call # tries to read null pointer and crashes
  end
end

b = B.new { }

this is the backtrace:

[0x10bc628cb] *Exception::CallStack::print_backtrace:Nil +107 in /Users/xxx/.cache/crystal/crystal-run-test.tmp
[0x10bc476ed] ~procProc(Int32, Pointer(LibC::SiginfoT), Pointer(Void), Nil)@/usr/local/Cellar/crystal/1.12.2/share/crystal/src/crystal/system/unix/signal.cr:143 +285 in /Users/zxdx/.cache/crystal/crystal-run-test.tmp
[0x7ff81919437d] _sigtramp +29 in /usr/lib/system/libsystem_platform.dylib

Update

For some reason, adding a second argument to the initialize functions instead causes a strange compile error:

class A
  def initialize(a, &b)
  end
end

class B < A
  def initialize(a, &b)
    super 
  end
end

b = B.new { }

with the error being

 14 | super   # adding &b here STIL
      ^----
Error: wrong number of arguments for 'Reference#initialize' (given 1, expected 0)

Overloads are:
 - Reference#initialize()

Version info

OS: macOS 14.1.1 (Sonoma)

Crystal 1.12.2 (2024-05-31)

LLVM: 18.1.6
Default target: x86_64-apple-macosx