Bug #14895

Inconsistent constant names when using const_set on a singleton class

Added by silver_phoenix (Pedro Pinto) 14 days ago. Updated 13 days ago.

Target version:
ruby -v:
ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]


irb(main):001:0> class X; end
=> nil
irb(main):002:0> X.const_set(:Y,
=> X::Y
irb(main):003:0> module M; end
=> nil
irb(main):004:0> M.const_set(:N,
=> M::N
irb(main):005:0> x =
=> #<Object:0x000055886ee2b110>
irb(main):006:0> x.singleton_class.const_set(:Z,
=> #<Module:0x000055886ec59a80>
irb(main):007:0> x.singleton_class.class_eval "module A; self end"
=> #<Class:0x000055886ec59d00>::A
irb(main):008:0> x.singleton_class.const_set(:B,
=> #<Class:0x000055886ec59d00>::B

I would expect module Z to be named, but the modules only start being named after creating module A through the module builtin.

For consistency, if module B is named, shouldn't module Z be named as well?

Also happens in these ruby versions:
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
ruby 2.5.1p57 (2018-03-29 revision 63029) [i386-mingw32]


#1 [ruby-core:87812] Updated by nobu (Nobuyoshi Nakada) 14 days ago

The names of A, B, and Z are temporary names at the moments of assignment.
Once you assign x.singleton_class to a constant, say C, they appear as C::A, C::B, and C::Z, respectively.

#2 [ruby-core:87815] Updated by silver_phoenix (Pedro Pinto) 13 days ago

Yes, I understand that, but why isn't Z named like B is?

Z is #<Module:...> (unnamed)
B is #<...>::B (named)

There's something not being initialized on the singleton class, which is only triggered after adding a named module explicitly (like what's being done with the A module example).

#3 [ruby-core:87816] Updated by nobu (Nobuyoshi Nakada) 13 days ago

silver_phoenix (Pedro Pinto) wrote:

Yes, I understand that, but why isn't Z named like B is?

Z is #<Module:...> (unnamed)
B is #<...>::B (named)

Because they are not "fully-named" yet.

#4 [ruby-core:87817] Updated by silver_phoenix (Pedro Pinto) 13 days ago

So, what you're saying is that the singleton class is being assigned to a constant when it creates module A, so modules are only named after this step?

Is this expected behavior then?

#5 [ruby-core:87820] Updated by marcandre (Marc-Andre Lafortune) 13 days ago

This looks like a bug to me.

Here's a simplified example:

s =
a = s.const_set(:A,       # => #<Module:0x00007fed619915f0>
b = s.class_eval "module B; self end" # => #<Class:0x00007fed6198a020>::B
c = s.const_set(:C,       # => #<Class:0x00007fed6198a020>::C

a and c should be treated identically. The right behavior would be for their name to be #<Class:0x...>::A/C

Note that naming the singleton class afterwards changes all names correctly:

S = s # => #<Class:#<Object:0x00007fed6198a1b0>> 
a   # => S::A 
b   # => S::B 
c   # => S::C 

Also available in: Atom PDF