@@ -2122,3 +2122,76 @@ def ==(o)
21222122 roundtripped_obj = ractor.take
21232123 roundtripped_obj.instance_variable_get(:@array) == [1] ? :ok : roundtripped_obj
21242124}
2125+
2126+ # moved composite types move their non-shareable parts properly
2127+ assert_equal 'ok' , %q{
2128+ k, v = String.new("key"), String.new("value")
2129+ h = { k => v }
2130+ h.instance_variable_set("@b", String.new("b"))
2131+ a = [k,v]
2132+ o_singleton = Object.new
2133+ def o_singleton.a
2134+ @a
2135+ end
2136+ o_singleton.instance_variable_set("@a", String.new("a"))
2137+ class MyObject
2138+ attr_reader :a
2139+ def initialize(a)
2140+ @a = a
2141+ end
2142+ end
2143+ struct_class = Struct.new(:a)
2144+ struct = struct_class.new(String.new('a'))
2145+ o = MyObject.new(String.new('a'))
2146+ r = Ractor.new do
2147+ loop do
2148+ obj = Ractor.receive
2149+ val = case obj
2150+ when Hash
2151+ obj['key'] == 'value' && obj.instance_variable_get("@b") == 'b'
2152+ when Array
2153+ obj[0] == 'key'
2154+ when Struct
2155+ obj.a == 'a'
2156+ when Object
2157+ obj.a == 'a'
2158+ end
2159+ Ractor.yield val
2160+ end
2161+ end
2162+
2163+ objs = [h, a, o_singleton, o, struct]
2164+ objs.each_with_index do |obj, i|
2165+ klass = obj.class
2166+ parts_moved = {}
2167+ case obj
2168+ when Hash
2169+ parts_moved[klass] = [obj['key'], obj.instance_variable_get("@b")]
2170+ when Array
2171+ parts_moved[klass] = obj.dup # the contents
2172+ when Struct, Object
2173+ parts_moved[klass] = [obj.a]
2174+ end
2175+ r.send(obj, move: true)
2176+ val = r.take
2177+ if val != true
2178+ raise "bad val in ractor for obj at i:#{i}"
2179+ end
2180+ begin
2181+ p obj
2182+ rescue
2183+ else
2184+ raise "should be moved"
2185+ end
2186+ parts_moved.each do |klass, parts|
2187+ parts.each_with_index do |part, j|
2188+ case part
2189+ when Ractor::MovedObject
2190+ else
2191+ raise "part for class #{klass} at i:#{j} should be moved"
2192+ end
2193+ end
2194+ end
2195+ end
2196+ 'ok'
2197+ }
0 commit comments