From: merch-redmine@... Date: 2020-11-24T20:12:07+00:00 Subject: [ruby-core:101054] [Ruby master Bug#17321] Having a singleton class makes cloning imperfect Issue #17321 has been updated by jeremyevans0 (Jeremy Evans). Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: REQUIRED ufuk (Ufuk Kayserilioglu) wrote in #note-2: > @jeremyevans0 Thanks for closing the issue. > > Can we get this fix backported to 2.5, 2.6 and 2.7 please? As noted in the original report, this bug is present all the way back to 2.0. 2.5 is unlikely, as that is in security maintenance mode and this is not a security fix. 2.6 and 2.7 are possibilities. However, it is up to the branch maintainers whether this will be backported. I've updated the backport information to show that a backport is requested. ---------------------------------------- Bug #17321: Having a singleton class makes cloning imperfect https://bugs.ruby-lang.org/issues/17321#change-88726 * Author: ufuk (Ufuk Kayserilioglu) * Status: Closed * Priority: Normal * ruby -v: ruby 3.0.0dev (2020-11-11T09:11:09Z master fa3670e6e4) [x86_64-darwin19] * Backport: 2.5: REQUIRED, 2.6: REQUIRED, 2.7: REQUIRED ---------------------------------------- ## Problem --- Running the following reproduction script: ```ruby 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 and me have put together a PR that makes `Case 2` output identical to `Case 1` output: https://github.com/ruby/ruby/pull/3761 -- https://bugs.ruby-lang.org/ Unsubscribe: