Project

General

Profile

Actions

Bug #22197

open

Backtraces show methods which do not exist

Bug #22197: Backtraces show methods which do not exist
1

Added by Eregon (Benoit Daloze) 3 days ago. Updated 3 days ago.

Status:
Open
Assignee:
-
Target version:
-
ruby -v:
ruby 4.0.3 (2026-04-21 revision 85ddef263a) +PRISM [arm64-darwin25]
[ruby-core:126092]

Description

class Parent
  def original
    puts caller_locations(0), nil
  end
end

class Child < Parent
  alias_method :alias, :original
end

Child.new.alias

module Original
  def original
    puts caller_locations(0)
  end
end

class A
  define_method(:a, Original.instance_method(:original))
end

A.new.a

gives:

$ ruby -v backtrace_alias.rb
ruby 4.0.3 (2026-04-21 revision 85ddef263a) +PRISM [arm64-darwin25]
backtrace_alias.rb:3:in 'Child#original'
backtrace_alias.rb:11:in '<main>'

backtrace_alias.rb:15:in 'A#original'
backtrace_alias.rb:23:in '<main>'

But this seems clearly incorrect:

  • there is no Child#original, there is only Parent#original and Child#alias.
  • there is no A#original, there is only Original#original and A#a.

This behavior exists since Ruby 3.4 which added the module name in backtraces (#19117).

So the issue is that backtraces show the "original method name from the definition" with the "method owner of the actually-called method".

It should be consistent to avoid showing methods which don't exist.
And it should be the original method from the definition, because we show the file and line of that, so we should also show the original name (already the case) and the original module (not the case yet, the bug).

FWIW TruffleRuby already behaves like that:

$ truffleruby 34.0.1 (2026-04-26), like ruby 3.4.9, Oracle GraalVM Native [arm64-darwin23]
backtrace_alias.rb:3:in 'Parent#original'
backtrace_alias.rb:11:in '<main>'

backtrace_alias.rb:15:in 'Original#original'
backtrace_alias.rb:23:in '<main>'

In #19117 there was some discussion about this, notably:
https://bugs.ruby-lang.org/issues/19117#note-17
@byroot (Jean Boussier)

My suggestion is for the owner. Simply put because it matches the path and other existing method representations.

But actually the owner isn't that, what is described here is the original module of the method definition, same as the expected from this issue.

https://bugs.ruby-lang.org/issues/19117#note-18
@Eregon (Benoit Daloze)

It must be the owner, anything else would be very confusing.
I believe nobody wants String#then (there is no such method), they want to see Kernel#then.

Where I was wrong about owner being the only thing. I was also expressing we should show where the method is defined, but I overlooked the "originally" part (aliases, define_method, etc).

Also CC @mame (Yusuke Endoh) who implemented the change.

I think this is worth fixing for Ruby 4.1 (not sure if worth backporting).

Updated by Eregon (Benoit Daloze) 3 days ago Actions #1 [ruby-core:126093]

In CRuby implementation terms we'd get the original method module with something like:

const rb_callable_method_entry_t *me = cme;
// (1) unwrap an explicit alias entry, if present
while (me->def->type == VM_METHOD_TYPE_ALIAS) {
  me = me->def->body.alias.original_me;      // cf. original_method_definition(), vm_method.c:2737
}
// (2) defined_class -> real module
VALUE dc = me->defined_class;
VALUE mod = RB_TYPE_P(dc, T_ICLASS) ? RBASIC_CLASS(dc) : dc;   // + prepend-origin guard (4156-4158)

I'll attempt to make a PR for it soon.

Actions

Also available in: PDF Atom