As a weekend experiment, I decided to write a few prototypes to answer the following question: Is it possible to improve Ruby backtraces by including the class where a given method was defined, similar to how Java and other languages do it?

Turns out that it can be done with a handful of changes in the implementation of backtraces: https://github.com/ivoanjo/ruby/commit/cfa29197cb9f98866ef9c77662f49ba9fdf351a3.

This allows the following example:

module A
  class Super1
    def classes_example
      print_stack_trace(Thread.current.backtrace_locations)
    end
  end
end

module B
  class Super2 < A::Super1
    def classes_example
      super
    end
  end
end

module C
  class Super3 < B::Super2
    def classes_example
      super
    end
  end
end

module D
  class Super4 < C::Super3
    def classes_example
      super
    end
  end
end


puts "Stack for classes_example:"
D::Super4.new.classes_example

…​to be printed as:

Thread.backtrace_locations(rich_stack_trace_example.rb:42)
A::Super1.classes_example(rich_stack_trace_example.rb:42)
B::Super2.classes_example(rich_stack_trace_example.rb:50)
C::Super3.classes_example(rich_stack_trace_example.rb:58)
D::Super4.classes_example(rich_stack_trace_example.rb:66)
Object.<main>(rich_stack_trace_example.rb:73)

…​instead of the more usual:

rich_stack_trace_example.rb:42:in `backtrace_locations'
rich_stack_trace_example.rb:42:in `classes_example'
rich_stack_trace_example.rb:50:in `classes_example'
rich_stack_trace_example.rb:58:in `classes_example'
rich_stack_trace_example.rb:66:in `classes_example'
rich_stack_trace_example.rb:73:in `<main>'

It’s not completely perfect for other cases (modules, singleton definitions, etc) — I hope to look into that in the future.