rbs 3.9.4 → 4.2.0

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 (354) hide show
  1. checksums.yaml +4 -4
  2. data/.clang-format +75 -0
  3. data/.clangd +2 -0
  4. data/.dockerignore +37 -0
  5. data/.gitattributes +1 -0
  6. data/.github/dependabot.yml +16 -14
  7. data/.github/workflows/bundle-update.yml +63 -0
  8. data/.github/workflows/c-check.yml +66 -0
  9. data/.github/workflows/changelog.yml +121 -0
  10. data/.github/workflows/comments.yml +6 -4
  11. data/.github/workflows/dependabot.yml +2 -2
  12. data/.github/workflows/jruby.yml +74 -0
  13. data/.github/workflows/release-gems.yml +234 -0
  14. data/.github/workflows/ruby.yml +86 -32
  15. data/.github/workflows/rust.yml +186 -0
  16. data/.github/workflows/truffleruby.yml +54 -0
  17. data/.github/workflows/typecheck.yml +6 -3
  18. data/.github/workflows/wasm.yml +55 -0
  19. data/.github/workflows/windows.yml +10 -4
  20. data/.gitignore +16 -0
  21. data/.rubocop.yml +1 -2
  22. data/CHANGELOG.md +502 -0
  23. data/Dockerfile.jruby +53 -0
  24. data/README.md +42 -5
  25. data/Rakefile +892 -111
  26. data/Steepfile +11 -0
  27. data/config.yml +665 -62
  28. data/core/array.rbs +541 -398
  29. data/core/basic_object.rbs +9 -8
  30. data/core/binding.rbs +0 -2
  31. data/core/builtin.rbs +9 -8
  32. data/core/class.rbs +11 -8
  33. data/core/comparable.rbs +55 -34
  34. data/core/complex.rbs +104 -78
  35. data/core/dir.rbs +61 -49
  36. data/core/encoding.rbs +12 -15
  37. data/core/enumerable.rbs +297 -196
  38. data/core/enumerator/arithmetic_sequence.rbs +70 -0
  39. data/core/enumerator/product.rbs +5 -5
  40. data/core/enumerator.rbs +91 -28
  41. data/core/errno.rbs +11 -2
  42. data/core/errors.rbs +58 -29
  43. data/core/exception.rbs +13 -13
  44. data/core/fiber.rbs +74 -54
  45. data/core/file.rbs +260 -1151
  46. data/core/file_constants.rbs +463 -0
  47. data/core/file_stat.rbs +534 -0
  48. data/core/file_test.rbs +3 -3
  49. data/core/float.rbs +257 -116
  50. data/core/gc.rbs +425 -281
  51. data/core/hash.rbs +1151 -829
  52. data/core/integer.rbs +156 -195
  53. data/core/io/buffer.rbs +53 -42
  54. data/core/io/wait.rbs +13 -35
  55. data/core/io.rbs +222 -155
  56. data/core/kernel.rbs +239 -163
  57. data/core/marshal.rbs +4 -4
  58. data/core/match_data.rbs +16 -14
  59. data/core/math.rbs +107 -66
  60. data/core/method.rbs +69 -33
  61. data/core/module.rbs +302 -150
  62. data/core/nil_class.rbs +7 -6
  63. data/core/numeric.rbs +77 -63
  64. data/core/object.rbs +9 -11
  65. data/core/object_space/weak_key_map.rbs +7 -7
  66. data/core/object_space.rbs +30 -23
  67. data/core/pathname.rbs +1312 -0
  68. data/core/proc.rbs +95 -58
  69. data/core/process.rbs +222 -202
  70. data/core/ractor.rbs +364 -518
  71. data/core/random.rbs +21 -3
  72. data/core/range.rbs +181 -79
  73. data/core/rational.rbs +60 -89
  74. data/core/rbs/ops.rbs +154 -0
  75. data/core/rbs/unnamed/argf.rbs +63 -56
  76. data/core/rbs/unnamed/env_class.rbs +19 -14
  77. data/core/rbs/unnamed/main_class.rbs +123 -0
  78. data/core/rbs/unnamed/random.rbs +11 -118
  79. data/core/regexp.rbs +258 -214
  80. data/core/ruby.rbs +53 -0
  81. data/core/ruby_vm.rbs +78 -34
  82. data/core/rubygems/config_file.rbs +5 -5
  83. data/core/rubygems/errors.rbs +6 -70
  84. data/core/rubygems/requirement.rbs +5 -15
  85. data/core/rubygems/rubygems.rbs +18 -81
  86. data/core/rubygems/specification.rbs +8 -0
  87. data/core/rubygems/version.rbs +2 -163
  88. data/core/set.rbs +493 -363
  89. data/core/signal.rbs +26 -16
  90. data/core/string.rbs +3234 -1285
  91. data/core/struct.rbs +43 -42
  92. data/core/symbol.rbs +41 -34
  93. data/core/thread.rbs +139 -83
  94. data/core/time.rbs +81 -50
  95. data/core/trace_point.rbs +41 -35
  96. data/core/true_class.rbs +2 -2
  97. data/core/unbound_method.rbs +24 -16
  98. data/core/warning.rbs +7 -7
  99. data/docs/CONTRIBUTING.md +3 -2
  100. data/docs/aliases.md +79 -0
  101. data/docs/collection.md +3 -3
  102. data/docs/config.md +171 -0
  103. data/docs/encoding.md +56 -0
  104. data/docs/gem.md +0 -1
  105. data/docs/inline.md +634 -0
  106. data/docs/rbs_by_example.md +20 -20
  107. data/docs/release.md +303 -0
  108. data/docs/rust.md +96 -0
  109. data/docs/sigs.md +3 -3
  110. data/docs/stdlib.md +8 -0
  111. data/docs/syntax.md +60 -18
  112. data/docs/type_fingerprint.md +21 -0
  113. data/docs/wasm_serialization.md +80 -0
  114. data/exe/rbs +1 -1
  115. data/ext/rbs_extension/ast_translation.c +1870 -0
  116. data/ext/rbs_extension/ast_translation.h +41 -0
  117. data/ext/rbs_extension/class_constants.c +189 -0
  118. data/{include/rbs/constants.h → ext/rbs_extension/class_constants.h} +24 -1
  119. data/ext/rbs_extension/compat.h +10 -0
  120. data/ext/rbs_extension/extconf.rb +26 -1
  121. data/ext/rbs_extension/legacy_location.c +299 -0
  122. data/ext/rbs_extension/legacy_location.h +82 -0
  123. data/ext/rbs_extension/main.c +639 -23
  124. data/ext/rbs_extension/rbs_extension.h +6 -21
  125. data/ext/rbs_extension/rbs_string_bridging.c +9 -0
  126. data/ext/rbs_extension/rbs_string_bridging.h +24 -0
  127. data/include/rbs/ast.h +1055 -0
  128. data/include/rbs/defines.h +104 -0
  129. data/include/rbs/lexer.h +208 -0
  130. data/include/rbs/location.h +40 -0
  131. data/include/rbs/parser.h +187 -0
  132. data/include/rbs/serialize.h +39 -0
  133. data/include/rbs/string.h +47 -0
  134. data/include/rbs/util/rbs_allocator.h +59 -0
  135. data/include/rbs/util/rbs_assert.h +20 -0
  136. data/include/rbs/util/rbs_buffer.h +83 -0
  137. data/include/rbs/util/rbs_constant_pool.h +6 -70
  138. data/include/rbs/util/rbs_encoding.h +282 -0
  139. data/include/rbs/util/rbs_unescape.h +24 -0
  140. data/include/rbs.h +9 -2
  141. data/lib/rbs/annotate/formatter.rb +3 -13
  142. data/lib/rbs/annotate/rdoc_annotator.rb +30 -32
  143. data/lib/rbs/annotate/rdoc_source.rb +1 -1
  144. data/lib/rbs/ast/annotation.rb +1 -1
  145. data/lib/rbs/ast/comment.rb +1 -1
  146. data/lib/rbs/ast/declarations.rb +11 -11
  147. data/lib/rbs/ast/members.rb +14 -14
  148. data/lib/rbs/ast/ruby/annotations.rb +451 -0
  149. data/lib/rbs/ast/ruby/comment_block.rb +247 -0
  150. data/lib/rbs/ast/ruby/declarations.rb +291 -0
  151. data/lib/rbs/ast/ruby/helpers/constant_helper.rb +28 -0
  152. data/lib/rbs/ast/ruby/helpers/location_helper.rb +15 -0
  153. data/lib/rbs/ast/ruby/members.rb +762 -0
  154. data/lib/rbs/ast/type_param.rb +25 -5
  155. data/lib/rbs/buffer.rb +142 -20
  156. data/lib/rbs/cli/diff.rb +16 -15
  157. data/lib/rbs/cli/validate.rb +63 -126
  158. data/lib/rbs/cli.rb +59 -29
  159. data/lib/rbs/collection/config/lockfile_generator.rb +28 -3
  160. data/lib/rbs/collection/sources/git.rb +7 -0
  161. data/lib/rbs/definition.rb +6 -1
  162. data/lib/rbs/definition_builder/ancestor_builder.rb +129 -70
  163. data/lib/rbs/definition_builder/method_builder.rb +74 -33
  164. data/lib/rbs/definition_builder.rb +181 -21
  165. data/lib/rbs/diff.rb +7 -1
  166. data/lib/rbs/environment/class_entry.rb +81 -0
  167. data/lib/rbs/environment/module_entry.rb +91 -0
  168. data/lib/rbs/environment.rb +410 -215
  169. data/lib/rbs/environment_loader.rb +2 -8
  170. data/lib/rbs/errors.rb +31 -21
  171. data/lib/rbs/inline_parser/comment_association.rb +117 -0
  172. data/lib/rbs/inline_parser.rb +568 -0
  173. data/lib/rbs/location_aux.rb +36 -4
  174. data/lib/rbs/locator.rb +5 -1
  175. data/lib/rbs/method_type.rb +5 -3
  176. data/lib/rbs/namespace.rb +47 -18
  177. data/lib/rbs/parser_aux.rb +37 -7
  178. data/lib/rbs/prototype/helpers.rb +24 -0
  179. data/lib/rbs/prototype/rb.rb +3 -28
  180. data/lib/rbs/prototype/rbi.rb +196 -45
  181. data/lib/rbs/prototype/runtime/value_object_generator.rb +0 -1
  182. data/lib/rbs/prototype/runtime.rb +13 -3
  183. data/lib/rbs/resolver/constant_resolver.rb +2 -2
  184. data/lib/rbs/resolver/type_name_resolver.rb +120 -44
  185. data/lib/rbs/rewriter.rb +70 -0
  186. data/lib/rbs/source.rb +99 -0
  187. data/lib/rbs/subtractor.rb +7 -4
  188. data/lib/rbs/test/type_check.rb +25 -3
  189. data/lib/rbs/type_name.rb +34 -21
  190. data/lib/rbs/types.rb +135 -81
  191. data/lib/rbs/unit_test/convertibles.rb +1 -0
  192. data/lib/rbs/unit_test/type_assertions.rb +47 -11
  193. data/lib/rbs/validator.rb +2 -2
  194. data/lib/rbs/version.rb +1 -1
  195. data/lib/rbs/wasm/deserializer.rb +213 -0
  196. data/lib/rbs/wasm/location.rb +61 -0
  197. data/lib/rbs/wasm/parser.rb +174 -0
  198. data/lib/rbs/wasm/runtime.rb +211 -0
  199. data/lib/rbs/wasm/serialization_schema.rb +111 -0
  200. data/lib/rbs.rb +25 -2
  201. data/lib/rbs_jars.rb +39 -0
  202. data/lib/rdoc/discover.rb +1 -1
  203. data/lib/rdoc_plugin/parser.rb +8 -3
  204. data/rbs.gemspec +34 -6
  205. data/schema/function.json +12 -1
  206. data/schema/typeParam.json +17 -1
  207. data/sig/ancestor_builder.rbs +1 -1
  208. data/sig/annotate/formatter.rbs +2 -2
  209. data/sig/annotate/rdoc_annotater.rbs +13 -10
  210. data/sig/ast/ruby/annotations.rbs +470 -0
  211. data/sig/ast/ruby/comment_block.rbs +127 -0
  212. data/sig/ast/ruby/declarations.rbs +158 -0
  213. data/sig/ast/ruby/helpers/constant_helper.rbs +11 -0
  214. data/sig/ast/ruby/helpers/location_helper.rbs +15 -0
  215. data/sig/ast/ruby/members.rbs +198 -0
  216. data/sig/buffer.rbs +81 -5
  217. data/sig/cli/diff.rbs +5 -11
  218. data/sig/cli/validate.rbs +12 -8
  219. data/sig/cli.rbs +18 -18
  220. data/sig/collection/config/lockfile_generator.rbs +2 -0
  221. data/sig/definition.rbs +6 -0
  222. data/sig/definition_builder.rbs +3 -1
  223. data/sig/environment/class_entry.rbs +56 -0
  224. data/sig/environment/module_entry.rbs +65 -0
  225. data/sig/environment.rbs +94 -87
  226. data/sig/errors.rbs +26 -20
  227. data/sig/inline_parser/comment_association.rbs +71 -0
  228. data/sig/inline_parser.rbs +126 -0
  229. data/sig/location.rbs +32 -7
  230. data/sig/locator.rbs +0 -2
  231. data/sig/manifest.yaml +0 -2
  232. data/sig/method_builder.rbs +9 -4
  233. data/sig/namespace.rbs +20 -5
  234. data/sig/parser.rbs +79 -15
  235. data/sig/prototype/helpers.rbs +2 -0
  236. data/sig/prototype/rbi.rbs +33 -4
  237. data/sig/resolver/type_name_resolver.rbs +36 -10
  238. data/sig/rewriter.rbs +45 -0
  239. data/sig/source.rbs +48 -0
  240. data/sig/type_param.rbs +13 -8
  241. data/sig/typename.rbs +15 -5
  242. data/sig/types.rbs +21 -9
  243. data/sig/unit_test/spy.rbs +0 -8
  244. data/sig/unit_test/type_assertions.rbs +17 -2
  245. data/sig/wasm/deserializer.rbs +66 -0
  246. data/sig/wasm/serialization_schema.rbs +13 -0
  247. data/src/ast.c +1644 -0
  248. data/src/lexer.c +3223 -0
  249. data/src/lexer.re +187 -0
  250. data/src/lexstate.c +222 -0
  251. data/src/location.c +31 -0
  252. data/src/parser.c +4318 -0
  253. data/src/serialize.c +965 -0
  254. data/src/string.c +41 -0
  255. data/src/util/rbs_allocator.c +171 -0
  256. data/src/util/rbs_assert.c +19 -0
  257. data/src/util/rbs_buffer.c +54 -0
  258. data/src/util/rbs_constant_pool.c +18 -92
  259. data/src/util/rbs_encoding.c +21454 -0
  260. data/src/util/rbs_unescape.c +167 -0
  261. data/stdlib/abbrev/0/array.rbs +1 -1
  262. data/stdlib/bigdecimal/0/big_decimal.rbs +116 -98
  263. data/stdlib/bigdecimal-math/0/big_math.rbs +169 -8
  264. data/stdlib/cgi/0/core.rbs +9 -393
  265. data/stdlib/cgi/0/manifest.yaml +1 -0
  266. data/stdlib/cgi-escape/0/escape.rbs +171 -0
  267. data/stdlib/coverage/0/coverage.rbs +7 -4
  268. data/stdlib/csv/0/csv.rbs +5 -5
  269. data/stdlib/date/0/date.rbs +92 -79
  270. data/stdlib/date/0/date_time.rbs +25 -24
  271. data/stdlib/delegate/0/delegator.rbs +11 -7
  272. data/stdlib/did_you_mean/0/did_you_mean.rbs +17 -16
  273. data/stdlib/digest/0/digest.rbs +117 -1
  274. data/stdlib/erb/0/erb.rbs +754 -353
  275. data/stdlib/etc/0/etc.rbs +73 -54
  276. data/stdlib/fileutils/0/fileutils.rbs +179 -160
  277. data/stdlib/forwardable/0/forwardable.rbs +13 -10
  278. data/stdlib/io-console/0/io-console.rbs +2 -2
  279. data/stdlib/ipaddr/0/ipaddr.rbs +0 -5
  280. data/stdlib/json/0/json.rbs +232 -185
  281. data/stdlib/monitor/0/monitor.rbs +9 -9
  282. data/stdlib/net-http/0/net-http.rbs +162 -134
  283. data/stdlib/objspace/0/objspace.rbs +17 -34
  284. data/stdlib/open-uri/0/open-uri.rbs +48 -8
  285. data/stdlib/open3/0/open3.rbs +469 -10
  286. data/stdlib/openssl/0/openssl.rbs +521 -397
  287. data/stdlib/optparse/0/optparse.rbs +26 -17
  288. data/stdlib/pathname/0/pathname.rbs +11 -1381
  289. data/stdlib/pp/0/pp.rbs +9 -8
  290. data/stdlib/prettyprint/0/prettyprint.rbs +7 -7
  291. data/stdlib/pstore/0/pstore.rbs +35 -30
  292. data/stdlib/psych/0/psych.rbs +65 -12
  293. data/stdlib/psych/0/store.rbs +2 -4
  294. data/stdlib/pty/0/pty.rbs +9 -6
  295. data/stdlib/random-formatter/0/random-formatter.rbs +277 -0
  296. data/stdlib/rdoc/0/code_object.rbs +4 -3
  297. data/stdlib/rdoc/0/comment.rbs +2 -0
  298. data/stdlib/rdoc/0/options.rbs +76 -0
  299. data/stdlib/rdoc/0/parser.rbs +1 -1
  300. data/stdlib/rdoc/0/rdoc.rbs +7 -5
  301. data/stdlib/rdoc/0/store.rbs +2 -2
  302. data/stdlib/resolv/0/resolv.rbs +26 -69
  303. data/stdlib/ripper/0/ripper.rbs +25 -19
  304. data/stdlib/securerandom/0/manifest.yaml +2 -0
  305. data/stdlib/securerandom/0/securerandom.rbs +7 -20
  306. data/stdlib/shellwords/0/shellwords.rbs +3 -3
  307. data/stdlib/singleton/0/singleton.rbs +6 -0
  308. data/stdlib/socket/0/addrinfo.rbs +9 -9
  309. data/stdlib/socket/0/basic_socket.rbs +3 -3
  310. data/stdlib/socket/0/ip_socket.rbs +10 -8
  311. data/stdlib/socket/0/socket.rbs +23 -10
  312. data/stdlib/socket/0/tcp_server.rbs +1 -1
  313. data/stdlib/socket/0/tcp_socket.rbs +11 -3
  314. data/stdlib/socket/0/udp_socket.rbs +1 -1
  315. data/stdlib/socket/0/unix_server.rbs +1 -1
  316. data/stdlib/stringio/0/stringio.rbs +1211 -96
  317. data/stdlib/strscan/0/string_scanner.rbs +101 -80
  318. data/stdlib/tempfile/0/manifest.yaml +3 -0
  319. data/stdlib/tempfile/0/tempfile.rbs +25 -21
  320. data/stdlib/time/0/time.rbs +8 -6
  321. data/stdlib/timeout/0/timeout.rbs +58 -7
  322. data/stdlib/tsort/0/cyclic.rbs +4 -1
  323. data/stdlib/tsort/0/interfaces.rbs +8 -8
  324. data/stdlib/tsort/0/tsort.rbs +16 -15
  325. data/stdlib/uri/0/common.rbs +42 -20
  326. data/stdlib/uri/0/file.rbs +3 -3
  327. data/stdlib/uri/0/generic.rbs +21 -18
  328. data/stdlib/uri/0/http.rbs +2 -2
  329. data/stdlib/uri/0/ldap.rbs +2 -2
  330. data/stdlib/uri/0/mailto.rbs +3 -3
  331. data/stdlib/uri/0/rfc2396_parser.rbs +12 -12
  332. data/stdlib/zlib/0/deflate.rbs +4 -3
  333. data/stdlib/zlib/0/gzip_file.rbs +1 -1
  334. data/stdlib/zlib/0/gzip_reader.rbs +8 -8
  335. data/stdlib/zlib/0/gzip_writer.rbs +16 -13
  336. data/stdlib/zlib/0/inflate.rbs +1 -1
  337. data/stdlib/zlib/0/need_dict.rbs +1 -1
  338. data/wasm/README.md +109 -0
  339. data/wasm/rbs_wasm.c +479 -0
  340. metadata +133 -19
  341. data/ext/rbs_extension/lexer.c +0 -2728
  342. data/ext/rbs_extension/lexer.h +0 -179
  343. data/ext/rbs_extension/lexer.re +0 -147
  344. data/ext/rbs_extension/lexstate.c +0 -175
  345. data/ext/rbs_extension/location.c +0 -325
  346. data/ext/rbs_extension/location.h +0 -85
  347. data/ext/rbs_extension/parser.c +0 -2982
  348. data/ext/rbs_extension/parser.h +0 -18
  349. data/ext/rbs_extension/parserstate.c +0 -411
  350. data/ext/rbs_extension/parserstate.h +0 -163
  351. data/ext/rbs_extension/unescape.c +0 -32
  352. data/include/rbs/ruby_objs.h +0 -72
  353. data/src/constants.c +0 -153
  354. data/src/ruby_objs.c +0 -799
@@ -107,14 +107,14 @@ end
107
107
  For now, it's safe to ignore them, but they're included for completeness.
108
108
 
109
109
  ```rbs
110
- class Array[Elem]
110
+ class Array[E]
111
111
  def *: (String) -> String
112
- | (Integer) -> Array[Elem]
112
+ | (Integer) -> Array[E]
113
113
  end
114
114
  ```
115
115
 
116
116
  `Array`'s `*` method, when given a `String` returns a `String`. When given an
117
- `Integer`, it returns an `Array` of the same contained type `Elem` (in our example case, `Elem` corresponds to `Integer`).
117
+ `Integer`, it returns an `Array` of the same contained type `E` (in our example case, `E` corresponds to `Integer`).
118
118
 
119
119
  ### Union types
120
120
 
@@ -150,9 +150,9 @@ end
150
150
  ```
151
151
 
152
152
  ```rbs
153
- class Enumerable[Elem]
154
- def first: () -> Elem?
155
- | (Integer) -> Array[Elem]
153
+ class Enumerable[E]
154
+ def first: () -> E?
155
+ | (Integer) -> Array[E]
156
156
  end
157
157
  ```
158
158
 
@@ -160,12 +160,12 @@ end
160
160
 
161
161
  When called with no arguments, the return value will either be an instance of
162
162
  whatever type is contained in the enumerable, or `nil`. We represent that with
163
- the type variable `Elem`, and the `?` suffix nilable marker.
163
+ the type variable `E`, and the `?` suffix nilable marker.
164
164
 
165
165
  When called with an `Integer` positional argument, the return value will be an
166
166
  `Array` of whatever type is contained.
167
167
 
168
- The `?` syntax is a convenient shorthand for a union with nil. An equivalent union type would be `(Elem | nil)`.
168
+ The `?` syntax is a convenient shorthand for a union with nil. An equivalent union type would be `(E | nil)`.
169
169
 
170
170
  ### Keyword Arguments
171
171
 
@@ -222,9 +222,9 @@ end
222
222
  ```
223
223
 
224
224
  ```rbs
225
- class Array[Elem]
226
- def filter: () { (Elem) -> boolish } -> ::Array[Elem]
227
- | () -> ::Enumerator[Elem, ::Array[Elem]]
225
+ class Array[E]
226
+ def filter: () { (E) -> boolish } -> ::Array[E]
227
+ | () -> ::Enumerator[E, ::Array[E]]
228
228
  end
229
229
  ```
230
230
 
@@ -264,13 +264,13 @@ a.collect.with_index {|x, i| x * i}
264
264
  ```
265
265
 
266
266
  ```rbs
267
- class Array[Elem]
268
- def collect: [U] () { (Elem) -> U } -> Array[U]
269
- | () -> Enumerator[Elem, Array[untyped]]
267
+ class Array[E]
268
+ def collect: [U] () { (E) -> U } -> Array[U]
269
+ | () -> Enumerator[E, Array[untyped]]
270
270
  end
271
271
  ```
272
272
 
273
- Type variables can also be introduced in methods. Here, in `Array`'s `#collect` method, we introduce a type variable `U`. The block passed to `#collect` will receive a parameter of type `Elem`, and return a value of type `U`. Then `#collect` will return an `Array` of type `U`.
273
+ Type variables can also be introduced in methods. Here, in `Array`'s `#collect` method, we introduce a type variable `U`. The block passed to `#collect` will receive a parameter of type `E`, and return a value of type `U`. Then `#collect` will return an `Array` of type `U`.
274
274
 
275
275
  In this example, the method receives its signature from the inferred return type of the passed block. When then block is absent, as in when the method returns an `Enumerator`, we can't infer the type, and so the return value of the enumerator can only be described as `Array[untyped]`.
276
276
 
@@ -284,9 +284,9 @@ In this example, the method receives its signature from the inferred return type
284
284
  ```
285
285
 
286
286
  ```rbs
287
- class Enumerable[Elem]
288
- def partition: () { (Elem) -> boolish } -> [Array[Elem], Array[Elem]]
289
- | () -> ::Enumerator[Elem, [Array[Elem], Array[Elem] ]]
287
+ class Enumerable[E]
288
+ def partition: () { (E) -> boolish } -> [Array[E], Array[E]]
289
+ | () -> ::Enumerator[E, [Array[E], Array[E] ]]
290
290
  end
291
291
  ```
292
292
 
@@ -300,9 +300,9 @@ Tuples can be of any size, and they can have mixed types.
300
300
  ```
301
301
 
302
302
  ```rbs
303
- class Enumerable[Elem]
303
+ class Enumerable[E]
304
304
  def to_h: () -> ::Hash[untyped, untyped]
305
- | [T, U] () { (Elem) -> [T, U] } -> ::Hash[T, U]
305
+ | [T, U] () { (E) -> [T, U] } -> ::Hash[T, U]
306
306
  end
307
307
  ```
308
308
 
data/docs/release.md ADDED
@@ -0,0 +1,303 @@
1
+ # Releasing RBS
2
+
3
+ A release is a pull request and one workflow run. Everything that leaves the
4
+ repository — the tag, both gems, and the GitHub release — is produced by the
5
+ `Release gems` workflow, so nothing has to be built or pushed from a laptop.
6
+
7
+ Each release ships **two gems**:
8
+
9
+ | Gem | Platform | Parser |
10
+ | --- | --- | --- |
11
+ | `rbs-X.Y.Z.gem` | `ruby` (MRI) | C extension, compiled on install |
12
+ | `rbs-X.Y.Z-java.gem` | `java` (JRuby) | `rbs_parser.wasm`, built by the workflow |
13
+
14
+ The `-java` gem contains no native code — just `rbs_parser.wasm`. The Chicory/ASM
15
+ jars it needs are not shipped in the gem; they are declared as `jar-dependencies`
16
+ requirements and fetched from Maven when the gem is installed. So the gem can be
17
+ built once in any environment and runs on every JRuby.
18
+
19
+ There are three kinds of release, and they differ in what gets written up:
20
+
21
+ | Version | CHANGELOG section | GitHub release |
22
+ | --- | --- | --- |
23
+ | `X.Y.Z` | The whole cycle since the previous release proper, prereleases included | Published |
24
+ | `X.Y.Z.pre.N` | What changed since `X.Y.Z.pre.N-1` | Published, marked as a prerelease |
25
+ | `X.Y.Z.dev.N` | None | None |
26
+
27
+ `.dev.N` releases are cut from the development line for people who need a change
28
+ early, so they are gems and tags and nothing else.
29
+
30
+ ## Prerequisites
31
+
32
+ Push rights to the `rbs` gem on RubyGems are **not** needed: the workflow
33
+ authenticates through a trusted publisher registered for this repository and
34
+ `release-gems.yml`. What is needed is write access to the repository, since that
35
+ is what lets you dispatch the workflow.
36
+
37
+ ## Steps
38
+
39
+ The release pull request in step 1 is merged by a person who has reviewed it. Its merge commit is
40
+ what step 2 dispatches, tags, and pushes to RubyGems, and none of that can be taken back — so
41
+ prepare that pull request and stop there, rather than merging it and carrying on to step 2.
42
+
43
+ The bump that starts a new minor is the only other pull request that sets `RBS::VERSION`. It
44
+ publishes nothing and another bump undoes it, so one opened on an explicit request can go through
45
+ on its own.
46
+
47
+ ### 1. Prepare the release
48
+
49
+ Open a pull request that carries everything the release needs:
50
+
51
+ - `lib/rbs/version.rb` — set `RBS::VERSION` to the version being released.
52
+ - `Gemfile.lock` — run `bundle install` after the bump; the lockfile records the version too.
53
+ - `CHANGELOG.md` — add a section for the new version, directly under the `# CHANGELOG` heading.
54
+ Sections are newest first.
55
+
56
+ Label the pull request `skip-changelog`. It carries no change of its own, and without the label it
57
+ shows up in the next release's list — that is why 4.1.0's changelog contains a `Version 4.1.0`
58
+ entry.
59
+
60
+ `rake gem:changelog` lists the pull requests merged since the last release, already formatted:
61
+
62
+ ```console
63
+ $ bundle exec rake gem:changelog | pbcopy
64
+ ```
65
+
66
+ Where it starts follows `RBS::VERSION`, so bump the version first: a prerelease starts from the
67
+ latest tag, and a release proper skips the prerelease tags and starts from the previous release
68
+ proper. Pass a version to override it (`rake 'gem:changelog[4.1.0]'`). Only the list goes to
69
+ STDOUT, so it pipes cleanly. Pull requests labeled `skip-changelog` are left out and reported on
70
+ STDERR, and pull requests that only touch `rust/` are left out because the crates have their own
71
+ release cycle.
72
+
73
+ On a release proper, the `X.Y.Z.pre.N` sections above the previous release are replaced by the one
74
+ section being written — their pull requests are in it, and the notes they were published with stay
75
+ on their own GitHub releases.
76
+
77
+ Sort the list into the sections below. `rake gem:changelog:json` prints the same pull requests with
78
+ the changed files, labels, and body of each, which is what the sorting is based on.
79
+
80
+ Both tasks reach GitHub through `gh`, which a Claude Code on the web session cannot do. See
81
+ [Assembling the changelog without `gh`](#assembling-the-changelog-without-gh), which runs them on a
82
+ runner instead.
83
+
84
+ ```markdown
85
+ ## X.Y.Z (YYYY-MM-DD)
86
+
87
+ ### Signature updates
88
+
89
+ ### Language updates
90
+
91
+ ### Library changes
92
+
93
+ #### rbs prototype
94
+
95
+ #### rbs collection
96
+
97
+ ### Miscellaneous
98
+ ```
99
+
100
+ The sections always appear in this order; delete the ones that end up empty, which is most of them
101
+ on a small release. Two things scale with the size of the release:
102
+
103
+ - **Summary paragraphs**, above the first section. A patch release usually has none, 4.1.0 has four
104
+ paragraphs, and 4.0.0 has nine. A prerelease has none whatever its size: the cycle it belongs to
105
+ is summarized once, on the release proper that folds it in.
106
+ - **A list of the types whose signatures changed**, as the first line of `### Signature updates`,
107
+ written as `**Updated classes/modules/methods:**` followed by the names in backticks. Used on
108
+ `X.Y.0` releases only.
109
+
110
+ The date is the day the gem is released, matching the `vX.Y.Z` tag — not the day this pull request
111
+ is opened. Fix it up before step 2 if the pull request sat for a few days.
112
+
113
+ ### 2. Run the `Release gems` workflow
114
+
115
+ Once the pull request is merged, dispatch
116
+ [`release-gems.yml`](../.github/workflows/release-gems.yml) from the Actions tab with two inputs:
117
+
118
+ | Input | Value |
119
+ | --- | --- |
120
+ | `commit` | The full 40-character SHA of the merge commit, taken from the merged pull request |
121
+ | `version` | `X.Y.Z`, without the leading `v` |
122
+
123
+ The ref selector picks which copy of the workflow file runs, not what gets released — leave it on
124
+ `master`. Everything is built from `commit`, so the run is unaffected by whatever lands on `master`
125
+ in the meantime, and a patch release cut from a release branch is dispatched the same way as any
126
+ other: the workflow does not care which branch the commit is on.
127
+
128
+ The two inputs say the same thing twice, once as a commit and once as a name, and the run stops
129
+ before anything is built unless they agree with each other and with the repository:
130
+
131
+ - `commit` has to be a full SHA that some branch contains,
132
+ - `version` has to be the `RBS::VERSION` that commit declares,
133
+ - CHANGELOG.md has to start with a section for `version` (skipped for `.dev.N`, which is not
134
+ written up),
135
+ - `vX.Y.Z` must not exist yet.
136
+
137
+ It then:
138
+
139
+ - builds `rbs-X.Y.Z.gem`,
140
+ - compiles `rbs_parser.wasm` and builds `rbs-X.Y.Z-java.gem`,
141
+ - checks both: platforms, the C extension on one and its absence on the other, and that the wasm
142
+ module made it into the `java` gem,
143
+ - installs the `java` gem on JRuby and parses with it, so the WebAssembly runtime is exercised
144
+ before anything is published,
145
+ - uploads both gems as an artifact,
146
+ - tags `commit` as `vX.Y.Z` and pushes the tag,
147
+ - pushes both gems to RubyGems through trusted publishing,
148
+ - publishes the GitHub release with the notes from CHANGELOG.md, skipping this last step for
149
+ `.dev.N` versions.
150
+
151
+ The tag is created once both gems are known to build and run, and before anything is published: a
152
+ tag can be deleted, while a version pushed to RubyGems can only be yanked.
153
+
154
+ Checking the `dry_run` box runs everything up to the artifact and stops — no tag, no gems pushed,
155
+ no release — which is how the build is exercised without releasing. `version` still has to match
156
+ the commit, so a dry run is also how a release is rehearsed before it is cut.
157
+
158
+ ## The version on `master`
159
+
160
+ `RBS::VERSION` on `master` is read one of two ways, told apart by how the version ends:
161
+
162
+ | On `master` | Means |
163
+ | --- | --- |
164
+ | `X.Y.0.dev` — a bare `.dev` | `X.Y.0` is being developed |
165
+ | A complete version — `X.Y.Z`, `X.Y.Z.pre.N`, `X.Y.Z.dev.N` | The version *after* the one named is being developed |
166
+
167
+ So `4.1.1` on `master` is not a claim that `master` is 4.1.1. It says 4.1.1 has shipped and what
168
+ comes after it is being worked on. `4.1.2.dev.1` says the same thing about itself: that release is
169
+ out, and the line continues towards 4.1.2.
170
+
171
+ Both become true the moment the release is tagged, so **nothing has to be done to `master` after a
172
+ release**. `4.0.1` was followed by `4.0.2` with no version change in between, and `4.1.2.dev.1` is
173
+ what `master` carries today.
174
+
175
+ The bare `X.Y.0.dev` is the exception because it is the one version that names a target rather than
176
+ a predecessor: a new minor is developed towards `X.Y.0` for a long time, before it is known whether
177
+ the next thing to ship is `X.Y.0.pre.1` or `X.Y.0` itself. Setting it is the only version change
178
+ that has to be made deliberately.
179
+
180
+ `rake gem:changelog` reads `RBS::VERSION` too, to decide where the next changelog starts — but the
181
+ version is set to the one being released before the changelog is generated, so it sees that rather
182
+ than whatever `master` was carrying.
183
+
184
+ ## Starting a new minor
185
+
186
+ `master` is the development line of one minor at a time. Moving it from `X.Y` to `X.(Y+1)` is not
187
+ part of any one release — it is the decision that the `X.Y` line is done, taken whenever that
188
+ becomes true — and it is the one moment the version on `master` is changed by hand. Two changes, in
189
+ opposite places:
190
+
191
+ 1. **Branch the line being left behind**, from the last `master` commit that belongs to it:
192
+
193
+ ```console
194
+ $ git switch --create aaa-X.Y.x <that commit>
195
+ $ git push -u origin aaa-X.Y.x
196
+ ```
197
+
198
+ Branch from the commit *before* the bump below, so the branch keeps the version its line was
199
+ released under. Patch releases of `X.Y` are cut from here from now on, with their changes
200
+ cherry-picked from `master` — see [Backports](#backports). The `aaa-` prefix carries no meaning
201
+ beyond sorting the release branches to the top of the branch list.
202
+
203
+ The branch carries its own release tooling, since that is read from the ref rather than from
204
+ `master`: the `gem:` tasks, and `changelog.yml` for the changelog. Branching from `master`
205
+ brings both along; what needs watching is a later change to either, which reaches this line
206
+ only if it is cherry-picked here too.
207
+
208
+ 2. **Bump `master`** to `X.(Y+1).0.dev`, in a pull request with `Gemfile.lock` regenerated and
209
+ labeled `skip-changelog` like the release pull request itself. `4.1` was started exactly this
210
+ way: `aaa-4.0.x` was branched at the commit before `Start 4.1 development`, which set
211
+ `RBS::VERSION` to `4.1.0.dev`.
212
+
213
+ Two loose ends that are easy to forget:
214
+
215
+ - **The release note of the new line.** `rake gem:gh_release` links every published release to
216
+ `https://github.com/ruby/rbs/wiki/Release-Note-X.Y`, built from the version number without
217
+ checking that the page is there. Nothing has to be written when the line starts — the page comes
218
+ together as the first release proper of the line comes into view — but it does have to exist by
219
+ the time that release is published, or its notes link to an empty page.
220
+ - **Release branches that are done.** A branch is worth keeping only while its line might still
221
+ get a patch. The ones that exist do not cover every line that ever had one — `3.8.1` shipped and
222
+ there is no `aaa-3.8.x` — so this is housekeeping rather than a rule, but starting a new minor is
223
+ the natural moment to look at the bottom of the branch list and delete what has been superseded.
224
+
225
+ ## Backports
226
+
227
+ A patch release is cut from a release branch (`aaa-X.Y.x`), and what it carries beyond the previous
228
+ release is cherry-picked from the development line. Cherry-pick with `-x`:
229
+
230
+ ```console
231
+ $ git cherry-pick -x <commit>
232
+ ```
233
+
234
+ `-x` records the commit the change was copied from, and that recorded line is what `rake
235
+ gem:changelog` follows to reach the pull request the change was written and reviewed in. Without
236
+ it, the only pull request a backported commit is associated with is the one that carried the
237
+ backport, which says nothing about the change and is the same for every commit it brought over —
238
+ that is why the 4.0.3 changelog credits its three entries to the same pull request.
239
+
240
+ The entry names that pull request and adds the one that carried the backport:
241
+
242
+ ```markdown
243
+ * {title} ([#{original}](https://github.com/ruby/rbs/pull/{original}), Backported in [#{backport}](https://github.com/ruby/rbs/pull/{backport}))
244
+ ```
245
+
246
+ `gem:changelog` prints this form on its own, from the same `-x` trailer: the origin it resolves is
247
+ the first link, and the pull request of the cherry-pick in front of it is the second. On the
248
+ development line nothing is a cherry-pick, so entries there keep the plain single link.
249
+
250
+ The second link is what keeps the entry from reading as a mistake. The original pull request is
251
+ against `master`, so it is listed again when the development line ships — and with nothing to tell
252
+ the two apart, the same link under two version headings looks like a change written into the wrong
253
+ section. #1923 is the pair to look at: plain under 3.6.0.pre.1, annotated under 3.5.2, which
254
+ backported it.
255
+
256
+ ## Assembling the changelog without `gh`
257
+
258
+ `gem:changelog` and `gem:changelog:json` reach GitHub through `gh`, so they cannot run from a
259
+ Claude Code on the web session. `api.github.com` refuses anything the shell does there, and the
260
+ refusal is keyed on the session rather than on the client, so installing `gh` does not help:
261
+
262
+ ```console
263
+ $ curl -s -o /dev/null -w '%{http_code}' https://api.github.com/repos/ruby/rbs
264
+ 403
265
+ ```
266
+
267
+ Nothing else about the release is affected. `gem:check_release` and `gem:tag` read git and the
268
+ working tree, `gem:gh_release` runs on a runner, and git itself reaches github.com normally —
269
+ clone, fetch and push all work.
270
+
271
+ So the task is run where it does work. Dispatch
272
+ [`changelog.yml`](../.github/workflows/changelog.yml), which runs it on a runner, and read the list
273
+ from the run summary, the log, or the `changelog` artifact.
274
+
275
+ | Input | Value |
276
+ | --- | --- |
277
+ | The ref selector | The branch the changelog is for: `aaa-X.Y.x` for a patch release, `master` otherwise |
278
+ | `version` | Where the changelog starts, when that should not follow `RBS::VERSION`. It names the release before the one being written, so `4.1.2` produces the 4.1.3 changelog |
279
+ | `format` | `list` for the template, `json` for the pull request details the sections are sorted from |
280
+
281
+ The ref is not incidental the way it is for `release-gems.yml`: it picks the history being
282
+ described *and* the copy of the task that describes it. So a release branch needs `changelog.yml`
283
+ on it, the same way it needs the release tasks — dispatching on a ref without the file fails with
284
+ `Workflow does not have 'workflow_dispatch' trigger`, since the trigger is read from the ref.
285
+
286
+ ## Notes
287
+
288
+ - Prereleases (`X.Y.Z.pre.N`) are only installed with `gem install rbs --pre`;
289
+ a plain `gem install rbs` is unaffected. On JRuby, `gem install rbs [--pre]`
290
+ resolves to the `-java` gem automatically.
291
+ - The WASI SDK version is pinned in `wasm.yml`, `jruby.yml`, `release-gems.yml`, and
292
+ `Dockerfile.jruby`, each carrying its own copy. Keep them in sync when bumping. The
293
+ Chicory/ASM versions are not duplicated: they are the `jar` requirements in
294
+ `rbs.gemspec`, which is where the workflow, `Dockerfile.jruby` and `gem install` all
295
+ read them from.
296
+ - `rake 'gem:check_release[X.Y.Z]'` and `rake gem:tag` are what the workflow runs to
297
+ check the release and to create the tag. Both work locally, which is the fallback
298
+ if the tag ever has to be created by hand.
299
+ - Those two tasks and `rake gem:gh_release` come from the Rakefile of the commit
300
+ being released, not from the branch the workflow was dispatched from. Releasing
301
+ from a release branch (`aaa-X.Y.x`) therefore needs the release tooling on that
302
+ branch as well; without it the run fails on the missing task, before publishing
303
+ anything.
data/docs/rust.md ADDED
@@ -0,0 +1,96 @@
1
+ # Rust Crates
2
+
3
+ RBS provides two Rust crates:
4
+
5
+ - **`ruby-rbs-sys`** -- Low-level FFI bindings to the RBS C parser
6
+ - **`ruby-rbs`** -- High-level safe Rust API for parsing RBS signatures
7
+
8
+ Both crates are published to [crates.io](https://crates.io/) and are developed within the `rust/` directory of this repository.
9
+
10
+ ## Vendored RBS Source
11
+
12
+ The Rust crates depend on the RBS C parser source code (`include/`, `src/`) and configuration (`config.yml`) from this repository. These files are vendored into each crate's `vendor/rbs/` directory, which is managed by Rake tasks and not tracked by git.
13
+
14
+ The file `rust/rbs_version` records which version of RBS the Rust crates are pinned to.
15
+
16
+ ## Setup
17
+
18
+ After cloning the repository, set up the vendored source before building the Rust crates:
19
+
20
+ ```bash
21
+ rake rust:rbs:sync # Uses the pinned version from rust/rbs_version
22
+ ```
23
+
24
+ Then build and test:
25
+
26
+ ```bash
27
+ cd rust
28
+ cargo test
29
+ ```
30
+
31
+ ## Rake Tasks
32
+
33
+ ### `rake rust:rbs:sync`
34
+
35
+ Copies the source files from the pinned version into each crate's `vendor/rbs/`. The copied files are made read-only to prevent accidental edits.
36
+
37
+ ### `rake rust:rbs:pin[VERSION]`
38
+
39
+ Records a git tag in `rust/rbs_version`. For example:
40
+
41
+ ```bash
42
+ rake rust:rbs:pin[v4.0.3]
43
+ ```
44
+
45
+ ### `rake rust:publish:ruby-rbs-sys` / `rake rust:publish:ruby-rbs`
46
+
47
+ Publishes each crate to crates.io individually. Each task:
48
+
49
+ 1. Verifies `rust/rbs_version` is set
50
+ 2. Verifies vendor directories contain real files (not symlinks)
51
+ 3. Verifies the git working tree is clean
52
+ 4. Creates a release branch and commits the vendor files
53
+ 5. Runs a dry-run to check packaging
54
+ 6. Publishes the crate
55
+
56
+ Set `RBS_RUST_PUBLISH_DRY_RUN=1` to only run the dry-run step and skip the actual publish to crates.io. This is used in CI to verify that the crates can be packaged correctly.
57
+
58
+ ### `rake rust:rbs:symlink`
59
+
60
+ If your development needs unreleased version of RBS source code, use `rake rust:rbs:symlink` to set up symlinks in vendor directories to refer the worktree source code. Changes to the C parser source are immediately reflected in Rust builds.
61
+
62
+ ## Publishing Workflow
63
+
64
+ 1. Pin the RBS version to release against:
65
+
66
+ ```bash
67
+ rake rust:rbs:pin[v4.0.3]
68
+ ```
69
+
70
+ 2. Sync the vendored source:
71
+
72
+ ```bash
73
+ rake rust:rbs:sync
74
+ ```
75
+
76
+ 3. Update crate versions in `rust/ruby-rbs-sys/Cargo.toml` and `rust/ruby-rbs/Cargo.toml`.
77
+
78
+ 4. Build and test:
79
+
80
+ ```bash
81
+ cd rust && cargo test
82
+ ```
83
+
84
+ 5. Commit the version changes and `rust/rbs_version`:
85
+
86
+ ```bash
87
+ git add rust/rbs_version rust/ruby-rbs-sys/Cargo.toml rust/ruby-rbs/Cargo.toml
88
+ git commit -m "Bump Rust crate versions"
89
+ ```
90
+
91
+ 6. Publish each crate:
92
+
93
+ ```bash
94
+ rake rust:publish:ruby-rbs-sys
95
+ rake rust:publish:ruby-rbs
96
+ ```
data/docs/sigs.md CHANGED
@@ -131,10 +131,10 @@ You may need to specify `-r` or `-I` to load signatures.
131
131
  The default is `-I sig`.
132
132
 
133
133
  ```shell
134
- RBS_TEST_OPT='-r pathname -I sig'
134
+ RBS_TEST_OPT='-r logger -I sig'
135
135
  ```
136
136
 
137
- Replacing `pathname` with the `stdlib` you want to include. For example, if you need to load `Set` and `BigDecimal` in `stdlib`, you would need to have `RBS_TEST_OPT='-r set -r bigdecimal -I sig'`
137
+ Replacing `logger` with the `stdlib` you want to include. For example, if you need to load `Set` and `BigDecimal` in `stdlib`, you would need to have `RBS_TEST_OPT='-r set -r bigdecimal -I sig'`
138
138
 
139
139
  `RBS_TEST_LOGLEVEL` can be used to configure log level. Defaults to `info`.
140
140
 
@@ -148,7 +148,7 @@ So, a typical command line to start the test would look like the following:
148
148
  $ RBS_TEST_LOGLEVEL=error \
149
149
  RBS_TEST_TARGET='Kaigi::*' \
150
150
  RBS_TEST_SKIP='Kaigi::MonkeyPatch' \
151
- RBS_TEST_OPT='-rset -rpathname -Isig -Iprivate' \
151
+ RBS_TEST_OPT='-rlogger -Isig -Iprivate' \
152
152
  RBS_TEST_RAISE=true \
153
153
  RUBYOPT='-rbundler/setup -rrbs/test/setup' \
154
154
  bundle exec rake test
data/docs/stdlib.md CHANGED
@@ -15,6 +15,14 @@ $ bundle exec rake 'generate:stdlib_test[String]'
15
15
  Created: test/stdlib/String_test.rb
16
16
  ```
17
17
 
18
+ Core signatures are loaded by default. To generate a test for a class defined in standard library signatures,
19
+ pass the paths containing those signatures and their dependencies after the class name.
20
+
21
+ ```console
22
+ $ bundle exec rake 'generate:stdlib_test[CSV::Row,stdlib/csv/0,stdlib/forwardable/0]'
23
+ Created: test/stdlib/CSV_Row_test.rb
24
+ ```
25
+
18
26
  It generates `test/stdlib/[class_name]_test.rb`.
19
27
  The test scripts would look like the following:
20
28
 
data/docs/syntax.md CHANGED
@@ -3,17 +3,17 @@
3
3
  ## Types
4
4
 
5
5
  ```markdown
6
- _type_ ::= _class-name_ _type-arguments_ (Class instance type)
7
- | _interface-name_ _type-arguments_ (Interface type)
8
- | _alias-name_ _type-arguments_ (Alias type)
9
- | `singleton(` _class-name_ `)` (Class singleton type)
10
- | _literal_ (Literal type)
11
- | _type_ `|` _type_ (Union type)
12
- | _type_ `&` _type_ (Intersection type)
13
- | _type_ `?` (Optional type)
14
- | `{` _record-name_ `:` _type_ `,` etc. `}` (Record type)
15
- | `[]` | `[` _type_ `,` etc. `]` (Tuples)
16
- | _type-variable_ (Type variables)
6
+ _type_ ::= _class-name_ _type-arguments_ (Class instance type)
7
+ | _interface-name_ _type-arguments_ (Interface type)
8
+ | _alias-name_ _type-arguments_ (Alias type)
9
+ | `singleton(` _class-name_ `)` _type-arguments_ (Class singleton type)
10
+ | _literal_ (Literal type)
11
+ | _type_ `|` _type_ (Union type)
12
+ | _type_ `&` _type_ (Intersection type)
13
+ | _type_ `?` (Optional type)
14
+ | `{` _record-name_ `:` _type_ `,` etc. `}` (Record type)
15
+ | `[]` | `[` _type_ `,` etc. `]` (Tuples)
16
+ | _type-variable_ (Type variables)
17
17
  | `self`
18
18
  | `instance`
19
19
  | `class`
@@ -48,6 +48,18 @@ _proc_ ::= `^` _parameters?_ _self-type-binding?_ _block?_ `->` _type_
48
48
  | `^` `(` `?` `)` `->` _type_ # Proc type with untyped parameter
49
49
  ```
50
50
 
51
+ `\w` above, and everywhere else in this document, is `[a-zA-Z0-9_]` together
52
+ with every character outside ASCII -- the same set Ruby takes into an
53
+ identifier. So `ServicioÚltimaVez` is a class name and `nombre_único` is an
54
+ alias name.
55
+
56
+ The leading character is the exception. RBS reads it to tell a class name from
57
+ an interface name from an alias name, so where it makes that distinction it has
58
+ to be ASCII: `class 日本語` is a class in Ruby but not a name RBS can write.
59
+ Nowhere else is restricted -- a method name, a variable name, an instance
60
+ variable name and a class variable name may all open with any character Ruby
61
+ accepts.
62
+
51
63
  ### Class instance type
52
64
 
53
65
  Class instance type denotes _an instance of a class_.
@@ -85,7 +97,8 @@ Class singleton type denotes _the type of a singleton object of a class_.
85
97
 
86
98
  ```rbs
87
99
  singleton(String)
88
- singleton(::Hash) # Class singleton type cannot be parametrized.
100
+ singleton(::Hash) # Class singleton type
101
+ singleton(Array)[String] # Class singleton type with type application
89
102
  ```
90
103
 
91
104
  ### Literal type
@@ -195,8 +208,8 @@ It is an alias of `top` type, and you can use `boolish` if we want to allow any
195
208
  We can see an example at the definition of `Enumerable#find`:
196
209
 
197
210
  ```rbs
198
- module Enumerable[Elem, Return]
199
- def find: () { (Elem) -> boolish } -> Elem?
211
+ module Enumerable[E, R]
212
+ def find: () { (E) -> boolish } -> E?
200
213
  end
201
214
  ```
202
215
 
@@ -650,7 +663,7 @@ _module-type-parameters_ ::= #
650
663
 
651
664
  Class declaration can have type parameters and superclass. When you omit superclass, `::Object` is assumed.
652
665
 
653
- * Super class arguments and generic class upperbounds are not *classish-context* nor *self-context*
666
+ * Super class arguments and generic class bounds are not *classish-context* nor *self-context*
654
667
 
655
668
  ### Module declaration
656
669
 
@@ -668,7 +681,7 @@ end
668
681
 
669
682
  The `Enumerable` module above requires `each` method for enumerating objects.
670
683
 
671
- * Self type arguments and generic class upperbounds are not *classish-context* nor *self-context*
684
+ * Self type arguments and generic class bounds are not *classish-context* nor *self-context*
672
685
 
673
686
  ### Class/module alias declaration
674
687
 
@@ -764,7 +777,8 @@ _module-type-parameter_ ::= _generics-unchecked_ _generics-variance_ _type-varia
764
777
  _method-type-param_ ::= _type-variable_ _generics-bound_
765
778
 
766
779
  _generics-bound_ ::= (No type bound)
767
- | `<` _type_ (The generics parameter is bounded)
780
+ | `<` _type_ (The generics parameter has an upper bound)
781
+ | '>' _type_ (The generics parameter has a lower bound)
768
782
 
769
783
  _default-type_ ::= (No default type)
770
784
  | `=` _type_ (The generics parameter has default type)
@@ -777,6 +791,9 @@ _generics-unchecked_ ::= (Empty)
777
791
  | `unchecked` (Skips variance annotation validation)
778
792
  ```
779
793
 
794
+ A type parameter can have both upper and lower bounds, which can be specified in either order:
795
+ `[T < UpperBound > LowerBound]` or `[T > LowerBound < UpperBound]`.
796
+
780
797
  RBS allows class/module/interface/type alias definitions and methods to be generic.
781
798
 
782
799
  ```rbs
@@ -834,13 +851,38 @@ class PrettyPrint[T < _Output]
834
851
  end
835
852
  ```
836
853
 
837
- If a type parameter has an upper bound, the type parameter must be instantiated with types that is a subtype of the upper bound.
854
+ If a type parameter has an upper bound, the type parameter must be instantiated with types that are a subtype of the upper bound.
838
855
 
839
856
  ```rbs
840
857
  type str_printer = PrettyPrint[String] # OK
841
858
  type int_printer = PrettyPrint[Integer] # Type error
842
859
  ```
843
860
 
861
+ If a type parameter has a lower bound, the type parameter must be instantiated with types that are a supertype of the lower bound.
862
+
863
+ ```rbs
864
+ class PrettyPrint[T > Numeric]
865
+ end
866
+
867
+ type obj_printer = PrettyPrint[Object] # OK
868
+ type int_printer = PrettyPrint[Integer] # Type error
869
+ ```
870
+
871
+ A type parameter can have both an upper and a lower bound, and these bounds can be specified in any order.
872
+
873
+ ```rbs
874
+ class FlexibleProcessor[T > Integer < Numeric]
875
+ # This class processes types T that are supertypes of Integer but also subtypes of Numeric.
876
+ # This includes Integer, Rational, Complex, Float, and Numeric itself.
877
+ def calculate: (T) -> T
878
+ end
879
+
880
+ type int_processor = FlexibleProcessor[Integer] # OK (Integer > Integer and Integer < Numeric)
881
+ type num_processor = FlexibleProcessor[Numeric] # OK (Numeric > Integer and Numeric < Numeric)
882
+ type obj_processor = FlexibleProcessor[Object] # Type error (Object is not < Numeric)
883
+ type str_processor = FlexibleProcessor[String] # Type error (String is not > Integer)
884
+ ```
885
+
844
886
  The generics type parameter of modules, classes, interfaces, or type aliases can have a default type.
845
887
 
846
888
  ```rbs