From 4c893e2ff1077b977483da14c0540e9247b87c7e Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Fri, 5 Dec 2025 01:19:55 +0900 Subject: [PATCH] Method and UnboundMethod can be sharable with `RUBY_TYPED_FROZEN_SHAREABLE_NO_REC`, if the receiver object is shareable on Method objects. --- bootstraptest/test_ractor.rb | 22 ++++++++++++++++++++++ proc.c | 2 +- test/ruby/test_ractor.rb | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 6c3a45148c..cc00fa3586 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1203,6 +1203,28 @@ assert_equal '[:ok, "Proc\'s self is not shareable:"]', %q{ end } +# Ractor.make_sharable(Method/UnboundMethod) +assert_equal 'true', %q{ + # raise because receiver is unsharable + begin + _m0 = Ractor.make_shareable(self.method(:__id__)) + rescue => e + raise e unless e.message =~ /can not make shareable object/ + else + raise "no error" + end + + # Method with sharable receiver + M1 = Ractor.make_shareable(Object.method(:__id__)) + + # UnboundMethod + M2 = Ractor.make_shareable(Object.instance_method(:__id__)) + + Ractor.new do + Object.__id__ == M1.call && M1.call == M2.bind_call(Object) + end.value +} + # Ractor.shareable?(recursive_objects) assert_equal '[false, false]', %q{ y = [] diff --git a/proc.c b/proc.c index 2b14c38938..2df8fbee5e 100644 --- a/proc.c +++ b/proc.c @@ -1668,7 +1668,7 @@ static const rb_data_type_t method_data_type = { NULL, // No external memory to report, bm_mark_and_move, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE | RUBY_TYPED_FROZEN_SHAREABLE_NO_REC }; VALUE diff --git a/test/ruby/test_ractor.rb b/test/ruby/test_ractor.rb index efc67338e4..09c470911a 100644 --- a/test/ruby/test_ractor.rb +++ b/test/ruby/test_ractor.rb @@ -47,7 +47,7 @@ class TestRactor < Test::Unit::TestCase def x.to_s raise "this should not be called" end - assert_unshareable(x, "can not make shareable object for #", exception: Ractor::Error) + assert_unshareable(x, "can not make shareable object for # because it refers unshareable objects", exception: Ractor::Error) end def test_default_thread_group