Bug #7107

Ruby can no longer find constants in methods in anonymous modules

Added by Eric Hodel over 1 year ago. Updated over 1 year ago.

[ruby-core:47834]
Status:Closed
Priority:Normal
Assignee:Charlie Somerville
Category:core
Target version:2.0.0
ruby -v:ruby 2.0.0dev (2012-09-06 trunk 36915) [x86_64-darwin12.1.0] Backport:

Description

=begin
With ruby 1.9 and newer C cannot be found if m is duplicated:

module M
C = 1

def self.m
  C
end

end

puts 'named module'
M.m

puts 'anonymous module'
m = M.dup
m.m

Ruby 1.8:

$ ruby -v t.rb
ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]
named module
anonymous module

With Ruby 1.9:

$ ruby19 -v t.rb
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin12.2.0]
named module
anonymous module
t.rb:5:in m': uninitialized constant Module::C (NameError)
from t.rb:14:in
'

With trunk:

$ ruby19 -v t.rb 
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin12.2.0]
named module
anonymous module
t.rb:5:in `m': uninitialized constant Module::C (NameError)
    from t.rb:14:in `<main>'

(({m::C})) works in all three versions, though.
=end

Associated revisions

Revision 38423
Added by Charlie Somerville over 1 year ago

  • class.c (rewritecrefstack, clone_method): rewrite a method's cref stack when cloning into a new class to allow lexical const lookup to work as expected [Bug #7107]
  • test/ruby/test_class.rb (class TestClass): related test

History

#1 Updated by Eric Hodel over 1 year ago

=begin
Additionally, when the module is given a name it still can't find the constant:

module M
C = 1

def self.m
  C
end

end

puts 'named module'
M.m

puts 'anonymous module'
m = M.dup
begin
m.m
rescue NameError
p $!
end

puts 're-named module'
N = m
begin
N.m
rescue NameError
p $!
end

Ruby trunk:

$ ruby20 -v t.rb
ruby 2.0.0dev (2012-09-06 trunk 36915) [x86_64-darwin12.1.0]
named module
anonymous module
#
re-named module
#

=end

#2 Updated by Koichi Sasada over 1 year ago

  • Assignee set to Yusuke Endoh

#3 Updated by Yusuke Endoh over 1 year ago

  • Status changed from Open to Assigned
  • Assignee changed from Yusuke Endoh to Nobuyoshi Nakada

Indeed, it looks a bug. Nobu, could you investigate?

Yusuke Endoh mame@tsg.ne.jp

#4 Updated by Masaya Tarui over 1 year ago

hi,

I found strange behavior.

$ ruby -e "module M;C=1;def self.f;C end end;d=M.dup;p M.f;p d.f;class A;end;p d.f"
1
1
-e:1:in f': uninitialized constant Module::C (NameError)
from -e:1:in
'

It seems to hold the problem in InlineCache too.

#5 Updated by Masaya Tarui over 1 year ago

additional sample.
d.f referring to M::C is correct? or d::C?

$ ruby -e "module M;C=1;def self.f;C end end;d=M.dup;p M.f;p d.f;d::C=2;p M.f;p d::C;p d.f"
1
1
-e:1: warning: already initialized constant #Module:0x007ffb39f4c860::C
-e:1: warning: previous definition of C was here
1
2
1

#6 Updated by Charlie Somerville over 1 year ago

=begin

Nobu, I have found the cause of the bug - the cref_stack of methods are not fixed up to point to the new class/module when the class/module is duped.

Do you want me to commit it or attach it here for your review?

=end

#7 Updated by Charlie Somerville over 1 year ago

  • Assignee changed from Nobuyoshi Nakada to Charlie Somerville

#8 Updated by Charlie Somerville over 1 year ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r38423.
Eric, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • class.c (rewritecrefstack, clone_method): rewrite a method's cref stack when cloning into a new class to allow lexical const lookup to work as expected [Bug #7107]
  • test/ruby/test_class.rb (class TestClass): related test

Also available in: Atom PDF