rbs 4.0.0.dev.4 → 4.0.0.dev.5

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 (223) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +14 -14
  3. data/.github/workflows/bundle-update.yml +60 -0
  4. data/.github/workflows/c-check.yml +11 -8
  5. data/.github/workflows/comments.yml +3 -3
  6. data/.github/workflows/dependabot.yml +1 -1
  7. data/.github/workflows/ruby.yml +17 -34
  8. data/.github/workflows/typecheck.yml +2 -2
  9. data/.github/workflows/valgrind.yml +42 -0
  10. data/.github/workflows/windows.yml +2 -2
  11. data/.rubocop.yml +1 -1
  12. data/README.md +1 -1
  13. data/Rakefile +32 -5
  14. data/config.yml +46 -0
  15. data/core/array.rbs +96 -46
  16. data/core/binding.rbs +0 -2
  17. data/core/builtin.rbs +2 -2
  18. data/core/comparable.rbs +13 -6
  19. data/core/complex.rbs +55 -41
  20. data/core/dir.rbs +4 -4
  21. data/core/encoding.rbs +7 -10
  22. data/core/enumerable.rbs +90 -3
  23. data/core/enumerator/arithmetic_sequence.rbs +70 -0
  24. data/core/enumerator.rbs +63 -1
  25. data/core/errno.rbs +8 -0
  26. data/core/errors.rbs +28 -1
  27. data/core/exception.rbs +2 -2
  28. data/core/fiber.rbs +40 -20
  29. data/core/file.rbs +108 -78
  30. data/core/file_test.rbs +1 -1
  31. data/core/float.rbs +225 -69
  32. data/core/gc.rbs +417 -281
  33. data/core/hash.rbs +1023 -727
  34. data/core/integer.rbs +104 -110
  35. data/core/io/buffer.rbs +21 -10
  36. data/core/io/wait.rbs +11 -33
  37. data/core/io.rbs +82 -19
  38. data/core/kernel.rbs +70 -59
  39. data/core/marshal.rbs +1 -1
  40. data/core/match_data.rbs +1 -1
  41. data/core/math.rbs +42 -3
  42. data/core/method.rbs +63 -27
  43. data/core/module.rbs +103 -26
  44. data/core/nil_class.rbs +3 -3
  45. data/core/numeric.rbs +43 -35
  46. data/core/object.rbs +3 -3
  47. data/core/object_space.rbs +21 -15
  48. data/core/pathname.rbs +1272 -0
  49. data/core/proc.rbs +30 -25
  50. data/core/process.rbs +4 -2
  51. data/core/ractor.rbs +361 -509
  52. data/core/random.rbs +17 -0
  53. data/core/range.rbs +113 -16
  54. data/core/rational.rbs +56 -85
  55. data/core/rbs/unnamed/argf.rbs +2 -2
  56. data/core/rbs/unnamed/env_class.rbs +1 -1
  57. data/core/rbs/unnamed/random.rbs +4 -113
  58. data/core/regexp.rbs +25 -20
  59. data/core/ruby.rbs +53 -0
  60. data/core/ruby_vm.rbs +6 -4
  61. data/core/rubygems/errors.rbs +3 -70
  62. data/core/rubygems/rubygems.rbs +11 -79
  63. data/core/rubygems/version.rbs +2 -3
  64. data/core/set.rbs +488 -359
  65. data/core/signal.rbs +24 -14
  66. data/core/string.rbs +3171 -1241
  67. data/core/struct.rbs +1 -1
  68. data/core/symbol.rbs +17 -11
  69. data/core/thread.rbs +95 -33
  70. data/core/time.rbs +35 -9
  71. data/core/trace_point.rbs +7 -4
  72. data/core/unbound_method.rbs +14 -6
  73. data/docs/aliases.md +79 -0
  74. data/docs/collection.md +2 -2
  75. data/docs/encoding.md +56 -0
  76. data/docs/gem.md +0 -1
  77. data/docs/inline.md +470 -0
  78. data/docs/sigs.md +3 -3
  79. data/docs/syntax.md +33 -4
  80. data/docs/type_fingerprint.md +21 -0
  81. data/exe/rbs +1 -1
  82. data/ext/rbs_extension/ast_translation.c +77 -3
  83. data/ext/rbs_extension/ast_translation.h +3 -0
  84. data/ext/rbs_extension/class_constants.c +8 -2
  85. data/ext/rbs_extension/class_constants.h +4 -0
  86. data/ext/rbs_extension/extconf.rb +5 -1
  87. data/ext/rbs_extension/legacy_location.c +5 -5
  88. data/ext/rbs_extension/main.c +37 -20
  89. data/include/rbs/ast.h +85 -38
  90. data/include/rbs/defines.h +27 -0
  91. data/include/rbs/lexer.h +30 -11
  92. data/include/rbs/parser.h +6 -6
  93. data/include/rbs/string.h +0 -2
  94. data/include/rbs/util/rbs_allocator.h +34 -13
  95. data/include/rbs/util/rbs_assert.h +12 -1
  96. data/include/rbs/util/rbs_encoding.h +2 -0
  97. data/include/rbs/util/rbs_unescape.h +2 -1
  98. data/lib/rbs/ast/annotation.rb +1 -1
  99. data/lib/rbs/ast/comment.rb +1 -1
  100. data/lib/rbs/ast/declarations.rb +10 -10
  101. data/lib/rbs/ast/members.rb +14 -14
  102. data/lib/rbs/ast/ruby/annotations.rb +137 -0
  103. data/lib/rbs/ast/ruby/comment_block.rb +24 -0
  104. data/lib/rbs/ast/ruby/declarations.rb +198 -3
  105. data/lib/rbs/ast/ruby/helpers/constant_helper.rb +4 -0
  106. data/lib/rbs/ast/ruby/members.rb +159 -1
  107. data/lib/rbs/ast/type_param.rb +24 -4
  108. data/lib/rbs/buffer.rb +20 -15
  109. data/lib/rbs/cli/diff.rb +16 -15
  110. data/lib/rbs/cli/validate.rb +38 -51
  111. data/lib/rbs/cli.rb +52 -19
  112. data/lib/rbs/collection/config/lockfile_generator.rb +8 -0
  113. data/lib/rbs/collection/sources/git.rb +1 -0
  114. data/lib/rbs/definition.rb +1 -1
  115. data/lib/rbs/definition_builder/ancestor_builder.rb +62 -9
  116. data/lib/rbs/definition_builder/method_builder.rb +20 -0
  117. data/lib/rbs/definition_builder.rb +91 -2
  118. data/lib/rbs/diff.rb +7 -1
  119. data/lib/rbs/environment.rb +227 -74
  120. data/lib/rbs/environment_loader.rb +0 -6
  121. data/lib/rbs/errors.rb +27 -7
  122. data/lib/rbs/inline_parser.rb +341 -5
  123. data/lib/rbs/location_aux.rb +1 -1
  124. data/lib/rbs/locator.rb +5 -1
  125. data/lib/rbs/method_type.rb +5 -3
  126. data/lib/rbs/parser_aux.rb +2 -2
  127. data/lib/rbs/prototype/rb.rb +2 -2
  128. data/lib/rbs/prototype/rbi.rb +2 -0
  129. data/lib/rbs/prototype/runtime.rb +8 -0
  130. data/lib/rbs/resolver/constant_resolver.rb +2 -2
  131. data/lib/rbs/resolver/type_name_resolver.rb +116 -38
  132. data/lib/rbs/subtractor.rb +3 -1
  133. data/lib/rbs/test/type_check.rb +16 -2
  134. data/lib/rbs/type_name.rb +1 -1
  135. data/lib/rbs/types.rb +27 -27
  136. data/lib/rbs/validator.rb +2 -2
  137. data/lib/rbs/version.rb +1 -1
  138. data/lib/rbs.rb +1 -1
  139. data/lib/rdoc/discover.rb +1 -1
  140. data/lib/rdoc_plugin/parser.rb +1 -1
  141. data/rbs.gemspec +3 -2
  142. data/schema/typeParam.json +17 -1
  143. data/sig/ast/ruby/annotations.rbs +124 -0
  144. data/sig/ast/ruby/comment_block.rbs +8 -0
  145. data/sig/ast/ruby/declarations.rbs +102 -4
  146. data/sig/ast/ruby/members.rbs +87 -1
  147. data/sig/cli/diff.rbs +5 -11
  148. data/sig/cli/validate.rbs +13 -4
  149. data/sig/cli.rbs +18 -18
  150. data/sig/definition.rbs +6 -1
  151. data/sig/environment.rbs +70 -12
  152. data/sig/errors.rbs +13 -6
  153. data/sig/inline_parser.rbs +39 -2
  154. data/sig/locator.rbs +0 -2
  155. data/sig/manifest.yaml +0 -1
  156. data/sig/method_builder.rbs +3 -1
  157. data/sig/method_types.rbs +1 -1
  158. data/sig/parser.rbs +16 -2
  159. data/sig/resolver/type_name_resolver.rbs +35 -7
  160. data/sig/source.rbs +3 -3
  161. data/sig/type_param.rbs +13 -8
  162. data/sig/types.rbs +4 -4
  163. data/src/ast.c +80 -1
  164. data/src/lexer.c +1392 -1313
  165. data/src/lexer.re +3 -0
  166. data/src/lexstate.c +58 -37
  167. data/src/location.c +4 -4
  168. data/src/parser.c +412 -145
  169. data/src/string.c +0 -48
  170. data/src/util/rbs_allocator.c +89 -71
  171. data/src/util/rbs_assert.c +1 -1
  172. data/src/util/rbs_buffer.c +2 -2
  173. data/src/util/rbs_constant_pool.c +10 -10
  174. data/src/util/rbs_encoding.c +4 -8
  175. data/src/util/rbs_unescape.c +56 -20
  176. data/stdlib/bigdecimal/0/big_decimal.rbs +100 -82
  177. data/stdlib/bigdecimal-math/0/big_math.rbs +169 -8
  178. data/stdlib/cgi/0/core.rbs +9 -393
  179. data/stdlib/cgi/0/manifest.yaml +1 -0
  180. data/stdlib/cgi-escape/0/escape.rbs +171 -0
  181. data/stdlib/coverage/0/coverage.rbs +3 -1
  182. data/stdlib/date/0/date.rbs +67 -59
  183. data/stdlib/date/0/date_time.rbs +1 -1
  184. data/stdlib/delegate/0/delegator.rbs +10 -7
  185. data/stdlib/digest/0/digest.rbs +110 -0
  186. data/stdlib/erb/0/erb.rbs +737 -347
  187. data/stdlib/fileutils/0/fileutils.rbs +20 -14
  188. data/stdlib/forwardable/0/forwardable.rbs +3 -0
  189. data/stdlib/json/0/json.rbs +82 -28
  190. data/stdlib/net-http/0/net-http.rbs +3 -0
  191. data/stdlib/objspace/0/objspace.rbs +9 -27
  192. data/stdlib/open-uri/0/open-uri.rbs +40 -0
  193. data/stdlib/open3/0/open3.rbs +459 -1
  194. data/stdlib/openssl/0/openssl.rbs +331 -228
  195. data/stdlib/optparse/0/optparse.rbs +8 -3
  196. data/stdlib/pathname/0/pathname.rbs +9 -1379
  197. data/stdlib/psych/0/psych.rbs +4 -4
  198. data/stdlib/random-formatter/0/random-formatter.rbs +277 -0
  199. data/stdlib/rdoc/0/code_object.rbs +2 -1
  200. data/stdlib/rdoc/0/parser.rbs +1 -1
  201. data/stdlib/rdoc/0/rdoc.rbs +1 -1
  202. data/stdlib/rdoc/0/store.rbs +1 -1
  203. data/stdlib/resolv/0/resolv.rbs +25 -68
  204. data/stdlib/ripper/0/ripper.rbs +2 -2
  205. data/stdlib/securerandom/0/manifest.yaml +2 -0
  206. data/stdlib/securerandom/0/securerandom.rbs +6 -19
  207. data/stdlib/singleton/0/singleton.rbs +3 -0
  208. data/stdlib/socket/0/socket.rbs +13 -1
  209. data/stdlib/socket/0/tcp_socket.rbs +10 -2
  210. data/stdlib/stringio/0/stringio.rbs +1176 -85
  211. data/stdlib/strscan/0/string_scanner.rbs +31 -31
  212. data/stdlib/tempfile/0/tempfile.rbs +3 -3
  213. data/stdlib/time/0/time.rbs +1 -1
  214. data/stdlib/timeout/0/timeout.rbs +63 -7
  215. data/stdlib/tsort/0/cyclic.rbs +3 -0
  216. data/stdlib/uri/0/common.rbs +16 -2
  217. data/stdlib/uri/0/file.rbs +1 -1
  218. data/stdlib/uri/0/generic.rbs +24 -16
  219. data/stdlib/uri/0/rfc2396_parser.rbs +6 -7
  220. data/stdlib/zlib/0/gzip_reader.rbs +2 -2
  221. data/stdlib/zlib/0/gzip_writer.rbs +1 -1
  222. data/stdlib/zlib/0/zstream.rbs +1 -0
  223. metadata +30 -4
data/docs/inline.md ADDED
@@ -0,0 +1,470 @@
1
+ # Inline RBS Type Declaration
2
+
3
+ Inline RBS type declarations allow you to write type annotations directly in your Ruby source files using comments. Instead of maintaining separate `.rbs` files, you can keep your type information alongside your Ruby code, making it easier to keep types and implementation in sync.
4
+
5
+ The following example defines `Calculator` class and `add` instance method. The `@rbs` comment gives the type of the `add` method with the RBS method type syntax.
6
+
7
+ ```ruby
8
+ class Calculator
9
+ # @rbs (Integer, Integer) -> Integer
10
+ def add(a, b)
11
+ a + b
12
+ end
13
+ end
14
+ ```
15
+
16
+ ## Classes
17
+
18
+ Inline RBS supports class definitions from your Ruby code. When you define a class in Ruby, the library recognizes it and the corresponding class definition is generated in RBS.
19
+
20
+ ```ruby
21
+ class App
22
+ end
23
+ ```
24
+
25
+ The `::App` class is defined in RBS and you can use it as a type.
26
+
27
+ ### Non-constant class paths
28
+
29
+ Only classes with constant names are imported. Dynamic or non-constant class definitions are ignored:
30
+
31
+ ```ruby
32
+ # This class is imported
33
+ class MyClass
34
+ end
35
+
36
+ # This is ignored - dynamic class definition
37
+ MyClass = Class.new do
38
+ end
39
+
40
+ # This is also ignored - non-constant class name
41
+ object = Object
42
+ class object::MyClass
43
+ end
44
+ ```
45
+
46
+ ### Class Nesting
47
+
48
+ Nested classes work as expected:
49
+
50
+ ```ruby
51
+ class Client
52
+ class Error
53
+ end
54
+ end
55
+ ```
56
+
57
+ This creates the types `::Client` and `::Client::Error`.
58
+
59
+ ### Inheritance
60
+
61
+ Class declarations can have a super class.
62
+
63
+ ```ruby
64
+ class UsersController < ApplicationController
65
+ end
66
+ ```
67
+
68
+ The super class specification must be a constant.
69
+
70
+ The super class specification allows type applications.
71
+
72
+ ```ruby
73
+ class StringArray < Array #[String]
74
+ end
75
+ ```
76
+
77
+ ### Current Limitations
78
+
79
+ - Generic class definitions are not supported
80
+
81
+ ## Modules
82
+
83
+ Inline RBS supports module definitions from your Ruby code. When you define a module in Ruby, the library recognizes it and the corresponding module definition is generated in RBS.
84
+
85
+ ```ruby
86
+ module Helper
87
+ end
88
+ ```
89
+
90
+ The `::Helper` module is defined in RBS and you can use it as a type.
91
+
92
+ ### Non-constant module paths
93
+
94
+ Only modules with constant names are imported. Dynamic or non-constant module definitions are ignored:
95
+
96
+ ```ruby
97
+ # This module is imported
98
+ module MyModule
99
+ end
100
+
101
+ # This is ignored - dynamic module definition
102
+ MyModule = Module.new do
103
+ end
104
+
105
+ # This is also ignored - non-constant module name
106
+ object = Object
107
+ module object::MyModule
108
+ end
109
+ ```
110
+
111
+ ### Module Nesting
112
+
113
+ Nested modules work as expected:
114
+
115
+ ```ruby
116
+ module API
117
+ module V1
118
+ module Resources
119
+ end
120
+ end
121
+ end
122
+ ```
123
+
124
+ This creates the types `::API`, `::API::V1`, and `::API::V1::Resources`.
125
+
126
+ ### Current Limitations
127
+
128
+ - Generic module definitions are not supported
129
+ - Module self-type constraints are not supported
130
+
131
+ ## Method Definitions
132
+
133
+ Inline RBS supports methods defined using the `def` syntax in Ruby.
134
+
135
+ ```ruby
136
+ class Calculator
137
+ def add(x, y) = x+y
138
+ end
139
+ ```
140
+
141
+ It detects method definitions and allows you to add annotation comments to describe their types.
142
+
143
+ ### Unannotated method definition
144
+
145
+ Methods defined with `def` syntax are detected, but they are untyped.
146
+
147
+ ```ruby
148
+ class Calculator
149
+ def add(x, y) = x+y
150
+ end
151
+ ```
152
+
153
+ The type of the `Calculator#add` method is `(?) -> untyped` -- it accepts any arguments without type checking and returns an `untyped` object.
154
+
155
+ ### Method type annotation syntax
156
+
157
+ You can define the type of the method using `@rbs` and `:` syntax.
158
+
159
+ ```ruby
160
+ class Calculator
161
+ # @rbs (Integer, Integer) -> Integer
162
+ def add(x, y) = x + y
163
+
164
+ #: (Integer, Integer) -> Integer
165
+ def subtract(x, y) = x - y
166
+ end
167
+ ```
168
+
169
+ The type of both methods is `(Integer, Integer) -> Integer` -- they take two `Integer` objects and return an `Integer` object.
170
+
171
+ Both syntaxes support method overloading:
172
+
173
+ ```ruby
174
+ class Calculator
175
+ # @rbs (Integer, Integer) -> Integer
176
+ # | (Float, Float) -> Float
177
+ def add(x, y) = x + y
178
+
179
+ #: (Integer, Integer) -> Integer
180
+ #: (Float, Float) -> Float
181
+ def subtract(x, y) = x - y
182
+ end
183
+ ```
184
+
185
+ The type of both methods is `(Integer, Integer) -> Integer | (Float, Float) -> Float`.
186
+
187
+ > [!NOTE]
188
+ > The `@rbs METHOD-TYPE` syntax allows overloads with the `|` operator, just like in RBS files.
189
+ > Multiple `: METHOD-TYPE` declarations are required for overloads.
190
+
191
+ #### Doc-style syntax
192
+
193
+ The `@rbs return: T` syntax declares the return type of a method:
194
+
195
+ ```ruby
196
+ class Calculator
197
+ # @rbs return: String
198
+ def to_s
199
+ "Calculator"
200
+ end
201
+ end
202
+ ```
203
+
204
+ ### Current Limitations
205
+
206
+ - Class methods and singleton methods are not supported
207
+ - Parameter types are not supported with doc-style syntax
208
+ - Method visibility declaration is not supported yet
209
+
210
+ ## Attributes
211
+
212
+ Inline RBS supports Ruby's attribute methods: `attr_reader`, `attr_writer`, and `attr_accessor`.
213
+
214
+ ```ruby
215
+ class Person
216
+ attr_reader :name #: String
217
+ attr_writer :age #: Integer
218
+ attr_accessor :email #: String?
219
+ end
220
+ ```
221
+
222
+ It detects these attribute declarations and generates the corresponding getter and setter methods.
223
+
224
+ The accessor methods and instance variables are defined.
225
+
226
+ ### Unannotated attributes
227
+
228
+ Attributes defined without type annotations are treated as `untyped`:
229
+
230
+ ```ruby
231
+ class Person
232
+ attr_reader :name
233
+ attr_writer :age
234
+ attr_accessor :email
235
+ end
236
+ ```
237
+
238
+ ### Type annotations for attributes
239
+
240
+ You can add type annotations to attributes using the `#:` syntax in trailing comments:
241
+
242
+ ```ruby
243
+ class Person
244
+ attr_reader :name #: String
245
+ attr_writer :age #: Integer
246
+ attr_accessor :email #: String?
247
+ end
248
+ ```
249
+
250
+ This generates the following typed methods:
251
+ - `name: () -> String`
252
+ - `age=: (Integer) -> Integer`
253
+ - `email: () -> String?` and `email=: (String?) -> String?`
254
+
255
+ ### Multiple attributes
256
+
257
+ When declaring multiple attributes in one line, the type annotation applies to all attributes:
258
+
259
+ ```ruby
260
+ class Person
261
+ attr_reader :first_name, :last_name #: String
262
+ attr_accessor :age, :height #: Integer
263
+ end
264
+ ```
265
+
266
+ All attributes in each declaration share the same type.
267
+
268
+ ### Non-symbol attribute names
269
+
270
+ Attribute names must be symbol literals.
271
+
272
+ ```ruby
273
+ class Person
274
+ attr_reader "name" #: String
275
+
276
+ age = :age
277
+ attr_writer age #: Integer
278
+ end
279
+ ```
280
+
281
+ The attribute definitions are ignored because the names are given by string literals and local variables.
282
+
283
+ ### Current Limitations
284
+
285
+ - Attribute visibility is not supported yet. All attributes are _public_
286
+
287
+ ## Mixin
288
+
289
+ Inline RBS supports Ruby's mixin methods: `include`, `extend`, and `prepend`.
290
+
291
+ ```ruby
292
+ module Printable
293
+ # @rbs () -> String
294
+ def to_print
295
+ to_s
296
+ end
297
+ end
298
+
299
+ class Document
300
+ include Printable
301
+ extend Enumerable #[String]
302
+ prepend Trackable
303
+ end
304
+ ```
305
+
306
+ It detects these mixin declarations and adds them to the class or module definition.
307
+
308
+ ### Basic mixin usage
309
+
310
+ Mixins work just like in regular RBS files:
311
+
312
+ ```ruby
313
+ module Helper
314
+ end
315
+
316
+ class MyClass
317
+ include Helper
318
+ extend Helper
319
+ prepend Helper
320
+ end
321
+ ```
322
+
323
+ ### Type arguments for generic modules
324
+
325
+ You can specify type arguments for generic modules using the `#[...]` syntax:
326
+
327
+ ```ruby
328
+ class TodoList
329
+ include Enumerable #[String]
330
+
331
+ # @rbs () { (String) -> void } -> void
332
+ def each(&block)
333
+ @items.each(&block)
334
+ end
335
+ end
336
+ ```
337
+
338
+ ### Module name requirements
339
+
340
+ Only constant module names are supported. Dynamic module references are not allowed:
341
+
342
+ ```ruby
343
+ class MyClass
344
+ include Helper # ✓ Works - constant name
345
+
346
+ mod = Helper
347
+ include mod # ✗ Ignored - non-constant module reference
348
+
349
+ include Helper.new # ✗ Ignored - not a simple constant
350
+ end
351
+ ```
352
+
353
+ ### Module name resolution
354
+
355
+ The module name resolution is based on the nesting of the class/module definitions, unlike Ruby.
356
+
357
+ Modules accessible through ancestors (super-class/included modules) are not supported.
358
+
359
+ ### Current Limitations
360
+
361
+ - Only single module arguments are supported (no `include A, B` syntax)
362
+ - Module names must be constants
363
+
364
+ ## Instance Variables
365
+
366
+ Inline RBS declaration allows defining instance variables.
367
+
368
+ ```ruby
369
+ class Person
370
+ # @rbs @name: String
371
+ # @rbs @age: Integer? --
372
+ # how old is the person?
373
+ # `nil` means it's unspecified.
374
+
375
+ # @rbs (String name, Integer? age) -> void
376
+ def initialize(name, age)
377
+ @name = name
378
+ @age = age
379
+ end
380
+ end
381
+ ```
382
+
383
+ The `@rbs @VAR-NAME: TYPE` syntax enclosed in `class`/`module` syntax declares instance variables.
384
+ You can add the documentation of the variable followed by two hyphones (`--`).
385
+
386
+ Instance variable declarations must be under the `class`/`module` syntax, and they are ignored if written inside method definitions.
387
+
388
+ ### Current Limitations
389
+
390
+ - Only instance variables of class/module instances are allowed
391
+
392
+ ## Constants
393
+
394
+ Constants are supported by inline RBS declaration.
395
+
396
+ ```ruby
397
+ Foo = 123
398
+
399
+ module Bar
400
+ Baz = [1, ""] #: [Integer, String]
401
+ end
402
+
403
+ # Version of the library
404
+ #
405
+ VERSION = "1.2.3".freeze #: String
406
+ ```
407
+
408
+ ### Type Inference for Literal Constants
409
+
410
+ The types of constants may be automatically inferred when the right-hand side consists of literals:
411
+
412
+ - **Integers**: `COUNT = 42` → `Integer`
413
+ - **Floats**: `RATE = 3.14` → `Float`
414
+ - **Booleans**: `ENABLED = true` → `bool`
415
+ - **Strings**: `NAME = "test"` → `String`
416
+ - **Symbols**: `STATUS = :ready` → `:ready`
417
+
418
+ ```ruby
419
+ MAX_SIZE = 100 # Inferred as Integer
420
+ PI = 3.14159 # Inferred as Float
421
+ DEBUG = false # Inferred as bool
422
+ APP_NAME = "MyApp" # Inferred as String
423
+ DEFAULT_MODE = :strict # Inferred as :strict
424
+ ```
425
+
426
+ ### Explicit Type Annotations
427
+
428
+ For more complex types or when you want to override inference, use the `#:` syntax:
429
+
430
+ ```ruby
431
+ ITEMS = [1, "hello"] #: [Integer, String]
432
+ CONFIG = { name: "app", version: 1 } #: { name: String, version: Integer }
433
+ CALLBACK = -> { puts "done" } #: ^() -> void
434
+ ```
435
+
436
+ ### Documentation Comments
437
+
438
+ Comments above constant declarations become part of the constant's documentation:
439
+
440
+ ```ruby
441
+ # The maximum number of retries allowed
442
+ # before giving up on the operation
443
+ MAX_RETRIES = 3
444
+
445
+ # Application configuration loaded from environment
446
+ #
447
+ # This hash contains all the runtime configuration
448
+ # settings for the application.
449
+ CONFIG = load_config() #: Hash[String, untyped]
450
+ ```
451
+
452
+ ## Class/module Aliases
453
+
454
+ Class and module aliases can be defined by assigning existing classes or modules to constants using the `#: class-alias` or `#: module-alias` syntax.
455
+
456
+ ```ruby
457
+ MyObject = Object #: class-alias
458
+
459
+ MyKernel = Kernel #: module-alias
460
+ ```
461
+
462
+ This creates new type names that refer to the same class or module as the original.
463
+
464
+ The annotations can have optional type name to specify the class/module name, for the case it cannot be infered through the right-hand-side of the constant declaration.
465
+
466
+ ```ruby
467
+ MyObject = object #: class-alias Object
468
+
469
+ MyKernel = kernel #: module-alias Kernel
470
+ ```
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/syntax.md CHANGED
@@ -650,7 +650,7 @@ _module-type-parameters_ ::= #
650
650
 
651
651
  Class declaration can have type parameters and superclass. When you omit superclass, `::Object` is assumed.
652
652
 
653
- * Super class arguments and generic class upperbounds are not *classish-context* nor *self-context*
653
+ * Super class arguments and generic class bounds are not *classish-context* nor *self-context*
654
654
 
655
655
  ### Module declaration
656
656
 
@@ -668,7 +668,7 @@ end
668
668
 
669
669
  The `Enumerable` module above requires `each` method for enumerating objects.
670
670
 
671
- * Self type arguments and generic class upperbounds are not *classish-context* nor *self-context*
671
+ * Self type arguments and generic class bounds are not *classish-context* nor *self-context*
672
672
 
673
673
  ### Class/module alias declaration
674
674
 
@@ -764,7 +764,8 @@ _module-type-parameter_ ::= _generics-unchecked_ _generics-variance_ _type-varia
764
764
  _method-type-param_ ::= _type-variable_ _generics-bound_
765
765
 
766
766
  _generics-bound_ ::= (No type bound)
767
- | `<` _type_ (The generics parameter is bounded)
767
+ | `<` _type_ (The generics parameter has an upper bound)
768
+ | '>' _type_ (The generics parameter has a lower bound)
768
769
 
769
770
  _default-type_ ::= (No default type)
770
771
  | `=` _type_ (The generics parameter has default type)
@@ -777,6 +778,9 @@ _generics-unchecked_ ::= (Empty)
777
778
  | `unchecked` (Skips variance annotation validation)
778
779
  ```
779
780
 
781
+ A type parameter can have both upper and lower bounds, which can be specified in either order:
782
+ `[T < UpperBound > LowerBound]` or `[T > LowerBound < UpperBound]`.
783
+
780
784
  RBS allows class/module/interface/type alias definitions and methods to be generic.
781
785
 
782
786
  ```rbs
@@ -834,13 +838,38 @@ class PrettyPrint[T < _Output]
834
838
  end
835
839
  ```
836
840
 
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.
841
+ 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
842
 
839
843
  ```rbs
840
844
  type str_printer = PrettyPrint[String] # OK
841
845
  type int_printer = PrettyPrint[Integer] # Type error
842
846
  ```
843
847
 
848
+ If a type parameter has a lower bound, the type parameter must be instantiated with types that are a supertype of the lower bound.
849
+
850
+ ```rbs
851
+ class PrettyPrint[T > Numeric]
852
+ end
853
+
854
+ type obj_printer = PrettyPrint[Object] # OK
855
+ type int_printer = PrettyPrint[Integer] # Type error
856
+ ```
857
+
858
+ A type parameter can have both an upper and a lower bound, and these bounds can be specified in any order.
859
+
860
+ ```rbs
861
+ class FlexibleProcessor[T > Integer < Numeric]
862
+ # This class processes types T that are supertypes of Integer but also subtypes of Numeric.
863
+ # This includes Integer, Rational, Complex, Float, and Numeric itself.
864
+ def calculate: (T) -> T
865
+ end
866
+
867
+ type int_processor = FlexibleProcessor[Integer] # OK (Integer > Integer and Integer < Numeric)
868
+ type num_processor = FlexibleProcessor[Numeric] # OK (Numeric > Integer and Numeric < Numeric)
869
+ type obj_processor = FlexibleProcessor[Object] # Type error (Object is not < Numeric)
870
+ type str_processor = FlexibleProcessor[String] # Type error (String is not > Integer)
871
+ ```
872
+
844
873
  The generics type parameter of modules, classes, interfaces, or type aliases can have a default type.
845
874
 
846
875
  ```rbs
@@ -0,0 +1,21 @@
1
+ # Type Fingerprint of RBS Inline AST
2
+
3
+ Type fingerprint of RBS Inline AST is an object that can be used to detect if the RBS Inline AST is updated and the type checker should type check the whole codebase again.
4
+
5
+ 1. If the AST update is related to the type information, the fingerprint is changed -- adding new type, including new module, changing method type, etc. The type checker should type check the codebase with updated type information.
6
+ 2. If the AST updated is not related to the type information, the fingerprint keeps the last value -- changing the method implementation, adding a method call in the top level, adding white spaces and new lines, etc. The type checker can skip updating the type information, and type checking only the implementation of the file is sufficient.
7
+ 3. Documentation comments are considered type related information for now.
8
+
9
+ ## Type Fingerprint Calculation
10
+
11
+ The type fingerprint is calculated by converting AST nodes to standardized data structures that represent only the type-relevant information. Each AST class implements a `type_fingerprint` method that returns mainly arrays and strings.
12
+
13
+ We expect not using the values for something other than change detection. Compare old and new fingerprints, and we can detect the change between the RBS inline AST if the fingerprints are different.
14
+
15
+ The fingerprint methods are implemented across:
16
+
17
+ - `AST::Ruby::Annotations::*#type_fingerprint` - Returns `untyped` (arrays, strings, or nil)
18
+ - `AST::Ruby::Members::*#type_fingerprint` - Returns `untyped` (typically arrays)
19
+ - `AST::Ruby::Declarations::*#type_fingerprint` - Returns `untyped` (typically arrays)
20
+ - `InlineParser::Result#type_fingerprint` - Returns `untyped` (array of declaration fingerprints)
21
+
data/exe/rbs CHANGED
@@ -4,4 +4,4 @@ $LOAD_PATH << File.join(__dir__, "../lib")
4
4
  require "rbs"
5
5
  require "rbs/cli"
6
6
 
7
- RBS::CLI.new(stdout: STDOUT, stderr: STDERR).run(ARGV.dup)
7
+ exit RBS::CLI.new(stdout: STDOUT, stderr: STDERR).run(ARGV.dup)