Actions
Bug #17321
closedHaving a singleton class makes cloning imperfect
Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.0.0dev (2020-11-11T09:11:09Z master fa3670e6e4) [x86_64-darwin19]
Backport:
Description
Problem¶
Running the following reproduction script:
class Foo
def self.foo; end
end
def report(klass, name)
puts " #{name}.instance_methods(false): #{klass.instance_methods(false)}"
end
def clone_and_compare(obj)
cln = obj.clone
report(obj.singleton_class, "obj.singleton_class")
report(cln.singleton_class, "cln.singleton_class")
report(obj.singleton_class.singleton_class, "obj.singleton_class.singleton_class")
report(cln.singleton_class.singleton_class, "cln.singleton_class.singleton_class")
end
puts "## Case 1"
obj = Foo.new
clone_and_compare(obj)
puts "## Case 2"
obj = Foo.new
obj.singleton_class
clone_and_compare(obj)
puts "## Case 3"
obj = Foo.new
obj.singleton_class.singleton_class.send(:define_method, :method_on_s2) {}
clone_and_compare(obj)
gives the following output:
## Case 1
obj.singleton_class.instance_methods(false): []
cln.singleton_class.instance_methods(false): []
obj.singleton_class.singleton_class.instance_methods(false): []
cln.singleton_class.singleton_class.instance_methods(false): []
## Case 2
obj.singleton_class.instance_methods(false): []
cln.singleton_class.instance_methods(false): []
obj.singleton_class.singleton_class.instance_methods(false): []
cln.singleton_class.singleton_class.instance_methods(false): [:foo]
## Case 3
obj.singleton_class.instance_methods(false): []
cln.singleton_class.instance_methods(false): []
obj.singleton_class.singleton_class.instance_methods(false): [:method_on_s2]
cln.singleton_class.singleton_class.instance_methods(false): [:method_on_s2]
Case 2
is surprising, because the cloned object has different contents to the original.
It is surprising that clone.singleton_class.singleton_class
has the method :foo
whereas
obj.singleton_class.singleton_class
does not have any methods.
Case 3
suggests, however, that clone.singleton_class.singleton_class
should have the
same methods as the ones on obj.singleton_class.singleton_class
.
This reproduction script gives the same output all the way from Ruby 2.0 up to Ruby-HEAD:
https://wandbox.org/permlink/hRM9OMgtd6nuscRz
Fix¶
@alanwu (Alan Wu) and me have put together a PR that makes Case 2
output identical to Case 1
output:
https://github.com/ruby/ruby/pull/3761
Actions
Like0
Like0Like0Like0Like0Like0