Project

General

Profile

Actions

Bug #21535

closed

`NoMethodError` becomes `NameError`when using `...` delegation and method call indirection

Added by Earlopain (Earlopain _) about 1 month ago. Updated 11 days ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.5.0dev (2025-08-08T02:57:23Z master 3ad26d0501) +PRISM [x86_64-linux]
[ruby-core:122935]

Description

Consider this code:

class Test
  def foo(...)
    nil.foo(...)
  end

  def foo_indirect
    foo
  end
end

begin
  Test.new.foo
rescue => e
  puts e.class
end

begin
  Test.new.foo_indirect
rescue => e
  puts e.class
end
$ ruby -v foo.rb 
ruby 3.3.6 (2024-11-05 revision 75015d4c1f) [x86_64-linux]
NoMethodError
NoMethodError

$ ruby -v foo.rb 
ruby 3.5.0dev (2025-08-08T02:57:23Z master 3ad26d0501) +PRISM [x86_64-linux]
NoMethodError
NameError

On ruby 3.3 it used to always raise a NoMethodError. Starting with Ruby 3.4, it raises a NoMethodError when calling the method directly, and a NameError when the method is called indirectly via a different method.

The context is the delegate method from rails (original issue https://github.com/rails/rails/issues/55463), which rescues the NoMethodError to raise a more specific error class.

The problem is the ... delegation. If the method accepts no arguments, *, **, or something else, it behaves as expected.

Updated by byroot (Jean Boussier) 28 days ago

  • Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED

I ran a bisect and as suspected this regression was caused by the forward call optimization in https://github.com/ruby/ruby/commit/cdf33ed5f37f9649c482c3ba1d245f0d80ac01ce

FYI: @tenderlovemaking (Aaron Patterson)

Actions #3

Updated by Anonymous 11 days ago

  • Status changed from Open to Closed

Applied in changeset git|886268856ba7c70a6eaf25eeb402e6ebed9e851e.


Fix bad NameError raised using sendforward instruction through vcall

If you called a VCALL method and the method takes forwarding arguments
and then you forward those arguments along using the sendforward instruction,
the method_missing class was wrongly chosen as NameError instead of NoMethodError.
This is because the VM looked at the CallInfo of the vcall and determined it needed
to raise NameError. Now we detect that case and raise NoMethodError.

Fixes [Bug #21535]

Updated by alanwu (Alan Wu) 11 days ago

  • Backport changed from 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONE
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0