Project

General

Profile

Bug #14895

Inconsistent constant names when using const_set on a singleton class

Added by silver_phoenix (Pedro Pinto) 3 months ago. Updated 3 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]
[ruby-core:87787]

Description

irb(main):001:0> class X; end
=> nil
irb(main):002:0> X.const_set(:Y, Module.new)
=> X::Y
irb(main):003:0> module M; end
=> nil
irb(main):004:0> M.const_set(:N, Module.new)
=> M::N
irb(main):005:0> x = Object.new
=> #<Object:0x000055886ee2b110>
irb(main):006:0> x.singleton_class.const_set(:Z, Module.new)
=> #<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, Module.new)
=> #<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]

History

#1 [ruby-core:87812] Updated by nobu (Nobuyoshi Nakada) 3 months 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) 3 months 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) 3 months 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) 3 months 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) 3 months ago

This looks like a bug to me.

Here's a simplified example:

s = Object.new.singleton_class
a = s.const_set(:A, Module.new)       # => #<Module:0x00007fed619915f0>
b = s.class_eval "module B; self end" # => #<Class:0x00007fed6198a020>::B
c = s.const_set(:C, Module.new)       # => #<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