Non anonymous classes can't be frozen, cloned and then inspected
If you assign a class to a constant (that is, it isn't anonymous), and you freeze it and then clone it, you can't call to_s on it.
MyClass = Class.new ; MyClass.freeze.clone.to_s RuntimeError: can't modify frozen Class from (irb):1:in `to_s' from (irb):1 from /Users/agrimm/.rvm/rubies/ruby-head/bin/irb:16:in `<main>' MyConstantObject = Object.new ; MyConstantObject.freeze.clone.to_s # => "#<Object:0x00000100884d60>" MyClass_2 = Class.new ; MyClass_2.clone.to_s # => "#<Class:0x00000100872930>" MyClass_3 = Class.new ; MyClass_3.freeze.to_s # => "MyClass_3" MyClass_4 = Class.new.freeze ; MyClass_4.clone.to_s # => "#<Class:0x0000010088d4d8>" MyClass_5 = Class.new.freeze ; MyClass_5.freeze.clone.to_s # => An exception local_variable_class = Class.new ; local_variable_class.freeze.clone.to_s # => "#<Class:0x00000100964028>"
Presumably this is caused by class only determining whether it's assigned to a constant when it's first inspected.
I don't have a use case for freezing and cloning a class.
Updated by akr (Akira Tanaka) about 6 years ago
- Status changed from Assigned to Feedback
The name of anonymous class is searched and cached when it is first inspected.
The cache is implemented as a hidden instance variable of the class.
If the class is frozen, the cache is failed as the exception because the instance variable is not assignable.
Note that Class.new.freeze.to_s doesn't raise the exception.
This is because Kernel#freeze is redefined by Module#freeze and it caches the class name before freezing.
Kernel#clone is not redefined.
So there is not such trick to avoid the exception.
I'm not sure that it is worth to fix this problem.
Updated by akr (Akira Tanaka) almost 6 years ago
- Status changed from Feedback to Closed
- % Done changed from 0 to 100
Applied in changeset r46370.
- object.c (rb_mod_initialize_clone): Override Kernel#initialize_clone to avoid an exception on Class.new.freeze.clone.to_s. Reported by Andrew Grimm. [ruby-core:41858] [Bug #5828]