mruby-compiler: fix bare nil? in if/unless to use self as receiver

The if/unless nil? optimization called codegen() on the call node's
receiver, but a bare `nil?` is parsed as an FCALL whose receiver is
NULL. codegen(NULL) emits OP_LOADNIL, so the JMPNIL was testing the
literal nil instead of self, making `if nil?` always behave as
`if nil.nil?` (always true) and `unless nil?` always skip its body.
Load self when the receiver is implicit. Fixes #6874.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-05-30 07:39:18 +09:00
parent 543bc325f3
commit f5ca906852
2 changed files with 33 additions and 1 deletions
+26
View File
@@ -194,3 +194,29 @@ assert('register window of calls (#3783)') do
end
end
end
assert('bare `nil?` in if/unless uses self as receiver (#6874)') do
klass = Class.new do
def unless_form
reached = false
unless nil?
reached = true
end
reached
end
def if_form
if nil?
:yes
else
:no
end
end
end
assert_true klass.new.unless_form
assert_equal :no, klass.new.if_form
# Sanity: explicit literal nil receiver still optimized correctly.
result = if nil.nil? then :yes else :no end
assert_equal :yes, result
end