Project

General

Profile

Actions

Feature #21335

open

Namespaces should be present in the backtrace

Added by tenderlovemaking (Aaron Patterson) 2 days ago. Updated 2 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:122070]

Description

Namespaces can call in to other name spaces. I think it might be helpful if namespace information is in the backtrace.

For example:

File.binwrite "foo.rb", <<-eorb
class Foo
  def self.test(ns1, ns2, count)
    if count == 0
      puts caller
    else
      if count % 2 == 0
        ns1::Foo.test(ns1, ns2, count - 1)
      else
        ns2::Foo.test(ns1, ns2, count - 1)
      end
    end
  end
end
eorb

ns1 = Namespace.new
ns1.load "foo.rb"

ns2 = Namespace.new
ns2.load "foo.rb"

ns1::Foo.test(ns1, ns2, 10)

The output is like this:

See doc/namespace.md for known issues, etc.
/Users/aaron/git/ruby/exe/ruby: warning: Namespace is experimental, and the behavior may change in the future!
See doc/namespace.md for known issues, etc.
/Users/aaron/git/ruby/foo.rb:9:in 'test'
/Users/aaron/git/ruby/foo.rb:7:in 'test'
/Users/aaron/git/ruby/foo.rb:9:in 'test'
/Users/aaron/git/ruby/foo.rb:7:in 'test'
/Users/aaron/git/ruby/foo.rb:9:in 'test'
/Users/aaron/git/ruby/foo.rb:7:in 'test'
/Users/aaron/git/ruby/foo.rb:9:in 'test'
/Users/aaron/git/ruby/foo.rb:7:in 'test'
/Users/aaron/git/ruby/foo.rb:9:in 'test'
/Users/aaron/git/ruby/foo.rb:7:in 'test'
./test.rb:23:in '<main>'

Foo.test alternates between namespaces when calling a method, but you can't tell from the backtrace. I think we should include namespaces in the backtrace.


Related issues 2 (2 open0 closed)

Related to Ruby - Feature #21311: Namespace on read (revised)Assignedtagomoris (Satoshi Tagomori)Actions
Related to Ruby - Bug #21316: Namespaces leak with permanent namesOpenActions
Actions #1

Updated by tenderlovemaking (Aaron Patterson) 2 days ago

Updated by mame (Yusuke Endoh) 2 days ago

As the current behavior of the backtrace, if the receiver class is completely bound to the constant names, they are prefixed to the method names in the backtrace. So, if you do:

NS1 = Namespace.new
NS1.load "foo.rb"

NS2 = Namespace.new
NS2.load "foo.rb"

NS1::Foo.test(NS1, NS2, 10)

you will see:

$ RUBY_NAMESPACE=1 ./miniruby test.rb
./miniruby: warning: Namespace is experimental, and the behavior may change in the future!
See doc/namespace.md for know issues, etc.
foo.rb:9:in 'NS1::Foo.test'
foo.rb:7:in 'NS2::Foo.test'
foo.rb:9:in 'NS1::Foo.test'
foo.rb:7:in 'NS2::Foo.test'
foo.rb:9:in 'NS1::Foo.test'
foo.rb:7:in 'NS2::Foo.test'
foo.rb:9:in 'NS1::Foo.test'
foo.rb:7:in 'NS2::Foo.test'
foo.rb:9:in 'NS1::Foo.test'
foo.rb:7:in 'NS1::Foo.test'
test.rb:23:in '<main>'

This depends on the output of Class#name, so the result may change depending of the progress of #21316.

Actions #3

Updated by mame (Yusuke Endoh) 2 days ago

  • Related to Bug #21316: Namespaces leak with permanent names added

Updated by mame (Yusuke Endoh) 2 days ago

It is possible to change how to display the backtrace to show class names that are not completely bound to constants.
I have conservatively designed the current spec of the backtrace to avoid potential confusing output, but I'm not sure which would be better.

diff --git a/vm_backtrace.c b/vm_backtrace.c
index 26e0a6fb76..15ec9b7a4d 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -201,20 +201,19 @@ VALUE rb_mod_name0(VALUE klass, bool *permanent);
 VALUE
 rb_gen_method_name(VALUE owner, VALUE name)
 {
-    bool permanent;
     if (RB_TYPE_P(owner, T_CLASS) || RB_TYPE_P(owner, T_MODULE)) {
         if (RCLASS_SINGLETON_P(owner)) {
             VALUE v = RCLASS_ATTACHED_OBJECT(owner);
             if (RB_TYPE_P(v, T_CLASS) || RB_TYPE_P(v, T_MODULE)) {
-                v = rb_mod_name0(v, &permanent);
-                if (permanent && !NIL_P(v)) {
+                v = rb_mod_name(v);
+                if (!NIL_P(v)) {
                     return rb_sprintf("%"PRIsVALUE".%"PRIsVALUE, v, name);
                 }
             }
         }
         else {
-            owner = rb_mod_name0(owner, &permanent);
-            if (permanent && !NIL_P(owner)) {
+            owner = rb_mod_name(owner);
+            if (!NIL_P(owner)) {
                 return rb_sprintf("%"PRIsVALUE"#%"PRIsVALUE, owner, name);
             }
         }
$ RUBY_NAMESPACE=1 ./miniruby test.rb
./miniruby: warning: Namespace is experimental, and the behavior may change in the future!
See doc/namespace.md for know issues, etc.
foo.rb:9:in '#<Namespace:0x00007ff4d61f9f20>::Foo.test'
foo.rb:7:in '#<Namespace:0x00007ff4d61f93e0>::Foo.test'
foo.rb:9:in '#<Namespace:0x00007ff4d61f9f20>::Foo.test'
foo.rb:7:in '#<Namespace:0x00007ff4d61f93e0>::Foo.test'
foo.rb:9:in '#<Namespace:0x00007ff4d61f9f20>::Foo.test'
foo.rb:7:in '#<Namespace:0x00007ff4d61f93e0>::Foo.test'
foo.rb:9:in '#<Namespace:0x00007ff4d61f9f20>::Foo.test'
foo.rb:7:in '#<Namespace:0x00007ff4d61f93e0>::Foo.test'
foo.rb:9:in '#<Namespace:0x00007ff4d61f9f20>::Foo.test'
foo.rb:7:in '#<Namespace:0x00007ff4d61f9f20>::Foo.test'
test.rb:23:in '<main>'

Updated by tagomoris (Satoshi Tagomori) 2 days ago

The ns_id seems good to be shown in backtrace (I'm unsure about this format is good or not):

foo.rb:7:in namespace(1) 'Foo.test'

Updated by tenderlovemaking (Aaron Patterson) 2 days ago

mame (Yusuke Endoh) wrote in #note-2:

As the current behavior of the backtrace, if the receiver class is completely bound to the constant names, they are prefixed to the method names in the backtrace.

Ah, ok, I didn't know that. Thank you.

I'm not sure if printing the address or the ns_id is better. Either works for me, but I'm not sure what would be most ergonomic.

Actions

Also available in: Atom PDF

Like2
Like0Like0Like0Like0Like0Like0