Repository navigation
Description
What happens
Calling a method of FFT or Image with too few arguments converts a Go runtime panic into a Ruby error, instead of checking the count:
FFT.fft()
# ArgumentError: fft: runtime error: index out of range [0] with length 0
Image.new
# ArgumentError: new: runtime error: index out of range [0] with length 0MRI says wrong number of arguments (given 0, expected 1). What rbgo answers names an internal fault, and its class is accidental — it is ArgumentError only because the recovery path labels every panic that way.
Extent, measured
A census over rbgo itself (Special.methods(false).each { |m| … }, every method called with zero arguments, classified by its message) on wave70-special, 2026-10-12:
| receiver | unchecked | checked | takes zero arguments |
|---|---|---|---|
FFT. |
17 | 0 | 0 |
Image. |
2 | 0 | 0 |
Image# |
12 | 0 | 22 |
NDArray. |
0 | 10 | 2 |
NDArray# |
0 | 6 | 30 |
Special. |
0 | 66 | 0 |
Stats. |
0 | 23 | 9 |
Stats::Continuous# / Stats::Discrete# |
0 | 10 / 10 | 9 / 9 |
31 methods in all: every one of FFT's 17, and 14 of Image's.
FFT:bartlett blackman blackman_harris fft fft2 fftfreq fftn hamming hann ifft ifft2 ifftn irfft psd rfft rfftfreq spectrogramImage.:decode newImage#:adjust_brightness adjust_contrast box_blur canny crop dilate erode gaussian_blur get median resize set
Why NDArray is clean, and the fix
NDArray already has the answer in the same package: ndArgc(args, min, max) (internal/vm/ndarray.go:70) raises MRI's ArgumentError with MRI's message, including the min..max and min+ forms. Special and Stats (#819) use it, which is why they report 0.
So the fix is one line per method, and internal/vm/fft.go is the smaller half: most of its methods are registered through two helpers (def and window), so a check in the helper covers the window functions at once.
A test that does not need the list
The census is cheap enough to BE the test, and better than a list because a method added later is covered without being named. TestSpecialArityIsAlwaysChecked and TestStatsArityIsAlwaysChecked (#819) do this for the two new modules:
Special.methods(false).each do |m|
begin; Special.send(m)
rescue => e; bad << m if e.message.include?("runtime error")
end
endThey assert the number of methods walked as well as the empty result, so a census that reads nothing fails rather than passing. Dropping one arity check from special.go makes it name the exact 33 methods affected — verified.
The same shape would fit FFT and Image.
Severity
Not a crash: the panic is recovered and the VM survives. It is wrong behaviour — a Ruby program rescuing ArgumentError and reading e.message sees Go's internals, and a program relying on the message to tell a user what it passed wrongly cannot. It is also the kind of defect that hides the next one, since a genuine index fault inside a binding would read identically.
Measured 2026-10-12 with go1.27.2, CGO_ENABLED=0.
🤖 Generated with Claude Code
Activity
Special, Stats: assert the surface is complete and that arity is alwa…
Special, Stats: assert the surface is complete and that arity is alwa…
Special, Stats, Integrate, Optimize: go-numerics and go-statistics as…
FFT, Image: every method declares its arity, so a missing argument is…
FFT, Image: every method declares its arity, so a missing argument is…