rbs 3.9.5 → 3.10.0.pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/.clang-format +74 -0
  3. data/.clangd +2 -0
  4. data/.github/workflows/c-check.yml +54 -0
  5. data/.github/workflows/comments.yml +3 -3
  6. data/.github/workflows/ruby.yml +34 -19
  7. data/.github/workflows/typecheck.yml +1 -1
  8. data/.github/workflows/windows.yml +1 -1
  9. data/.gitignore +4 -0
  10. data/README.md +38 -1
  11. data/Rakefile +152 -23
  12. data/config.yml +190 -62
  13. data/core/array.rbs +44 -43
  14. data/core/dir.rbs +2 -2
  15. data/core/encoding.rbs +3 -2
  16. data/core/enumerable.rbs +89 -2
  17. data/core/errno.rbs +8 -0
  18. data/core/errors.rbs +28 -1
  19. data/core/exception.rbs +2 -2
  20. data/core/fiber.rbs +3 -3
  21. data/core/file.rbs +26 -11
  22. data/core/float.rbs +1 -1
  23. data/core/gc.rbs +422 -281
  24. data/core/hash.rbs +1024 -727
  25. data/core/io/wait.rbs +11 -33
  26. data/core/io.rbs +6 -4
  27. data/core/kernel.rbs +49 -43
  28. data/core/marshal.rbs +1 -1
  29. data/core/match_data.rbs +1 -1
  30. data/core/math.rbs +42 -3
  31. data/core/method.rbs +14 -6
  32. data/core/module.rbs +71 -11
  33. data/core/nil_class.rbs +3 -3
  34. data/core/numeric.rbs +8 -8
  35. data/core/object.rbs +3 -3
  36. data/core/object_space.rbs +13 -0
  37. data/{stdlib/pathname/0 → core}/pathname.rbs +253 -352
  38. data/core/proc.rbs +15 -8
  39. data/core/process.rbs +2 -2
  40. data/core/ractor.rbs +278 -437
  41. data/core/range.rbs +6 -7
  42. data/core/rbs/unnamed/argf.rbs +1 -1
  43. data/core/rbs/unnamed/env_class.rbs +1 -1
  44. data/core/rbs/unnamed/random.rbs +4 -2
  45. data/core/regexp.rbs +22 -17
  46. data/core/ruby_vm.rbs +6 -4
  47. data/core/rubygems/errors.rbs +3 -70
  48. data/core/rubygems/rubygems.rbs +11 -79
  49. data/core/set.rbs +439 -332
  50. data/core/string.rbs +2897 -1117
  51. data/core/struct.rbs +1 -1
  52. data/core/symbol.rbs +4 -4
  53. data/core/thread.rbs +83 -20
  54. data/core/time.rbs +35 -9
  55. data/core/unbound_method.rbs +14 -6
  56. data/docs/aliases.md +79 -0
  57. data/docs/collection.md +2 -2
  58. data/docs/gem.md +0 -1
  59. data/docs/sigs.md +3 -3
  60. data/ext/rbs_extension/ast_translation.c +1016 -0
  61. data/ext/rbs_extension/ast_translation.h +37 -0
  62. data/ext/rbs_extension/class_constants.c +157 -0
  63. data/{include/rbs/constants.h → ext/rbs_extension/class_constants.h} +7 -1
  64. data/ext/rbs_extension/compat.h +10 -0
  65. data/ext/rbs_extension/extconf.rb +25 -1
  66. data/ext/rbs_extension/legacy_location.c +317 -0
  67. data/ext/rbs_extension/legacy_location.h +45 -0
  68. data/ext/rbs_extension/main.c +365 -14
  69. data/ext/rbs_extension/rbs_extension.h +6 -21
  70. data/ext/rbs_extension/rbs_string_bridging.c +9 -0
  71. data/ext/rbs_extension/rbs_string_bridging.h +24 -0
  72. data/include/rbs/ast.h +687 -0
  73. data/include/rbs/defines.h +86 -0
  74. data/include/rbs/lexer.h +199 -0
  75. data/include/rbs/location.h +59 -0
  76. data/include/rbs/parser.h +135 -0
  77. data/include/rbs/string.h +49 -0
  78. data/include/rbs/util/rbs_allocator.h +59 -0
  79. data/include/rbs/util/rbs_assert.h +20 -0
  80. data/include/rbs/util/rbs_buffer.h +83 -0
  81. data/include/rbs/util/rbs_constant_pool.h +6 -67
  82. data/include/rbs/util/rbs_encoding.h +282 -0
  83. data/include/rbs/util/rbs_unescape.h +23 -0
  84. data/include/rbs.h +1 -2
  85. data/lib/rbs/annotate/formatter.rb +3 -13
  86. data/lib/rbs/annotate/rdoc_annotator.rb +3 -1
  87. data/lib/rbs/annotate/rdoc_source.rb +1 -1
  88. data/lib/rbs/cli/validate.rb +2 -2
  89. data/lib/rbs/cli.rb +1 -1
  90. data/lib/rbs/collection/config/lockfile_generator.rb +1 -0
  91. data/lib/rbs/definition_builder/ancestor_builder.rb +5 -5
  92. data/lib/rbs/environment.rb +64 -59
  93. data/lib/rbs/environment_loader.rb +1 -1
  94. data/lib/rbs/errors.rb +1 -1
  95. data/lib/rbs/parser_aux.rb +5 -0
  96. data/lib/rbs/resolver/constant_resolver.rb +2 -2
  97. data/lib/rbs/resolver/type_name_resolver.rb +124 -38
  98. data/lib/rbs/test/type_check.rb +13 -0
  99. data/lib/rbs/types.rb +3 -1
  100. data/lib/rbs/version.rb +1 -1
  101. data/lib/rbs.rb +1 -1
  102. data/lib/rdoc/discover.rb +1 -1
  103. data/lib/rdoc_plugin/parser.rb +3 -3
  104. data/sig/annotate/formatter.rbs +2 -2
  105. data/sig/annotate/rdoc_annotater.rbs +1 -1
  106. data/sig/environment.rbs +57 -6
  107. data/sig/manifest.yaml +0 -1
  108. data/sig/parser.rbs +20 -0
  109. data/sig/resolver/type_name_resolver.rbs +38 -7
  110. data/sig/types.rbs +4 -1
  111. data/src/ast.c +1256 -0
  112. data/src/lexer.c +2956 -0
  113. data/src/lexer.re +147 -0
  114. data/src/lexstate.c +205 -0
  115. data/src/location.c +71 -0
  116. data/src/parser.c +3495 -0
  117. data/src/string.c +90 -0
  118. data/src/util/rbs_allocator.c +152 -0
  119. data/src/util/rbs_assert.c +21 -0
  120. data/src/util/rbs_buffer.c +54 -0
  121. data/src/util/rbs_constant_pool.c +16 -86
  122. data/src/util/rbs_encoding.c +21308 -0
  123. data/src/util/rbs_unescape.c +131 -0
  124. data/stdlib/cgi/0/core.rbs +2 -396
  125. data/stdlib/cgi/0/manifest.yaml +1 -0
  126. data/stdlib/cgi-escape/0/escape.rbs +153 -0
  127. data/stdlib/coverage/0/coverage.rbs +3 -1
  128. data/stdlib/delegate/0/delegator.rbs +10 -7
  129. data/stdlib/erb/0/erb.rbs +737 -347
  130. data/stdlib/fileutils/0/fileutils.rbs +18 -13
  131. data/stdlib/forwardable/0/forwardable.rbs +3 -0
  132. data/stdlib/json/0/json.rbs +67 -48
  133. data/stdlib/net-http/0/net-http.rbs +3 -0
  134. data/stdlib/objspace/0/objspace.rbs +8 -3
  135. data/stdlib/open-uri/0/open-uri.rbs +40 -0
  136. data/stdlib/openssl/0/openssl.rbs +182 -149
  137. data/stdlib/optparse/0/optparse.rbs +3 -3
  138. data/stdlib/rdoc/0/code_object.rbs +2 -2
  139. data/stdlib/rdoc/0/comment.rbs +2 -0
  140. data/stdlib/rdoc/0/options.rbs +76 -0
  141. data/stdlib/rdoc/0/rdoc.rbs +7 -5
  142. data/stdlib/rdoc/0/store.rbs +1 -1
  143. data/stdlib/resolv/0/resolv.rbs +25 -68
  144. data/stdlib/ripper/0/ripper.rbs +5 -2
  145. data/stdlib/singleton/0/singleton.rbs +3 -0
  146. data/stdlib/socket/0/socket.rbs +13 -1
  147. data/stdlib/socket/0/tcp_socket.rbs +10 -2
  148. data/stdlib/stringio/0/stringio.rbs +412 -80
  149. data/stdlib/strscan/0/string_scanner.rbs +31 -31
  150. data/stdlib/tempfile/0/tempfile.rbs +1 -1
  151. data/stdlib/tsort/0/cyclic.rbs +3 -0
  152. data/stdlib/uri/0/common.rbs +11 -2
  153. data/stdlib/uri/0/file.rbs +1 -1
  154. data/stdlib/uri/0/generic.rbs +16 -15
  155. data/stdlib/uri/0/rfc2396_parser.rbs +6 -7
  156. data/stdlib/zlib/0/zstream.rbs +1 -0
  157. metadata +41 -18
  158. data/ext/rbs_extension/lexer.c +0 -2728
  159. data/ext/rbs_extension/lexer.h +0 -179
  160. data/ext/rbs_extension/lexer.re +0 -147
  161. data/ext/rbs_extension/lexstate.c +0 -175
  162. data/ext/rbs_extension/location.c +0 -325
  163. data/ext/rbs_extension/location.h +0 -85
  164. data/ext/rbs_extension/parser.c +0 -2982
  165. data/ext/rbs_extension/parser.h +0 -18
  166. data/ext/rbs_extension/parserstate.c +0 -411
  167. data/ext/rbs_extension/parserstate.h +0 -163
  168. data/ext/rbs_extension/unescape.c +0 -32
  169. data/include/rbs/ruby_objs.h +0 -72
  170. data/src/constants.c +0 -153
  171. data/src/ruby_objs.c +0 -799
data/core/ractor.rbs CHANGED
@@ -1,12 +1,9 @@
1
1
  # <!-- rdoc-file=ractor.rb -->
2
- # Ractor is an Actor-model abstraction for Ruby that provides thread-safe
3
- # parallel execution.
4
- #
5
2
  # Ractor.new makes a new Ractor, which can run in parallel.
6
3
  #
7
4
  # # The simplest ractor
8
5
  # r = Ractor.new {puts "I am in Ractor!"}
9
- # r.take # wait for it to finish
6
+ # r.join # wait for it to finish
10
7
  # # Here, "I am in Ractor!" is printed
11
8
  #
12
9
  # Ractors do not share all objects with each other. There are two main benefits
@@ -40,55 +37,12 @@
40
37
  # puts "I am in Ractor! a=#{a_in_ractor}"
41
38
  # end
42
39
  # r.send(a) # pass it
43
- # r.take
40
+ # r.join
44
41
  # # Here, "I am in Ractor! a=1" is printed
45
42
  #
46
- # There are two pairs of methods for sending/receiving messages:
47
- #
48
- # * Ractor#send and Ractor.receive for when the *sender* knows the receiver
49
- # (push);
50
- # * Ractor.yield and Ractor#take for when the *receiver* knows the sender
51
- # (pull);
52
- #
53
43
  # In addition to that, any arguments passed to Ractor.new are passed to the
54
44
  # block and available there as if received by Ractor.receive, and the last block
55
- # value is sent outside of the ractor as if sent by Ractor.yield.
56
- #
57
- # A little demonstration of a classic ping-pong:
58
- #
59
- # server = Ractor.new(name: "server") do
60
- # puts "Server starts: #{self.inspect}"
61
- # puts "Server sends: ping"
62
- # Ractor.yield 'ping' # The server doesn't know the receiver and sends to whoever interested
63
- # received = Ractor.receive # The server doesn't know the sender and receives from whoever sent
64
- # puts "Server received: #{received}"
65
- # end
66
- #
67
- # client = Ractor.new(server) do |srv| # The server is sent to the client, and available as srv
68
- # puts "Client starts: #{self.inspect}"
69
- # received = srv.take # The client takes a message from the server
70
- # puts "Client received from " \
71
- # "#{srv.inspect}: #{received}"
72
- # puts "Client sends to " \
73
- # "#{srv.inspect}: pong"
74
- # srv.send 'pong' # The client sends a message to the server
75
- # end
76
- #
77
- # [client, server].each(&:take) # Wait until they both finish
78
- #
79
- # This will output something like:
80
- #
81
- # Server starts: #<Ractor:#2 server test.rb:1 running>
82
- # Server sends: ping
83
- # Client starts: #<Ractor:#3 test.rb:8 running>
84
- # Client received from #<Ractor:#2 server test.rb:1 blocking>: ping
85
- # Client sends to #<Ractor:#2 server test.rb:1 blocking>: pong
86
- # Server received: pong
87
- #
88
- # Ractors receive their messages via the *incoming port*, and send them to the
89
- # *outgoing port*. Either one can be disabled with Ractor#close_incoming and
90
- # Ractor#close_outgoing, respectively. When a ractor terminates, its ports are
91
- # closed automatically.
45
+ # value can be received with Ractor#value.
92
46
  #
93
47
  # ## Shareable and unshareable objects
94
48
  #
@@ -128,7 +82,7 @@
128
82
  # puts "In ractor: #{data2.object_id}, #{data2[0].object_id}, #{data2[1].object_id}"
129
83
  # end
130
84
  # r.send(data)
131
- # r.take
85
+ # r.join
132
86
  # puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"
133
87
  #
134
88
  # This will output something like:
@@ -151,7 +105,7 @@
151
105
  # puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
152
106
  # end
153
107
  # r.send(data, move: true)
154
- # r.take
108
+ # r.join
155
109
  # puts "Outside: moved? #{Ractor::MovedObject === data}"
156
110
  # puts "Outside: #{data.inspect}"
157
111
  #
@@ -164,7 +118,7 @@
164
118
  # Notice that even `inspect` (and more basic methods like `__id__`) is
165
119
  # inaccessible on a moved object.
166
120
  #
167
- # Class and Module objects are shareable so the class/module definitions are
121
+ # `Class` and `Module` objects are shareable so the class/module definitions are
168
122
  # shared between ractors. Ractor objects are also shareable. All operations on
169
123
  # shareable objects are thread-safe, so the thread-safety property will be kept.
170
124
  # We can not define mutable shareable objects in Ruby, but C extensions can
@@ -189,7 +143,7 @@
189
143
  # puts "I can't see #{cls.tricky}"
190
144
  # cls.tricky = true # doesn't get here, but this would also raise an error
191
145
  # end
192
- # r.take
146
+ # r.join
193
147
  # # I see C
194
148
  # # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
195
149
  #
@@ -203,7 +157,7 @@
203
157
  # puts "GOOD=#{GOOD}"
204
158
  # puts "BAD=#{BAD}"
205
159
  # end
206
- # r.take
160
+ # r.join
207
161
  # # GOOD=good
208
162
  # # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError)
209
163
  #
@@ -213,7 +167,7 @@
213
167
  # puts "I see #{C}"
214
168
  # puts "I can't see #{C.tricky}"
215
169
  # end
216
- # r.take
170
+ # r.join
217
171
  # # I see C
218
172
  # # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
219
173
  #
@@ -229,7 +183,7 @@
229
183
  # a = 1
230
184
  # Thread.new {puts "Thread in ractor: a=#{a}"}.join
231
185
  # end
232
- # r.take
186
+ # r.join
233
187
  # # Here "Thread in ractor: a=1" will be printed
234
188
  #
235
189
  # ## Note on code examples
@@ -242,7 +196,7 @@
242
196
  # end
243
197
  #
244
198
  # It is **only for demonstration purposes** and shouldn't be used in a real
245
- # code. Most of the time, #take is used to wait for ractors to finish.
199
+ # code. Most of the time, #join is used to wait for ractors to finish.
246
200
  #
247
201
  # ## Reference
248
202
  #
@@ -280,10 +234,10 @@ class Ractor
280
234
  # Returns the number of Ractors currently running or blocking (waiting).
281
235
  #
282
236
  # Ractor.count #=> 1
283
- # r = Ractor.new(name: 'example') { Ractor.yield(1) }
237
+ # r = Ractor.new(name: 'example') { Ractor.receive }
284
238
  # Ractor.count #=> 2 (main + example ractor)
285
- # r.take # wait for Ractor.yield(1)
286
- # r.take # wait until r will finish
239
+ # r << 42 # r's Ractor.receive will resume
240
+ # r.join # wait for r's termination
287
241
  # Ractor.count #=> 1
288
242
  #
289
243
  def self.count: () -> Integer
@@ -363,7 +317,7 @@ class Ractor
363
317
  # `self` inside the block will refer to the current Ractor.
364
318
  #
365
319
  # r = Ractor.new { puts "Hi, I am #{self.inspect}" }
366
- # r.take
320
+ # r.join
367
321
  # # Prints "Hi, I am #<Ractor:#2 test.rb:1 running>"
368
322
  #
369
323
  # Any `args` passed are propagated to the block arguments by the same rules as
@@ -375,14 +329,14 @@ class Ractor
375
329
  # r = Ractor.new(arg) {|received_arg|
376
330
  # puts "Received: #{received_arg} (##{received_arg.object_id})"
377
331
  # }
378
- # r.take
332
+ # r.join
379
333
  # # Prints:
380
334
  # # Passing: [1, 2, 3] (#280)
381
335
  # # Received: [1, 2, 3] (#300)
382
336
  #
383
337
  # Ractor's `name` can be set for debugging purposes:
384
338
  #
385
- # r = Ractor.new(name: 'my ractor') {}; r.take
339
+ # r = Ractor.new(name: 'my ractor') {}; r.join
386
340
  # p r
387
341
  # #=> #<Ractor:#3 my ractor test.rb:1 terminated>
388
342
  #
@@ -390,128 +344,12 @@ class Ractor
390
344
 
391
345
  # <!--
392
346
  # rdoc-file=ractor.rb
393
- # - Ractor.receive -> msg
347
+ # - Ractor.receive -> obj
394
348
  # -->
395
- # Receive a message from the incoming port of the current ractor (which was sent
396
- # there by #send from another ractor).
397
- #
398
- # r = Ractor.new do
399
- # v1 = Ractor.receive
400
- # puts "Received: #{v1}"
401
- # end
402
- # r.send('message1')
403
- # r.take
404
- # # Here will be printed: "Received: message1"
405
- #
406
- # Alternatively, the private instance method `receive` may be used:
407
- #
408
- # r = Ractor.new do
409
- # v1 = receive
410
- # puts "Received: #{v1}"
411
- # end
412
- # r.send('message1')
413
- # r.take
414
- # # This prints: "Received: message1"
415
- #
416
- # The method blocks if the queue is empty.
417
- #
418
- # r = Ractor.new do
419
- # puts "Before first receive"
420
- # v1 = Ractor.receive
421
- # puts "Received: #{v1}"
422
- # v2 = Ractor.receive
423
- # puts "Received: #{v2}"
424
- # end
425
- # wait
426
- # puts "Still not received"
427
- # r.send('message1')
428
- # wait
429
- # puts "Still received only one"
430
- # r.send('message2')
431
- # r.take
432
- #
433
- # Output:
434
- #
435
- # Before first receive
436
- # Still not received
437
- # Received: message1
438
- # Still received only one
439
- # Received: message2
440
- #
441
- # If close_incoming was called on the ractor, the method raises
442
- # Ractor::ClosedError if there are no more messages in the incoming queue:
443
- #
444
- # Ractor.new do
445
- # close_incoming
446
- # receive
447
- # end
448
- # wait
449
- # # in `receive': The incoming port is already closed => #<Ractor:#2 test.rb:1 running> (Ractor::ClosedError)
349
+ # Receive a message from the default port.
450
350
  #
451
351
  def self.receive: () -> untyped
452
352
 
453
- # <!--
454
- # rdoc-file=ractor.rb
455
- # - Ractor.receive_if {|msg| block } -> msg
456
- # -->
457
- # Receive only a specific message.
458
- #
459
- # Instead of Ractor.receive, Ractor.receive_if can be given a pattern (or any
460
- # filter) in a block and you can choose the messages to accept that are
461
- # available in your ractor's incoming queue.
462
- #
463
- # r = Ractor.new do
464
- # p Ractor.receive_if{|msg| msg.match?(/foo/)} #=> "foo3"
465
- # p Ractor.receive_if{|msg| msg.match?(/bar/)} #=> "bar1"
466
- # p Ractor.receive_if{|msg| msg.match?(/baz/)} #=> "baz2"
467
- # end
468
- # r << "bar1"
469
- # r << "baz2"
470
- # r << "foo3"
471
- # r.take
472
- #
473
- # This will output:
474
- #
475
- # foo3
476
- # bar1
477
- # baz2
478
- #
479
- # If the block returns a truthy value, the message is removed from the incoming
480
- # queue and returned. Otherwise, the message remains in the incoming queue and
481
- # the next messages are checked by the given block.
482
- #
483
- # If there are no messages left in the incoming queue, the method will block
484
- # until new messages arrive.
485
- #
486
- # If the block is escaped by break/return/exception/throw, the message is
487
- # removed from the incoming queue as if a truthy value had been returned.
488
- #
489
- # r = Ractor.new do
490
- # val = Ractor.receive_if{|msg| msg.is_a?(Array)}
491
- # puts "Received successfully: #{val}"
492
- # end
493
- #
494
- # r.send(1)
495
- # r.send('test')
496
- # wait
497
- # puts "2 non-matching sent, nothing received"
498
- # r.send([1, 2, 3])
499
- # wait
500
- #
501
- # Prints:
502
- #
503
- # 2 non-matching sent, nothing received
504
- # Received successfully: [1, 2, 3]
505
- #
506
- # Note that you can not call receive/receive_if in the given block recursively.
507
- # You should not do any tasks in the block other than message filtration.
508
- #
509
- # Ractor.current << true
510
- # Ractor.receive_if{|msg| Ractor.receive}
511
- # #=> `receive': can not call receive/receive_if recursively (Ractor::Error)
512
- #
513
- def self.receive_if: () { (untyped) -> boolish } -> untyped
514
-
515
353
  # <!--
516
354
  # rdoc-file=ractor.rb
517
355
  # - recv()
@@ -521,57 +359,11 @@ class Ractor
521
359
 
522
360
  # <!--
523
361
  # rdoc-file=ractor.rb
524
- # - Ractor.select(*ractors, [yield_value:, move: false]) -> [ractor or symbol, obj]
362
+ # - Ractor.select(*ports) -> [...]
525
363
  # -->
526
- # Wait for any ractor to have something in its outgoing port, read from this
527
- # ractor, and then return that ractor and the object received.
528
- #
529
- # r1 = Ractor.new {Ractor.yield 'from 1'}
530
- # r2 = Ractor.new {Ractor.yield 'from 2'}
531
- #
532
- # r, obj = Ractor.select(r1, r2)
364
+ # TBD
533
365
  #
534
- # puts "received #{obj.inspect} from #{r.inspect}"
535
- # # Prints: received "from 1" from #<Ractor:#2 test.rb:1 running>
536
- # # But could just as well print "from r2" here, either prints could be first.
537
- #
538
- # If one of the given ractors is the current ractor, and it is selected, `r`
539
- # will contain the `:receive` symbol instead of the ractor object.
540
- #
541
- # r1 = Ractor.new(Ractor.current) do |main|
542
- # main.send 'to main'
543
- # Ractor.yield 'from 1'
544
- # end
545
- # r2 = Ractor.new do
546
- # Ractor.yield 'from 2'
547
- # end
548
- #
549
- # r, obj = Ractor.select(r1, r2, Ractor.current)
550
- # puts "received #{obj.inspect} from #{r.inspect}"
551
- # # Could print: received "to main" from :receive
552
- #
553
- # If `yield_value` is provided, that value may be yielded if another ractor is
554
- # calling #take. In this case, the pair `[:yield, nil]` is returned:
555
- #
556
- # r1 = Ractor.new(Ractor.current) do |main|
557
- # puts "Received from main: #{main.take}"
558
- # end
559
- #
560
- # puts "Trying to select"
561
- # r, obj = Ractor.select(r1, Ractor.current, yield_value: 123)
562
- # wait
563
- # puts "Received #{obj.inspect} from #{r.inspect}"
564
- #
565
- # This will print:
566
- #
567
- # Trying to select
568
- # Received from main: 123
569
- # Received nil from :yield
570
- #
571
- # `move` boolean flag defines whether yielded value will be copied (default) or
572
- # moved.
573
- #
574
- def self.select: (*Ractor ractors, ?move: boolish, ?yield_value: untyped) -> [ Ractor | Symbol, untyped ]
366
+ def self.select: (?) -> Array[untyped]
575
367
 
576
368
  # <!--
577
369
  # rdoc-file=ractor.rb
@@ -588,11 +380,41 @@ class Ractor
588
380
  #
589
381
  def self.shareable?: (untyped obj) -> bool
590
382
 
383
+ # <!--
384
+ # rdoc-file=ractor.rb
385
+ # - Ractor.sharable_proc(self: nil){} -> sharable proc
386
+ # -->
387
+ # It returns shareable Proc object. The Proc object is shareable and the self in
388
+ # a block will be replaced with the value passed via `self:` keyword.
389
+ #
390
+ # In a shareable Proc, you can not access to the outer variables.
391
+ #
392
+ # a = 42
393
+ # Ractor.shareable_proc{ p a }
394
+ # #=> can not isolate a Proc because it accesses outer variables (a). (ArgumentError)
395
+ #
396
+ # The `self` should be a sharable object
397
+ #
398
+ # Ractor.shareable_proc(self: self){}
399
+ # #=> self should be shareable: main (Ractor::IsolationError)
400
+ #
401
+ def self.shareable_proc: [T] () { (?) [self: nil] -> T } -> ^(?) [self: nil] -> T
402
+ | [T, S] (self: S) { (?) [self: S] -> T } -> ^(?) [self: S] -> T
403
+
404
+ # <!--
405
+ # rdoc-file=ractor.rb
406
+ # - Ractor.sharable_proc{} -> sharable proc
407
+ # -->
408
+ # Same as Ractor.sharable_proc, but returns lambda proc.
409
+ #
410
+ def self.shareable_lambda: [T] () { (?) [self: nil] -> T } -> ^(?) [self: nil] -> T
411
+ | [T, S] (self: S) { (?) [self: S] -> T } -> ^(?) [self: S] -> T
412
+
591
413
  # <!--
592
414
  # rdoc-file=ractor.rb
593
415
  # - Ractor.store_if_absent(key){ init_block }
594
416
  # -->
595
- # If the correponding value is not set, yield a value with init_block and store
417
+ # If the corresponding value is not set, yield a value with init_block and store
596
418
  # the value in thread-safe manner. This method returns corresponding stored
597
419
  # value.
598
420
  #
@@ -607,47 +429,7 @@ class Ractor
607
429
 
608
430
  # <!--
609
431
  # rdoc-file=ractor.rb
610
- # - Ractor.yield(msg, move: false) -> nil
611
- # -->
612
- # Send a message to the current ractor's outgoing port to be accepted by #take.
613
- #
614
- # r = Ractor.new {Ractor.yield 'Hello from ractor'}
615
- # puts r.take
616
- # # Prints: "Hello from ractor"
617
- #
618
- # This method is blocking, and will return only when somebody consumes the sent
619
- # message.
620
- #
621
- # r = Ractor.new do
622
- # Ractor.yield 'Hello from ractor'
623
- # puts "Ractor: after yield"
624
- # end
625
- # wait
626
- # puts "Still not taken"
627
- # puts r.take
628
- #
629
- # This will print:
630
- #
631
- # Still not taken
632
- # Hello from ractor
633
- # Ractor: after yield
634
- #
635
- # If the outgoing port was closed with #close_outgoing, the method will raise:
636
- #
637
- # r = Ractor.new do
638
- # close_outgoing
639
- # Ractor.yield 'Hello from ractor'
640
- # end
641
- # wait
642
- # # `yield': The outgoing-port is already closed (Ractor::ClosedError)
643
- #
644
- # The meaning of the `move` argument is the same as for #send.
645
- #
646
- def self.yield: (untyped obj, ?move: boolish) -> untyped
647
-
648
- # <!--
649
- # rdoc-file=ractor.rb
650
- # - <<(obj, move: false)
432
+ # - <<(...)
651
433
  # -->
652
434
  #
653
435
  alias << send
@@ -656,58 +438,50 @@ class Ractor
656
438
  # rdoc-file=ractor.rb
657
439
  # - [](sym)
658
440
  # -->
659
- # get a value from ractor-local storage of current Ractor Obsolete and use
441
+ # get a value from ractor-local storage for current Ractor Obsolete and use
660
442
  # Ractor.[] instead.
661
443
  #
444
+ %a{deprecated: Use Ractor.[] instead}
662
445
  def []: (interned sym) -> untyped
663
446
 
664
447
  # <!--
665
448
  # rdoc-file=ractor.rb
666
449
  # - []=(sym, val)
667
450
  # -->
668
- # set a value in ractor-local storage of current Ractor Obsolete and use
451
+ # set a value in ractor-local storage for current Ractor Obsolete and use
669
452
  # Ractor.[]= instead.
670
453
  #
454
+ %a{deprecated: Use Ractor.[]= instead}
671
455
  def []=: [T] (interned sym, T val) -> T
672
456
 
673
457
  # <!--
674
458
  # rdoc-file=ractor.rb
675
- # - ractor.close_incoming -> true | false
459
+ # - ractor.default_port -> port object
676
460
  # -->
677
- # Closes the incoming port and returns whether it was already closed. All
678
- # further attempts to Ractor.receive in the ractor, and #send to the ractor will
679
- # fail with Ractor::ClosedError.
680
- #
681
- # r = Ractor.new {sleep(500)}
682
- # r.close_incoming #=> false
683
- # r.close_incoming #=> true
684
- # r.send('test')
685
- # # Ractor::ClosedError (The incoming-port is already closed)
461
+ # return default port of the Ractor.
686
462
  #
687
- def close_incoming: () -> bool
463
+ def default_port: () -> Port[untyped]
688
464
 
689
465
  # <!--
690
466
  # rdoc-file=ractor.rb
691
- # - ractor.close_outgoing -> true | false
467
+ # - inspect()
692
468
  # -->
693
- # Closes the outgoing port and returns whether it was already closed. All
694
- # further attempts to Ractor.yield in the ractor, and #take from the ractor will
695
- # fail with Ractor::ClosedError.
696
469
  #
697
- # r = Ractor.new {sleep(500)}
698
- # r.close_outgoing #=> false
699
- # r.close_outgoing #=> true
700
- # r.take
701
- # # Ractor::ClosedError (The outgoing-port is already closed)
702
- #
703
- def close_outgoing: () -> bool
470
+ def inspect: () -> String
704
471
 
705
472
  # <!--
706
473
  # rdoc-file=ractor.rb
707
- # - inspect()
474
+ # - ractor.join -> self
708
475
  # -->
476
+ # Wait for the termination of the Ractor. If the Ractor was aborted (terminated
477
+ # with an exception), Ractor#value is called to raise an exception.
709
478
  #
710
- def inspect: () -> String
479
+ # Ractor.new{}.join #=> ractor
480
+ #
481
+ # Ractor.new{ raise "foo" }.join
482
+ # #=> raise an exception "foo (RuntimeError)"
483
+ #
484
+ def join: () -> self
711
485
 
712
486
  # <!--
713
487
  # rdoc-file=ractor.rb
@@ -719,162 +493,60 @@ class Ractor
719
493
 
720
494
  # <!--
721
495
  # rdoc-file=ractor.rb
722
- # - ractor.send(msg, move: false) -> self
496
+ # - ractor.monitor(port) -> self
723
497
  # -->
724
- # Send a message to a Ractor's incoming queue to be accepted by Ractor.receive.
725
- #
726
- # r = Ractor.new do
727
- # value = Ractor.receive
728
- # puts "Received #{value}"
729
- # end
730
- # r.send 'message'
731
- # # Prints: "Received: message"
732
- #
733
- # The method is non-blocking (will return immediately even if the ractor is not
734
- # ready to receive anything):
498
+ # Register port as a monitoring port. If the ractor terminated, the port
499
+ # received a Symbol object. :exited will be sent if the ractor terminated
500
+ # without an exception. :aborted will be sent if the ractor terminated with a
501
+ # exception.
735
502
  #
736
- # r = Ractor.new {sleep(5)}
737
- # r.send('test')
738
- # puts "Sent successfully"
739
- # # Prints: "Sent successfully" immediately
503
+ # r = Ractor.new{ some_task() }
504
+ # r.monitor(port = Ractor::Port.new)
505
+ # port.receive #=> :exited and r is terminated
740
506
  #
741
- # An attempt to send to a ractor which already finished its execution will raise
742
- # Ractor::ClosedError.
507
+ # r = Ractor.new{ raise "foo" }
508
+ # r.monitor(port = Ractor::Port.new)
509
+ # port.receive #=> :terminated and r is terminated with an exception "foo"
743
510
  #
744
- # r = Ractor.new {}
745
- # r.take
746
- # p r
747
- # # "#<Ractor:#6 (irb):23 terminated>"
748
- # r.send('test')
749
- # # Ractor::ClosedError (The incoming-port is already closed)
750
- #
751
- # If close_incoming was called on the ractor, the method also raises
752
- # Ractor::ClosedError.
753
- #
754
- # r = Ractor.new do
755
- # sleep(500)
756
- # receive
757
- # end
758
- # r.close_incoming
759
- # r.send('test')
760
- # # Ractor::ClosedError (The incoming-port is already closed)
761
- # # The error is raised immediately, not when the ractor tries to receive
762
- #
763
- # If the `obj` is unshareable, by default it will be copied into the receiving
764
- # ractor by deep cloning. If `move: true` is passed, the object is *moved* into
765
- # the receiving ractor and becomes inaccessible to the sender.
766
- #
767
- # r = Ractor.new {puts "Received: #{receive}"}
768
- # msg = 'message'
769
- # r.send(msg, move: true)
770
- # r.take
771
- # p msg
772
- #
773
- # This prints:
774
- #
775
- # Received: message
776
- # in `p': undefined method `inspect' for #<Ractor::MovedObject:0x000055c99b9b69b8>
777
- #
778
- # All references to the object and its parts will become invalid to the sender.
779
- #
780
- # r = Ractor.new {puts "Received: #{receive}"}
781
- # s = 'message'
782
- # ary = [s]
783
- # copy = ary.dup
784
- # r.send(ary, move: true)
785
- #
786
- # s.inspect
787
- # # Ractor::MovedError (can not send any methods to a moved object)
788
- # ary.class
789
- # # Ractor::MovedError (can not send any methods to a moved object)
790
- # copy.class
791
- # # => Array, it is different object
792
- # copy[0].inspect
793
- # # Ractor::MovedError (can not send any methods to a moved object)
794
- # # ...but its item was still a reference to `s`, which was moved
795
- #
796
- # If the object is shareable, `move: true` has no effect on it:
797
- #
798
- # r = Ractor.new {puts "Received: #{receive}"}
799
- # s = 'message'.freeze
800
- # r.send(s, move: true)
801
- # s.inspect #=> "message", still available
511
+ def monitor: [T < Symbol] (Port[T]) -> untyped
512
+
513
+ # <!--
514
+ # rdoc-file=ractor.rb
515
+ # - ractor.send(msg) -> self
516
+ # -->
517
+ # It is equivalent to default_port.send(msg)
802
518
  #
803
519
  def send: (untyped obj, ?move: boolish) -> Ractor
804
520
 
805
521
  # <!--
806
522
  # rdoc-file=ractor.rb
807
- # - ractor.take -> msg
523
+ # - to_s()
808
524
  # -->
809
- # Get a message from the ractor's outgoing port, which was put there by
810
- # Ractor.yield or at ractor's termination.
811
- #
812
- # r = Ractor.new do
813
- # Ractor.yield 'explicit yield'
814
- # 'last value'
815
- # end
816
- # puts r.take #=> 'explicit yield'
817
- # puts r.take #=> 'last value'
818
- # puts r.take # Ractor::ClosedError (The outgoing-port is already closed)
819
- #
820
- # The fact that the last value is also sent to the outgoing port means that
821
- # `take` can be used as an analog of Thread#join ("just wait until ractor
822
- # finishes"). However, it will raise if somebody has already consumed that
823
- # message.
824
- #
825
- # If the outgoing port was closed with #close_outgoing, the method will raise
826
- # Ractor::ClosedError.
827
525
  #
828
- # r = Ractor.new do
829
- # sleep(500)
830
- # Ractor.yield 'Hello from ractor'
831
- # end
832
- # r.close_outgoing
833
- # r.take
834
- # # Ractor::ClosedError (The outgoing-port is already closed)
835
- # # The error would be raised immediately, not when ractor will try to receive
836
- #
837
- # If an uncaught exception is raised in the Ractor, it is propagated by take as
838
- # a Ractor::RemoteError.
839
- #
840
- # r = Ractor.new {raise "Something weird happened"}
841
- #
842
- # begin
843
- # r.take
844
- # rescue => e
845
- # p e # => #<Ractor::RemoteError: thrown by remote Ractor.>
846
- # p e.ractor == r # => true
847
- # p e.cause # => #<RuntimeError: Something weird happened>
848
- # end
849
- #
850
- # Ractor::ClosedError is a descendant of StopIteration, so the termination of
851
- # the ractor will break out of any loops that receive this message without
852
- # propagating the error:
853
- #
854
- # r = Ractor.new do
855
- # 3.times {|i| Ractor.yield "message #{i}"}
856
- # "finishing"
857
- # end
858
- #
859
- # loop {puts "Received: " + r.take}
860
- # puts "Continue successfully"
861
- #
862
- # This will print:
863
- #
864
- # Received: message 0
865
- # Received: message 1
866
- # Received: message 2
867
- # Received: finishing
868
- # Continue successfully
526
+ alias to_s inspect
527
+
528
+ # <!--
529
+ # rdoc-file=ractor.rb
530
+ # - ractor.unmonitor(port) -> self
531
+ # -->
532
+ # Unregister port from the monitoring ports.
869
533
  #
870
- def take: () -> untyped
534
+ def unmonitor: (Port[untyped]) -> self
871
535
 
872
536
  # <!--
873
537
  # rdoc-file=ractor.rb
874
- # - to_s()
538
+ # - ractor.value -> obj
875
539
  # -->
540
+ # Waits for `ractor` to complete, using #join, and return its value or raise the
541
+ # exception which terminated the Ractor. The value will not be copied even if it
542
+ # is unshareable object. Therefore at most 1 Ractor can get a value.
876
543
  #
877
- alias to_s inspect
544
+ # r = Ractor.new{ [1, 2] }
545
+ # r.value #=> [1, 2] (unshareable object)
546
+ #
547
+ # Ractor.new(r){|r| r.value} #=> Ractor::Error
548
+ #
549
+ def value: () -> untyped
878
550
 
879
551
  private
880
552
 
@@ -938,9 +610,15 @@ class Ractor
938
610
  class ClosedError < StopIteration
939
611
  end
940
612
 
613
+ # <!-- rdoc-file=ractor.c -->
614
+ # The parent class of Ractor-related error classes.
615
+ #
941
616
  class Error < RuntimeError
942
617
  end
943
618
 
619
+ # <!-- rdoc-file=ractor.c -->
620
+ # Raised on attempt to make a Ractor-unshareable object Ractor-shareable.
621
+ #
944
622
  class IsolationError < Ractor::Error
945
623
  end
946
624
 
@@ -1037,6 +715,166 @@ class Ractor
1037
715
  def method_missing: (*untyped) -> untyped
1038
716
  end
1039
717
 
718
+ # <!-- rdoc-file=ractor.rb -->
719
+ # Port objects transmit messages between Ractors.
720
+ #
721
+ class Port[T = untyped]
722
+ # <!--
723
+ # rdoc-file=ractor.rb
724
+ # - <<(obj, move: false)
725
+ # -->
726
+ #
727
+ alias << send
728
+
729
+ # <!--
730
+ # rdoc-file=ractor.rb
731
+ # - port.close
732
+ # -->
733
+ # Close the port. On the closed port, sending is not prohibited. Receiving is
734
+ # also not allowed if there is no sent messages arrived before closing.
735
+ #
736
+ # port = Ractor::Port.new
737
+ # Ractor.new port do |port|
738
+ # port.send 1 # OK
739
+ # port.send 2 # OK
740
+ # port.close
741
+ # port.send 3 # raise Ractor::ClosedError
742
+ # end
743
+ #
744
+ # port.receive #=> 1
745
+ # port.receive #=> 2
746
+ # port.receive #=> raise Ractor::ClosedError
747
+ #
748
+ # Now, only a Ractor which creates the port is allowed to close ports.
749
+ #
750
+ # port = Ractor::Port.new
751
+ # Ractor.new port do |port|
752
+ # port.close #=> closing port by other ractors is not allowed (Ractor::Error)
753
+ # end.join
754
+ #
755
+ def close: () -> void
756
+
757
+ # <!--
758
+ # rdoc-file=ractor.rb
759
+ # - port.closed? -> true/false
760
+ # -->
761
+ # Return the port is closed or not.
762
+ #
763
+ def closed?: () -> bool
764
+
765
+ # <!--
766
+ # rdoc-file=ractor.rb
767
+ # - port.inspect -> string
768
+ # -->
769
+ #
770
+ def inspect: () -> String
771
+
772
+ # <!--
773
+ # rdoc-file=ractor.rb
774
+ # - port.receive -> msg
775
+ # -->
776
+ # Receive a message to the port (which was sent there by Port#send).
777
+ #
778
+ # port = Ractor::Port.new
779
+ # r = Ractor.new port do |port|
780
+ # port.send('message1')
781
+ # end
782
+ #
783
+ # v1 = port.receive
784
+ # puts "Received: #{v1}"
785
+ # r.join
786
+ # # Here will be printed: "Received: message1"
787
+ #
788
+ # The method blocks if the message queue is empty.
789
+ #
790
+ # port = Ractor::Port.new
791
+ # r = Ractor.new port do |port|
792
+ # wait
793
+ # puts "Still not received"
794
+ # port.send('message1')
795
+ # wait
796
+ # puts "Still received only one"
797
+ # port.send('message2')
798
+ # end
799
+ # puts "Before first receive"
800
+ # v1 = port.receive
801
+ # puts "Received: #{v1}"
802
+ # v2 = port.receive
803
+ # puts "Received: #{v2}"
804
+ # r.join
805
+ #
806
+ # Output:
807
+ #
808
+ # Before first receive
809
+ # Still not received
810
+ # Received: message1
811
+ # Still received only one
812
+ # Received: message2
813
+ #
814
+ # If close_incoming was called on the ractor, the method raises
815
+ # Ractor::ClosedError if there are no more messages in the message queue:
816
+ #
817
+ # port = Ractor::Port.new
818
+ # port.close
819
+ # port.receive #=> raise Ractor::ClosedError
820
+ #
821
+ def receive: () -> T
822
+
823
+ # <!--
824
+ # rdoc-file=ractor.rb
825
+ # - port.send(msg, move: false) -> self
826
+ # -->
827
+ # Send a message to a port to be accepted by port.receive.
828
+ #
829
+ # port = Ractor::Port.new
830
+ # r = Ractor.new do
831
+ # r.send 'message'
832
+ # end
833
+ # value = port.receive
834
+ # puts "Received #{value}"
835
+ # # Prints: "Received: message"
836
+ #
837
+ # The method is non-blocking (will return immediately even if the ractor is not
838
+ # ready to receive anything):
839
+ #
840
+ # port = Ractor::Port.new
841
+ # r = Ractor.new(port) do |port|
842
+ # port.send 'test'}
843
+ # puts "Sent successfully"
844
+ # # Prints: "Sent successfully" immediately
845
+ # end
846
+ #
847
+ # An attempt to send to a port which already closed its execution will raise
848
+ # Ractor::ClosedError.
849
+ #
850
+ # r = Ractor.new {Ractor::Port.new}
851
+ # r.join
852
+ # p r
853
+ # # "#<Ractor:#6 (irb):23 terminated>"
854
+ # port = r.value
855
+ # port.send('test') # raise Ractor::ClosedError
856
+ #
857
+ # If the `obj` is unshareable, by default it will be copied into the receiving
858
+ # ractor by deep cloning.
859
+ #
860
+ # If the object is shareable, it only send a reference to the object without
861
+ # cloning.
862
+ #
863
+ def send: (T obj, ?move: boolish) -> self
864
+
865
+ private
866
+
867
+ # <!--
868
+ # rdoc-file=ractor_sync.c
869
+ # - Ractor::Port.new -> new_port
870
+ # -->
871
+ # Returns a new Ractor::Port object.
872
+ #
873
+ def initialize: () -> void
874
+
875
+ def initialize_copy: (untyped) -> untyped
876
+ end
877
+
1040
878
  # <!-- rdoc-file=ractor.c -->
1041
879
  # Raised on attempt to Ractor#take if there was an uncaught exception in the
1042
880
  # Ractor. Its `cause` will contain the original exception, and `ractor` is the
@@ -1059,6 +897,9 @@ class Ractor
1059
897
  def ractor: () -> Ractor
1060
898
  end
1061
899
 
900
+ # <!-- rdoc-file=ractor.c -->
901
+ # Raised when Ractor-unsafe C-methods is invoked by a non-main Ractor.
902
+ #
1062
903
  class UnsafeError < Ractor::Error
1063
904
  end
1064
905